Down-integrate internal changes to github.
diff --git a/csharp/src/Google.Protobuf.Test/testprotos.pb b/csharp/src/Google.Protobuf.Test/testprotos.pb
index 7affb95..cf1a89a 100644
--- a/csharp/src/Google.Protobuf.Test/testprotos.pb
+++ b/csharp/src/Google.Protobuf.Test/testprotos.pb
Binary files differ
diff --git a/java/core/src/main/java/com/google/protobuf/Descriptors.java b/java/core/src/main/java/com/google/protobuf/Descriptors.java
index 8f75192..6f8696e 100644
--- a/java/core/src/main/java/com/google/protobuf/Descriptors.java
+++ b/java/core/src/main/java/com/google/protobuf/Descriptors.java
@@ -32,7 +32,22 @@
 
 import static com.google.protobuf.Internal.checkNotNull;
 
-import com.google.protobuf.DescriptorProtos.*;
+import com.google.protobuf.DescriptorProtos.DescriptorProto;
+import com.google.protobuf.DescriptorProtos.EnumDescriptorProto;
+import com.google.protobuf.DescriptorProtos.EnumOptions;
+import com.google.protobuf.DescriptorProtos.EnumValueDescriptorProto;
+import com.google.protobuf.DescriptorProtos.EnumValueOptions;
+import com.google.protobuf.DescriptorProtos.FieldDescriptorProto;
+import com.google.protobuf.DescriptorProtos.FieldOptions;
+import com.google.protobuf.DescriptorProtos.FileDescriptorProto;
+import com.google.protobuf.DescriptorProtos.FileOptions;
+import com.google.protobuf.DescriptorProtos.MessageOptions;
+import com.google.protobuf.DescriptorProtos.MethodDescriptorProto;
+import com.google.protobuf.DescriptorProtos.MethodOptions;
+import com.google.protobuf.DescriptorProtos.OneofDescriptorProto;
+import com.google.protobuf.DescriptorProtos.OneofOptions;
+import com.google.protobuf.DescriptorProtos.ServiceDescriptorProto;
+import com.google.protobuf.DescriptorProtos.ServiceOptions;
 import com.google.protobuf.Descriptors.FileDescriptor.Syntax;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
@@ -1211,7 +1226,7 @@
       StringBuilder result = new StringBuilder(name.length());
       boolean isNextUpperCase = false;
       for (int i = 0; i < name.length(); i++) {
-        Character ch = name.charAt(i);
+        char ch = name.charAt(i);
         if (ch == '_') {
           isNextUpperCase = true;
         } else if (isNextUpperCase) {
diff --git a/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java b/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java
index 53af544..cacfa05 100644
--- a/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java
+++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java
@@ -1681,6 +1681,15 @@
       }
     }
 
+    @Override
+    public Message.Builder newBuilderForField(final FieldDescriptor field) {
+      if (field.isExtension()) {
+        return DynamicMessage.newBuilder(field.getMessageType());
+      } else {
+        return super.newBuilderForField(field);
+      }
+    }
+
     protected final void mergeExtensionFields(final ExtendableMessage other) {
       ensureExtensionsIsMutable();
       extensions.mergeFrom(other.extensions);
diff --git a/java/core/src/main/java/com/google/protobuf/TextFormat.java b/java/core/src/main/java/com/google/protobuf/TextFormat.java
index aaea097..f00c812 100644
--- a/java/core/src/main/java/com/google/protobuf/TextFormat.java
+++ b/java/core/src/main/java/com/google/protobuf/TextFormat.java
@@ -1127,7 +1127,6 @@
     PARSER.merge(input, builder);
   }
 
-
   /**
    * Parse a text-format message from {@code input}.
    *
@@ -1167,7 +1166,6 @@
     PARSER.merge(input, extensionRegistry, builder);
   }
 
-
   /**
    * Parse a text-format message from {@code input}. Extensions will be recognized if they are
    * registered in {@code extensionRegistry}.
@@ -1187,7 +1185,6 @@
   }
 
 
-
   /**
    * Parser for text-format proto2 instances. This class is thread-safe. The implementation largely
    * follows google/protobuf/text_format.cc.
@@ -1217,36 +1214,6 @@
       FORBID_SINGULAR_OVERWRITES
     }
 
-    /**
-     * Determines how to deal with repeated values for singular Message fields. For example,
-     * given a field "foo" containing subfields "baz" and "qux":
-     *
-     * <ul>
-     *   <li>"foo { baz: 1 } foo { baz: 2 }", or
-     *   <li>"foo { baz: 1 } foo { qux: 2 }"
-     * </ul>
-     */
-    public enum MergingStyle {
-      /**
-       * Merge the values in standard protobuf fashion:
-       *
-       * <ul>
-       *   <li>"foo { baz: 2 }" and
-       *   <li>"foo { baz: 1, qux: 2 }", respectively.
-       * </ul>
-       */
-      RECURSIVE,
-      /**
-       * Later values overwrite ("clobber") previous values:
-       *
-       * <ul>
-       *   <li>"foo { baz: 2 }" and
-       *   <li>"foo { qux: 2 }", respectively.
-       * </ul>
-       */
-      NON_RECURSIVE
-    }
-
     private final boolean allowUnknownFields;
     private final boolean allowUnknownEnumValues;
     private final boolean allowUnknownExtensions;
@@ -1349,7 +1316,6 @@
     }
 
 
-
     private static final int BUFFER_SIZE = 4096;
 
     // TODO(chrisn): See if working around java.io.Reader#read(CharBuffer)
@@ -1435,20 +1401,18 @@
       List<UnknownField> unknownFields = new ArrayList<UnknownField>();
 
       while (!tokenizer.atEnd()) {
-        mergeField(tokenizer, extensionRegistry, target, MergingStyle.RECURSIVE, unknownFields);
+        mergeField(tokenizer, extensionRegistry, target, unknownFields);
       }
 
       checkUnknownFields(unknownFields);
     }
 
 
-
     /** Parse a single field from {@code tokenizer} and merge it into {@code builder}. */
     private void mergeField(
         final Tokenizer tokenizer,
         final ExtensionRegistry extensionRegistry,
         final MessageReflection.MergeTarget target,
-        final MergingStyle mergingStyle,
         List<UnknownField> unknownFields)
         throws ParseException {
       mergeField(
@@ -1456,7 +1420,6 @@
           extensionRegistry,
           target,
           parseInfoTreeBuilder,
-          mergingStyle,
           unknownFields);
     }
 
@@ -1466,7 +1429,6 @@
         final ExtensionRegistry extensionRegistry,
         final MessageReflection.MergeTarget target,
         TextFormatParseInfoTree.Builder parseTreeBuilder,
-        final MergingStyle mergingStyle,
         List<UnknownField> unknownFields)
         throws ParseException {
       FieldDescriptor field = null;
@@ -1573,7 +1535,6 @@
               field,
               extension,
               childParseTreeBuilder,
-              mergingStyle,
               unknownFields);
         } else {
           consumeFieldValues(
@@ -1583,7 +1544,6 @@
               field,
               extension,
               parseTreeBuilder,
-              mergingStyle,
               unknownFields);
         }
       } else {
@@ -1595,7 +1555,6 @@
             field,
             extension,
             parseTreeBuilder,
-            mergingStyle,
             unknownFields);
       }
 
@@ -1620,7 +1579,6 @@
         final FieldDescriptor field,
         final ExtensionRegistry.ExtensionInfo extension,
         final TextFormatParseInfoTree.Builder parseTreeBuilder,
-        final MergingStyle mergingStyle,
         List<UnknownField> unknownFields)
         throws ParseException {
       // Support specifying repeated field values as a comma-separated list.
@@ -1635,7 +1593,6 @@
                 field,
                 extension,
                 parseTreeBuilder,
-                mergingStyle,
                 unknownFields);
             if (tokenizer.tryConsume("]")) {
               // End of list.
@@ -1652,7 +1609,6 @@
             field,
             extension,
             parseTreeBuilder,
-            mergingStyle,
             unknownFields);
       }
     }
@@ -1665,7 +1621,6 @@
         final FieldDescriptor field,
         final ExtensionRegistry.ExtensionInfo extension,
         final TextFormatParseInfoTree.Builder parseTreeBuilder,
-        final MergingStyle mergingStyle,
         List<UnknownField> unknownFields)
         throws ParseException {
       if (singularOverwritePolicy == SingularOverwritePolicy.FORBID_SINGULAR_OVERWRITES
@@ -1698,18 +1653,9 @@
           endToken = "}";
         }
 
-        final MessageReflection.MergeTarget subField;
         Message defaultInstance = (extension == null) ? null : extension.defaultInstance;
-        switch (mergingStyle) {
-          case RECURSIVE:
-            subField = target.newMergeTargetForField(field, defaultInstance);
-            break;
-          case NON_RECURSIVE:
-            subField = target.newEmptyTargetForField(field, defaultInstance);
-            break;
-          default:
-            throw new AssertionError();
-        }
+        MessageReflection.MergeTarget subField =
+            target.newMergeTargetForField(field, defaultInstance);
 
         while (!tokenizer.tryConsume(endToken)) {
           if (tokenizer.atEnd()) {
@@ -1720,7 +1666,6 @@
               extensionRegistry,
               subField,
               parseTreeBuilder,
-              mergingStyle,
               unknownFields);
         }
 
diff --git a/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java b/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java
index 17df54a..ddd3585 100644
--- a/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java
+++ b/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java
@@ -391,14 +391,12 @@
   }
 
   /**
-   * Gets the field with the given name within the class, or {@code null} if not found. If found,
-   * the field is made accessible.
+   * Gets the field with the given name within the class, or {@code null} if not found.
    */
   private static Field field(Class<?> clazz, String fieldName) {
     Field field;
     try {
       field = clazz.getDeclaredField(fieldName);
-      field.setAccessible(true);
     } catch (Throwable t) {
       // Failed to access the fields.
       field = null;
diff --git a/java/core/src/main/java/com/google/protobuf/Utf8.java b/java/core/src/main/java/com/google/protobuf/Utf8.java
index 4512bf9..9fe1383 100644
--- a/java/core/src/main/java/com/google/protobuf/Utf8.java
+++ b/java/core/src/main/java/com/google/protobuf/Utf8.java
@@ -1104,7 +1104,8 @@
 
     private static int partialIsValidUtf8NonAscii(byte[] bytes, int index, int limit) {
       for (; ; ) {
-        int byte1, byte2;
+        int byte1;
+        int byte2;
 
         // Optimize for interior runs of ASCII bytes.
         do {
diff --git a/java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java b/java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java
index 0514241..fe37ea8 100644
--- a/java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java
+++ b/java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java
@@ -33,8 +33,10 @@
 import com.google.protobuf.Descriptors.EnumDescriptor;
 import com.google.protobuf.Descriptors.FieldDescriptor;
 import com.google.protobuf.Descriptors.OneofDescriptor;
+import protobuf_unittest.UnittestProto;
 import protobuf_unittest.UnittestProto.TestAllExtensions;
 import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage;
 import protobuf_unittest.UnittestProto.TestEmptyMessage;
 import protobuf_unittest.UnittestProto.TestPackedTypes;
 import java.util.Arrays;
@@ -223,6 +225,17 @@
     packedReflectionTester.assertPackedFieldsSetViaReflection(message3);
   }
 
+  public void testGetBuilderForExtensionField() {
+    DynamicMessage.Builder builder = DynamicMessage.newBuilder(TestAllExtensions.getDescriptor());
+    Message.Builder fieldBuilder =
+        builder.newBuilderForField(UnittestProto.optionalNestedMessageExtension.getDescriptor());
+    final int expected = 7432;
+    FieldDescriptor field =
+        NestedMessage.getDescriptor().findFieldByNumber(NestedMessage.BB_FIELD_NUMBER);
+    fieldBuilder.setField(field, expected);
+    assertEquals(expected, fieldBuilder.build().getField(field));
+  }
+
   public void testDynamicMessageCopy() throws Exception {
     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
     TestUtil.setAllFields(builder);
diff --git a/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java b/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java
index 13457bc..2d025fe 100644
--- a/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java
+++ b/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java
@@ -578,6 +578,29 @@
     TestUtil.assertAllExtensionsSet(message);
   }
 
+  public void testGetBuilderForExtensionField() {
+    TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+    Message.Builder fieldBuilder =
+        builder.newBuilderForField(UnittestProto.optionalNestedMessageExtension.getDescriptor());
+    final int expected = 7432;
+    FieldDescriptor field =
+        NestedMessage.getDescriptor().findFieldByNumber(NestedMessage.BB_FIELD_NUMBER);
+    fieldBuilder.setField(field, expected);
+    assertEquals(expected, fieldBuilder.build().getField(field));
+  }
+
+
+  public void testGetBuilderForNonMessageExtensionField() {
+    TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+    try {
+      // This should throw an exception because the extension field is not a message.
+      builder.newBuilderForField(UnittestProto.optionalInt32Extension.getDescriptor());
+      fail("Exception was not thrown");
+    } catch (UnsupportedOperationException e) {
+      // This exception is expected.
+    }
+  }
+
   public void testExtensionRepeatedSetters() throws Exception {
     TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
     TestUtil.setAllExtensions(builder);
diff --git a/java/core/src/test/proto/com/google/protobuf/map_lite_test.proto b/java/core/src/test/proto/com/google/protobuf/map_lite_test.proto
index 7324653..240600f 100644
--- a/java/core/src/test/proto/com/google/protobuf/map_lite_test.proto
+++ b/java/core/src/test/proto/com/google/protobuf/map_lite_test.proto
@@ -30,10 +30,9 @@
 
 syntax = "proto3";
 
-package map_lite_test;
+package map_test;
 
-option optimize_for = LITE_RUNTIME;
-option java_package = "map_lite_test";
+option java_package = "map_test";
 option java_outer_classname = "MapTestProto";
 
 message TestMap {
diff --git a/java/util/src/main/java/com/google/protobuf/util/Durations.java b/java/util/src/main/java/com/google/protobuf/util/Durations.java
index 7836ccf..0ecac25 100644
--- a/java/util/src/main/java/com/google/protobuf/util/Durations.java
+++ b/java/util/src/main/java/com/google/protobuf/util/Durations.java
@@ -42,6 +42,7 @@
 import static com.google.protobuf.util.Timestamps.NANOS_PER_MILLISECOND;
 import static com.google.protobuf.util.Timestamps.NANOS_PER_SECOND;
 
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.protobuf.Duration;
 import java.text.ParseException;
 import java.util.Comparator;
@@ -91,8 +92,8 @@
   }
 
   /**
-   * Compares two durations. The value returned is identical to what would be returned by:
-   * {@code Durations.comparator().compare(x, y)}.
+   * Compares two durations. The value returned is identical to what would be returned by: {@code
+   * Durations.comparator().compare(x, y)}.
    *
    * @return the value {@code 0} if {@code x == y}; a value less than {@code 0} if {@code x < y};
    *     and a value greater than {@code 0} if {@code x > y}
@@ -151,6 +152,7 @@
    * @throws IllegalArgumentException if {@code duration} is negative or invalid
    * @throws NullPointerException if {@code duration} is {@code null}
    */
+  @CanIgnoreReturnValue
   public static Duration checkNotNegative(Duration duration) {
     checkValid(duration);
     checkArgument(!isNegative(duration), "duration (%s) must not be negative", toString(duration));
@@ -163,6 +165,7 @@
    * @throws IllegalArgumentException if {@code duration} is negative, {@code ZERO}, or invalid
    * @throws NullPointerException if {@code duration} is {@code null}
    */
+  @CanIgnoreReturnValue
   public static Duration checkPositive(Duration duration) {
     checkValid(duration);
     checkArgument(
@@ -173,20 +176,33 @@
   }
 
   /** Throws an {@link IllegalArgumentException} if the given {@link Duration} is not valid. */
+  @CanIgnoreReturnValue
   public static Duration checkValid(Duration duration) {
     long seconds = duration.getSeconds();
     int nanos = duration.getNanos();
     if (!isValid(seconds, nanos)) {
-        throw new IllegalArgumentException(String.format(
-            "Duration is not valid. See proto definition for valid values. "
-            + "Seconds (%s) must be in range [-315,576,000,000, +315,576,000,000]. "
-            + "Nanos (%s) must be in range [-999,999,999, +999,999,999]. "
-            + "Nanos must have the same sign as seconds", seconds, nanos));
+      throw new IllegalArgumentException(
+          String.format(
+              "Duration is not valid. See proto definition for valid values. "
+                  + "Seconds (%s) must be in range [-315,576,000,000, +315,576,000,000]. "
+                  + "Nanos (%s) must be in range [-999,999,999, +999,999,999]. "
+                  + "Nanos must have the same sign as seconds",
+              seconds, nanos));
     }
     return duration;
   }
 
   /**
+   * Builds the given builder and throws an {@link IllegalArgumentException} if it is not valid. See
+   * {@link #checkValid(Duration}).
+   *
+   * @return A valid, built {@link Duration}.
+   */
+  public static Duration checkValid(Duration.Builder durationBuilder) {
+    return checkValid(durationBuilder.build());
+  }
+
+  /**
    * Convert Duration to string format. The string format will contains 3, 6, or 9 fractional digits
    * depending on the precision required to represent the exact Duration value. For example: "1s",
    * "1.010s", "1.000000100s", "-3.100s" The range that can be represented by Duration is from
diff --git a/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java b/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java
index 86f56ad..d07731d 100644
--- a/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java
+++ b/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java
@@ -30,6 +30,7 @@
 
 package com.google.protobuf.util;
 
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.protobuf.Descriptors.Descriptor;
 import com.google.protobuf.Descriptors.FieldDescriptor;
 import com.google.protobuf.FieldMask;
@@ -88,15 +89,14 @@
   }
 
   /**
-   * Adds a field path to the tree. In a FieldMask, every field path matches the
-   * specified field as well as all its sub-fields. For example, a field path
-   * "foo.bar" matches field "foo.bar" and also "foo.bar.baz", etc. When adding
-   * a field path to the tree, redundant sub-paths will be removed. That is,
-   * after adding "foo.bar" to the tree, "foo.bar.baz" will be removed if it
-   * exists, which will turn the tree node for "foo.bar" to a leaf node.
-   * Likewise, if the field path to add is a sub-path of an existing leaf node,
-   * nothing will be changed in the tree.
+   * Adds a field path to the tree. In a FieldMask, every field path matches the specified field as
+   * well as all its sub-fields. For example, a field path "foo.bar" matches field "foo.bar" and
+   * also "foo.bar.baz", etc. When adding a field path to the tree, redundant sub-paths will be
+   * removed. That is, after adding "foo.bar" to the tree, "foo.bar.baz" will be removed if it
+   * exists, which will turn the tree node for "foo.bar" to a leaf node. Likewise, if the field path
+   * to add is a sub-path of an existing leaf node, nothing will be changed in the tree.
    */
+  @CanIgnoreReturnValue
   FieldMaskTree addFieldPath(String path) {
     String[] parts = path.split(FIELD_PATH_SEPARATOR_REGEX);
     if (parts.length == 0) {
@@ -125,9 +125,8 @@
     return this;
   }
 
-  /**
-   * Merges all field paths in a FieldMask into this tree.
-   */
+  /** Merges all field paths in a FieldMask into this tree. */
+  @CanIgnoreReturnValue
   FieldMaskTree mergeFromFieldMask(FieldMask mask) {
     for (String path : mask.getPathsList()) {
       addFieldPath(path);
diff --git a/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java b/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java
index aedc5ea..6af1493 100644
--- a/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java
+++ b/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java
@@ -36,12 +36,12 @@
 import com.google.common.base.Joiner;
 import com.google.common.base.Splitter;
 import com.google.common.primitives.Ints;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.protobuf.Descriptors.Descriptor;
 import com.google.protobuf.Descriptors.FieldDescriptor;
 import com.google.protobuf.FieldMask;
 import com.google.protobuf.Internal;
 import com.google.protobuf.Message;
-
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -277,9 +277,7 @@
 
     /**
      * Whether to replace message fields (i.e., discard existing content in
-     * destination message fields) when merging.
-     * Default behavior is to merge the source message field into the
-     * destination message field.
+     * destination message fields).
      */
     public boolean replaceMessageFields() {
       return replaceMessageFields;
@@ -287,9 +285,7 @@
 
     /**
      * Whether to replace repeated fields (i.e., discard existing content in
-     * destination repeated fields) when merging.
-     * Default behavior is to append elements from source repeated field to the
-     * destination repeated field.
+     * destination repeated fields).
      */
     public boolean replaceRepeatedFields() {
       return replaceRepeatedFields;
@@ -297,30 +293,51 @@
 
     /**
      * Whether to replace primitive (non-repeated and non-message) fields in
-     * destination message fields with the source primitive fields (i.e., if the
-     * field is set in the source, the value is copied to the
-     * destination; if the field is unset in the source, the field is cleared
-     * from the destination) when merging.
-     *
-     * <p>Default behavior is to always set the value of the source primitive
-     * field to the destination primitive field, and if the source field is
-     * unset, the default value of the source field is copied to the
-     * destination.
+     * destination message fields with the source primitive fields (i.e., clear
+     * destination field if source field is not set).
      */
     public boolean replacePrimitiveFields() {
       return replacePrimitiveFields;
     }
 
+    /**
+     * Specify whether to replace message fields. Defaults to false.
+     *
+     * <p>If true, discard existing content in destination message fields when merging.
+     *
+     * <p>If false, merge the source message field into the destination message field.
+     */
+    @CanIgnoreReturnValue
     public MergeOptions setReplaceMessageFields(boolean value) {
       replaceMessageFields = value;
       return this;
     }
 
+    /**
+     * Specify whether to replace repeated fields. Defaults to false.
+     *
+     * <p>If true, discard existing content in destination repeated fields) when merging.
+     *
+     * <p>If false, append elements from source repeated field to the destination repeated field.
+     */
+    @CanIgnoreReturnValue
     public MergeOptions setReplaceRepeatedFields(boolean value) {
       replaceRepeatedFields = value;
       return this;
     }
 
+    /**
+     * Specify whether to replace primitive (non-repeated and non-message) fields in destination
+     * message fields with the source primitive fields. Defaults to false.
+     *
+     * <p>If true, set the value of the destination primitive field to the source primitive field if
+     * the source field is set, but clear the destination field otherwise.
+     *
+     * <p>If false, always set the value of the destination primitive field to the source primitive
+     * field, and if the source field is unset, the default value of the source field is copied to
+     * the destination.
+     */
+    @CanIgnoreReturnValue
     public MergeOptions setReplacePrimitiveFields(boolean value) {
       replacePrimitiveFields = value;
       return this;
diff --git a/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java b/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java
index 3301e02..77c837e 100644
--- a/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java
+++ b/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java
@@ -32,6 +32,7 @@
 
 import com.google.common.base.Preconditions;
 import com.google.common.io.BaseEncoding;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
 import com.google.gson.JsonArray;
@@ -226,7 +227,7 @@
       return new Printer(
           registry,
           false,
-          fieldsToAlwaysOutput,
+          Collections.unmodifiableSet(new HashSet<>(fieldsToAlwaysOutput)),
           preservingProtoFieldNames,
           omittingInsignificantWhitespace,
           printingEnumsAsInts,
@@ -467,9 +468,10 @@
       private Builder() {}
 
       /**
-       * Adds a message type and all types defined in the same .proto file as
-       * well as all transitively imported .proto files to this {@link Builder}.
+       * Adds a message type and all types defined in the same .proto file as well as all
+       * transitively imported .proto files to this {@link Builder}.
        */
+      @CanIgnoreReturnValue
       public Builder add(Descriptor messageType) {
         if (types == null) {
           throw new IllegalStateException("A TypeRegistry.Builer can only be used once.");
@@ -479,9 +481,10 @@
       }
 
       /**
-       * Adds message types and all types defined in the same .proto file as
-       * well as all transitively imported .proto files to this {@link Builder}.
+       * Adds message types and all types defined in the same .proto file as well as all
+       * transitively imported .proto files to this {@link Builder}.
        */
+      @CanIgnoreReturnValue
       public Builder add(Iterable<Descriptor> messageTypes) {
         if (types == null) {
           throw new IllegalStateException("A TypeRegistry.Builder can only be used once.");
diff --git a/java/util/src/main/java/com/google/protobuf/util/Timestamps.java b/java/util/src/main/java/com/google/protobuf/util/Timestamps.java
index 83f3a9d..96608e5 100644
--- a/java/util/src/main/java/com/google/protobuf/util/Timestamps.java
+++ b/java/util/src/main/java/com/google/protobuf/util/Timestamps.java
@@ -36,6 +36,7 @@
 import static com.google.common.math.LongMath.checkedMultiply;
 import static com.google.common.math.LongMath.checkedSubtract;
 
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.protobuf.Duration;
 import com.google.protobuf.Timestamp;
 import java.text.ParseException;
@@ -119,8 +120,8 @@
   }
 
   /**
-   * Compares two timestamps. The value returned is identical to what would be returned by:
-   * {@code Timestamps.comparator().compare(x, y)}.
+   * Compares two timestamps. The value returned is identical to what would be returned by: {@code
+   * Timestamps.comparator().compare(x, y)}.
    *
    * @return the value {@code 0} if {@code x == y}; a value less than {@code 0} if {@code x < y};
    *     and a value greater than {@code 0} if {@code x > y}
@@ -162,19 +163,32 @@
   }
 
   /** Throws an {@link IllegalArgumentException} if the given {@link Timestamp} is not valid. */
+  @CanIgnoreReturnValue
   public static Timestamp checkValid(Timestamp timestamp) {
     long seconds = timestamp.getSeconds();
     int nanos = timestamp.getNanos();
     if (!isValid(seconds, nanos)) {
-        throw new IllegalArgumentException(String.format(
-            "Timestamp is not valid. See proto definition for valid values. "
-            + "Seconds (%s) must be in range [-62,135,596,800, +253,402,300,799]. "
-            + "Nanos (%s) must be in range [0, +999,999,999].", seconds, nanos));
+      throw new IllegalArgumentException(
+          String.format(
+              "Timestamp is not valid. See proto definition for valid values. "
+                  + "Seconds (%s) must be in range [-62,135,596,800, +253,402,300,799]. "
+                  + "Nanos (%s) must be in range [0, +999,999,999].",
+              seconds, nanos));
     }
     return timestamp;
   }
 
   /**
+   * Builds the given builder and throws an {@link IllegalArgumentException} if it is not valid. See
+   * {@link #checkValid(Timestamp}).
+   *
+   * @return A valid, built {@link Timestamp}.
+   */
+  public static Timestamp checkValid(Timestamp.Builder timestampBuilder) {
+    return checkValid(timestampBuilder.build());
+  }
+
+  /**
    * Convert Timestamp to RFC 3339 date string format. The output will always be Z-normalized and
    * uses 3, 6 or 9 fractional digits as required to represent the exact value. Note that Timestamp
    * can only represent time from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. See
diff --git a/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java b/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java
index 6095068..9805737 100644
--- a/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java
+++ b/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java
@@ -49,19 +49,20 @@
 import com.google.protobuf.UInt64Value;
 import com.google.protobuf.Value;
 import com.google.protobuf.util.JsonFormat.TypeRegistry;
-import com.google.protobuf.util.JsonTestProto.TestAllTypes;
-import com.google.protobuf.util.JsonTestProto.TestAllTypes.NestedEnum;
-import com.google.protobuf.util.JsonTestProto.TestAllTypes.NestedMessage;
-import com.google.protobuf.util.JsonTestProto.TestAny;
-import com.google.protobuf.util.JsonTestProto.TestCustomJsonName;
-import com.google.protobuf.util.JsonTestProto.TestDuration;
-import com.google.protobuf.util.JsonTestProto.TestFieldMask;
-import com.google.protobuf.util.JsonTestProto.TestMap;
-import com.google.protobuf.util.JsonTestProto.TestOneof;
-import com.google.protobuf.util.JsonTestProto.TestRecursive;
-import com.google.protobuf.util.JsonTestProto.TestStruct;
-import com.google.protobuf.util.JsonTestProto.TestTimestamp;
-import com.google.protobuf.util.JsonTestProto.TestWrappers;
+import com.google.protobuf.util.proto.JsonTestProto.TestAllTypes;
+import com.google.protobuf.util.proto.JsonTestProto.TestAllTypes.AliasedEnum;
+import com.google.protobuf.util.proto.JsonTestProto.TestAllTypes.NestedEnum;
+import com.google.protobuf.util.proto.JsonTestProto.TestAllTypes.NestedMessage;
+import com.google.protobuf.util.proto.JsonTestProto.TestAny;
+import com.google.protobuf.util.proto.JsonTestProto.TestCustomJsonName;
+import com.google.protobuf.util.proto.JsonTestProto.TestDuration;
+import com.google.protobuf.util.proto.JsonTestProto.TestFieldMask;
+import com.google.protobuf.util.proto.JsonTestProto.TestMap;
+import com.google.protobuf.util.proto.JsonTestProto.TestOneof;
+import com.google.protobuf.util.proto.JsonTestProto.TestRecursive;
+import com.google.protobuf.util.proto.JsonTestProto.TestStruct;
+import com.google.protobuf.util.proto.JsonTestProto.TestTimestamp;
+import com.google.protobuf.util.proto.JsonTestProto.TestWrappers;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -676,7 +677,7 @@
               + "}",
           builder);
       fail();
-        
+
     } catch (InvalidProtocolBufferException e) {
       // Exception expected.
     }
@@ -1159,8 +1160,8 @@
   }
 
   public void testParserAcceptBase64Variants() throws Exception {
-    assertAccepts("optionalBytes", "AQI");  // No padding
-    assertAccepts("optionalBytes", "-_w");  // base64Url, no padding
+    assertAccepts("optionalBytes", "AQI"); // No padding
+    assertAccepts("optionalBytes", "-_w"); // base64Url, no padding
   }
 
   public void testParserRejectInvalidEnumValue() throws Exception {
@@ -1197,6 +1198,23 @@
     assertEquals(0, builder.getOptionalNestedEnumValue());
   }
 
+  public void testParserSupportAliasEnums() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    String json = "{\n" + "  \"optionalAliasedEnum\": \"QUX\"\n" + "}";
+    JsonFormat.parser().merge(json, builder);
+    assertEquals(AliasedEnum.ALIAS_BAZ, builder.getOptionalAliasedEnum());
+
+    builder = TestAllTypes.newBuilder();
+    json = "{\n" + "  \"optionalAliasedEnum\": \"qux\"\n" + "}";
+    JsonFormat.parser().merge(json, builder);
+    assertEquals(AliasedEnum.ALIAS_BAZ, builder.getOptionalAliasedEnum());
+
+    builder = TestAllTypes.newBuilder();
+    json = "{\n" + "  \"optionalAliasedEnum\": \"bAz\"\n" + "}";
+    JsonFormat.parser().merge(json, builder);
+    assertEquals(AliasedEnum.ALIAS_BAZ, builder.getOptionalAliasedEnum());
+  }
+
   public void testUnknownEnumMap() throws Exception {
     TestMap.Builder builder = TestMap.newBuilder();
     JsonFormat.parser()
@@ -1280,7 +1298,8 @@
             + "  \"repeatedString\": [],\n"
             + "  \"repeatedBytes\": [],\n"
             + "  \"repeatedNestedMessage\": [],\n"
-            + "  \"repeatedNestedEnum\": []\n"
+            + "  \"repeatedNestedEnum\": [],\n"
+            + "  \"optionalAliasedEnum\": \"ALIAS_FOO\"\n"
             + "}",
         JsonFormat.printer().includingDefaultValueFields().print(message));
 
@@ -1644,11 +1663,11 @@
     mapBuilder.putStringToInt32Map("\ud834\udd20", 3); // utf-8 F0 9D 84 A0
     mapBuilder.putStringToInt32Map("foo", 99);
     mapBuilder.putStringToInt32Map("xxx", 123);
-    mapBuilder.putStringToInt32Map("\u20ac", 1);  // utf-8 E2 82 AC
+    mapBuilder.putStringToInt32Map("\u20ac", 1); // utf-8 E2 82 AC
     mapBuilder.putStringToInt32Map("abc", 20);
     mapBuilder.putStringToInt32Map("19", 19);
     mapBuilder.putStringToInt32Map("8", 8);
-    mapBuilder.putStringToInt32Map("\ufb00", 2);  // utf-8 EF AC 80
+    mapBuilder.putStringToInt32Map("\ufb00", 2); // utf-8 EF AC 80
     mapBuilder.putInt32ToInt32Map(3, 3);
     mapBuilder.putInt32ToInt32Map(10, 10);
     mapBuilder.putInt32ToInt32Map(5, 5);
diff --git a/java/util/src/test/proto/com/google/protobuf/util/json_test.proto b/java/util/src/test/proto/com/google/protobuf/util/json_test.proto
index d1248cf..26d0624 100644
--- a/java/util/src/test/proto/com/google/protobuf/util/json_test.proto
+++ b/java/util/src/test/proto/com/google/protobuf/util/json_test.proto
@@ -32,7 +32,7 @@
 
 package json_test;
 
-option java_package = "com.google.protobuf.util";
+option java_package = "com.google.protobuf.util.proto";
 option java_outer_classname = "JsonTestProto";
 
 import "google/protobuf/any.proto";
@@ -48,6 +48,17 @@
     BAR = 1;
     BAZ = 2;
   }
+
+  enum AliasedEnum {
+    option allow_alias = true;
+
+    ALIAS_FOO = 0;
+    ALIAS_BAR = 1;
+    ALIAS_BAZ = 2;
+    QUX = 2;
+    qux = 2;
+    bAz = 2;
+  }
   message NestedMessage {
     int32 value = 1;
   }
@@ -69,6 +80,7 @@
   bytes optional_bytes = 15;
   NestedMessage optional_nested_message = 18;
   NestedEnum optional_nested_enum = 21;
+  AliasedEnum optional_aliased_enum = 52;
 
   // Repeated
   repeated int32 repeated_int32 = 31;
diff --git a/js/binary/constants.js b/js/binary/constants.js
index 5c53a36..f8b13a8 100644
--- a/js/binary/constants.js
+++ b/js/binary/constants.js
@@ -55,7 +55,7 @@
 goog.forwardDeclare('jspb.BinaryReader');
 goog.forwardDeclare('jspb.BinaryWriter');
 goog.forwardDeclare('jspb.Message');
-goog.forwardDeclare('jsproto.BinaryExtension');
+goog.forwardDeclare('jsprotolib.BinaryExtension');
 
 
 
@@ -122,7 +122,7 @@
              !Uint8Array|
              !jspb.ConstBinaryMessage|
              !jspb.BinaryMessage|
-             !jsproto.BinaryExtension}
+             !jsprotolib.BinaryExtension}
  */
 jspb.AnyFieldType;
 
diff --git a/js/binary/decoder.js b/js/binary/decoder.js
index e33bf1b..d47c20e 100644
--- a/js/binary/decoder.js
+++ b/js/binary/decoder.js
@@ -63,7 +63,7 @@
  * @struct
  */
 jspb.BinaryIterator = function(opt_decoder, opt_next, opt_elements) {
-  /** @private {jspb.BinaryDecoder} */
+  /** @private {?jspb.BinaryDecoder} */
   this.decoder_ = null;
 
   /**
diff --git a/js/binary/reader.js b/js/binary/reader.js
index 731587c..91c7b6d 100644
--- a/js/binary/reader.js
+++ b/js/binary/reader.js
@@ -97,7 +97,7 @@
 
   /**
    * User-defined reader callbacks.
-   * @private {Object<string, function(!jspb.BinaryReader):*>}
+   * @private {?Object<string, function(!jspb.BinaryReader):*>}
    */
   this.readCallbacks_ = null;
 };
diff --git a/js/message_test.js b/js/message_test.js
index c237d06..7d2cdba 100644
--- a/js/message_test.js
+++ b/js/message_test.js
@@ -149,58 +149,60 @@
   });
 
   it('testComplexConversion', function() {
-    var data1 = ['a',,, [, 11], [[, 22], [, 33]],, ['s1', 's2'],, 1];
-    var data2 = ['a',,, [, 11], [[, 22], [, 33]],, ['s1', 's2'],, 1];
+    var data1 = ['a', , , [, 11], [[, 22], [, 33]], , ['s1', 's2'], , 1];
+    var data2 = ['a', , , [, 11], [[, 22], [, 33]], , ['s1', 's2'], , 1];
     var foo = new proto.jspb.test.Complex(data1);
     var bar = new proto.jspb.test.Complex(data2);
     var result = foo.toObject();
-    assertObjectEquals({
-      aString: 'a',
-      anOutOfOrderBool: 1,
-      aNestedMessage: {
-        anInt: 11
-      },
-      aRepeatedMessageList: [{anInt: 22}, {anInt: 33}],
-      aRepeatedStringList: ['s1', 's2']
-    }, result);
+    assertObjectEquals(
+        {
+          aString: 'a',
+          anOutOfOrderBool: 1,
+          aNestedMessage: {anInt: 11},
+          aRepeatedMessageList: [{anInt: 22}, {anInt: 33}],
+          aRepeatedStringList: ['s1', 's2']
+        },
+        result);
 
     // Now test with the jspb instances included.
     result = foo.toObject(true /* opt_includeInstance */);
-    assertObjectEquals({
-      aString: 'a',
-      anOutOfOrderBool: 1,
-      aNestedMessage: {
-        anInt: 11,
-        $jspbMessageInstance: foo.getANestedMessage()
-      },
-      aRepeatedMessageList: [
-        {anInt: 22, $jspbMessageInstance: foo.getARepeatedMessageList()[0]},
-        {anInt: 33, $jspbMessageInstance: foo.getARepeatedMessageList()[1]}
-      ],
-      aRepeatedStringList: ['s1', 's2'],
-      $jspbMessageInstance: foo
-    }, result);
+    assertObjectEquals(
+        {
+          aString: 'a',
+          anOutOfOrderBool: 1,
+          aNestedMessage:
+              {anInt: 11, $jspbMessageInstance: foo.getANestedMessage()},
+          aRepeatedMessageList: [
+            {anInt: 22, $jspbMessageInstance: foo.getARepeatedMessageList()[0]},
+            {anInt: 33, $jspbMessageInstance: foo.getARepeatedMessageList()[1]}
+          ],
+          aRepeatedStringList: ['s1', 's2'],
+          $jspbMessageInstance: foo
+        },
+        result);
 
   });
 
   it('testMissingFields', function() {
     var foo = new proto.jspb.test.Complex([
-        undefined, undefined, undefined, [],
-        undefined, undefined, undefined, undefined]);
+      undefined, undefined, undefined, [], undefined, undefined, undefined,
+      undefined
+    ]);
     var bar = new proto.jspb.test.Complex([
-        undefined, undefined, undefined, [],
-        undefined, undefined, undefined, undefined]);
+      undefined, undefined, undefined, [], undefined, undefined, undefined,
+      undefined
+    ]);
     var result = foo.toObject();
-    assertObjectEquals({
-      aString: undefined,
-      anOutOfOrderBool: undefined,
-      aNestedMessage: {
-        anInt: undefined
-      },
-      // Note: JsPb converts undefined repeated fields to empty arrays.
-      aRepeatedMessageList: [],
-      aRepeatedStringList: []
-    }, result);
+    assertObjectEquals(
+        {
+          aString: undefined,
+          anOutOfOrderBool: undefined,
+          aNestedMessage: {anInt: undefined},
+          // Note: JsPb converts undefined repeated fields to empty arrays.
+          aRepeatedMessageList: [],
+          aRepeatedStringList: []
+        },
+        result);
 
   });
 
@@ -214,20 +216,21 @@
   it('testSpecialCases', function() {
     // Note: Some property names are reserved in JavaScript.
     // These names are converted to the Js property named pb_<reserved_name>.
-    var special =
-        new proto.jspb.test.SpecialCases(['normal', 'default', 'function',
-        'var']);
+    var special = new proto.jspb.test.SpecialCases(
+        ['normal', 'default', 'function', 'var']);
     var result = special.toObject();
-    assertObjectEquals({
-      normal: 'normal',
-      pb_default: 'default',
-      pb_function: 'function',
-      pb_var: 'var'
-    }, result);
+    assertObjectEquals(
+        {
+          normal: 'normal',
+          pb_default: 'default',
+          pb_function: 'function',
+          pb_var: 'var'
+        },
+        result);
   });
 
   it('testDefaultValues', function() {
-    var defaultString = "default<>\'\"abc";
+    var defaultString = 'default<>\'"abc';
     var response = new proto.jspb.test.DefaultValues();
 
     // Test toObject
@@ -291,8 +294,10 @@
 
     // Test that clearing the values reverts them to the default state.
     response = makeDefault(['blah', false, 111, 77]);
-    response.clearStringField(); response.clearBoolField();
-    response.clearIntField(); response.clearEnumField();
+    response.clearStringField();
+    response.clearBoolField();
+    response.clearIntField();
+    response.clearEnumField();
     assertEquals(defaultString, response.getStringField());
     assertEquals(true, response.getBoolField());
     assertEquals(11, response.getIntField());
@@ -304,8 +309,10 @@
 
     // Test that setFoo(null) clears the values.
     response = makeDefault(['blah', false, 111, 77]);
-    response.setStringField(null); response.setBoolField(null);
-    response.setIntField(undefined); response.setEnumField(undefined);
+    response.setStringField(null);
+    response.setBoolField(null);
+    response.setIntField(undefined);
+    response.setEnumField(undefined);
     assertEquals(defaultString, response.getStringField());
     assertEquals(true, response.getBoolField());
     assertEquals(11, response.getIntField());
@@ -321,13 +328,13 @@
     assertTrue(jspb.Message.equals(s1, new proto.jspb.test.Simple1(['hi'])));
     assertFalse(jspb.Message.equals(s1, new proto.jspb.test.Simple1(['bye'])));
     var s1b = new proto.jspb.test.Simple1(['hi', ['hello']]);
-    assertTrue(jspb.Message.equals(s1b,
-        new proto.jspb.test.Simple1(['hi', ['hello']])));
-    assertTrue(jspb.Message.equals(s1b,
-        new proto.jspb.test.Simple1(['hi', ['hello', undefined,
-                                            undefined, undefined]])));
-    assertFalse(jspb.Message.equals(s1b,
-        new proto.jspb.test.Simple1(['no', ['hello']])));
+    assertTrue(jspb.Message.equals(
+        s1b, new proto.jspb.test.Simple1(['hi', ['hello']])));
+    assertTrue(jspb.Message.equals(s1b, new proto.jspb.test.Simple1([
+      'hi', ['hello', undefined, undefined, undefined]
+    ])));
+    assertFalse(jspb.Message.equals(
+        s1b, new proto.jspb.test.Simple1(['no', ['hello']])));
     // Test with messages of different types
     var s2 = new proto.jspb.test.Simple2(['hi']);
     assertFalse(jspb.Message.equals(s1, s2));
@@ -335,18 +342,18 @@
 
   it('testEquals_softComparison', function() {
     var s1 = new proto.jspb.test.Simple1(['hi', [], null]);
-    assertTrue(jspb.Message.equals(s1,
-        new proto.jspb.test.Simple1(['hi', []])));
+    assertTrue(
+        jspb.Message.equals(s1, new proto.jspb.test.Simple1(['hi', []])));
 
     var s1b = new proto.jspb.test.Simple1(['hi', [], true]);
-    assertTrue(jspb.Message.equals(s1b,
-        new proto.jspb.test.Simple1(['hi', [], 1])));
+    assertTrue(
+        jspb.Message.equals(s1b, new proto.jspb.test.Simple1(['hi', [], 1])));
   });
 
   it('testEqualsComplex', function() {
-    var data1 = ['a',,, [, 11], [[, 22], [, 33]],, ['s1', 's2'],, 1];
-    var data2 = ['a',,, [, 11], [[, 22], [, 34]],, ['s1', 's2'],, 1];
-    var data3 = ['a',,, [, 11], [[, 22]],, ['s1', 's2'],, 1];
+    var data1 = ['a', , , [, 11], [[, 22], [, 33]], , ['s1', 's2'], , 1];
+    var data2 = ['a', , , [, 11], [[, 22], [, 34]], , ['s1', 's2'], , 1];
+    var data3 = ['a', , , [, 11], [[, 22]], , ['s1', 's2'], , 1];
     var data4 = ['hi'];
     var c1a = new proto.jspb.test.Complex(data1);
     var c1b = new proto.jspb.test.Complex(data1);
@@ -363,42 +370,34 @@
   it('testEqualsExtensionsConstructed', function() {
     assertTrue(jspb.Message.equals(
         new proto.jspb.test.HasExtensions([]),
-        new proto.jspb.test.HasExtensions([{}])
-    ));
+        new proto.jspb.test.HasExtensions([{}])));
     assertTrue(jspb.Message.equals(
         new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]),
-        new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}])
-    ));
+        new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}])));
     assertFalse(jspb.Message.equals(
         new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]),
-        new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'b'}]}])
-    ));
+        new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'b'}]}])));
     assertTrue(jspb.Message.equals(
         new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}]),
-        new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}])
-    ));
+        new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}])));
     assertTrue(jspb.Message.equals(
         new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}]),
-        new proto.jspb.test.HasExtensions([,,, {100: [{200: 'a'}]}])
-    ));
+        new proto.jspb.test.HasExtensions([, , , {100: [{200: 'a'}]}])));
     assertTrue(jspb.Message.equals(
-        new proto.jspb.test.HasExtensions([,,, {100: [{200: 'a'}]}]),
-        new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}])
-    ));
+        new proto.jspb.test.HasExtensions([, , , {100: [{200: 'a'}]}]),
+        new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}])));
     assertTrue(jspb.Message.equals(
         new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]),
-        new proto.jspb.test.HasExtensions(['hi',,, {100: [{200: 'a'}]}])
-    ));
+        new proto.jspb.test.HasExtensions(['hi', , , {100: [{200: 'a'}]}])));
     assertTrue(jspb.Message.equals(
-        new proto.jspb.test.HasExtensions(['hi',,, {100: [{200: 'a'}]}]),
-        new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}])
-    ));
+        new proto.jspb.test.HasExtensions(['hi', , , {100: [{200: 'a'}]}]),
+        new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}])));
   });
 
   it('testEqualsExtensionsUnconstructed', function() {
     assertTrue(jspb.Message.compareFields([], [{}]));
-    assertTrue(jspb.Message.compareFields([,,, {}], []));
-    assertTrue(jspb.Message.compareFields([,,, {}], [,, {}]));
+    assertTrue(jspb.Message.compareFields([, , , {}], []));
+    assertTrue(jspb.Message.compareFields([, , , {}], [, , {}]));
     assertTrue(jspb.Message.compareFields(
         ['hi', {100: [{200: 'a'}]}], ['hi', {100: [{200: 'a'}]}]));
     assertFalse(jspb.Message.compareFields(
@@ -406,13 +405,13 @@
     assertTrue(jspb.Message.compareFields(
         [{100: [{200: 'a'}]}], [{100: [{200: 'a'}]}]));
     assertTrue(jspb.Message.compareFields(
-        [{100: [{200: 'a'}]}], [,,, {100: [{200: 'a'}]}]));
+        [{100: [{200: 'a'}]}], [, , , {100: [{200: 'a'}]}]));
     assertTrue(jspb.Message.compareFields(
-        [,,, {100: [{200: 'a'}]}], [{100: [{200: 'a'}]}]));
+        [, , , {100: [{200: 'a'}]}], [{100: [{200: 'a'}]}]));
     assertTrue(jspb.Message.compareFields(
-        ['hi', {100: [{200: 'a'}]}], ['hi',,, {100: [{200: 'a'}]}]));
+        ['hi', {100: [{200: 'a'}]}], ['hi', , , {100: [{200: 'a'}]}]));
     assertTrue(jspb.Message.compareFields(
-        ['hi',,, {100: [{200: 'a'}]}], ['hi', {100: [{200: 'a'}]}]));
+        ['hi', , , {100: [{200: 'a'}]}], ['hi', {100: [{200: 'a'}]}]));
   });
 
   it('testInitializeMessageWithLastFieldNull', function() {
@@ -436,13 +435,13 @@
   it('testToMap', function() {
     var p1 = new proto.jspb.test.Simple1(['k', ['v']]);
     var p2 = new proto.jspb.test.Simple1(['k1', ['v1', 'v2']]);
-    var soymap = jspb.Message.toMap([p1, p2],
-        proto.jspb.test.Simple1.prototype.getAString,
+    var soymap = jspb.Message.toMap(
+        [p1, p2], proto.jspb.test.Simple1.prototype.getAString,
         proto.jspb.test.Simple1.prototype.toObject);
     assertEquals('k', soymap['k'].aString);
     assertArrayEquals(['v'], soymap['k'].aRepeatedStringList);
-    var protomap = jspb.Message.toMap([p1, p2],
-        proto.jspb.test.Simple1.prototype.getAString);
+    var protomap = jspb.Message.toMap(
+        [p1, p2], proto.jspb.test.Simple1.prototype.getAString);
     assertEquals('k', protomap['k'].getAString());
     assertArrayEquals(['v'], protomap['k'].getARepeatedStringList());
   });
@@ -463,8 +462,12 @@
     extension.setExt('e1');
     original.setExtension(proto.jspb.test.IsExtension.extField, extension);
     var clone = original.clone();
-    assertArrayEquals(['v1',, ['x1', ['y1', 'z1']],,
-      [['x2', ['y2', 'z2']], ['x3', ['y3', 'z3']]], bytes1,, { 100: [, 'e1'] }],
+    assertArrayEquals(
+        [
+          'v1', , ['x1', ['y1', 'z1']], ,
+          [['x2', ['y2', 'z2']], ['x3', ['y3', 'z3']]], bytes1, ,
+          {100: [, 'e1']}
+        ],
         clone.toArray());
     clone.setStr('v2');
     var simple4 = new proto.jspb.test.Simple1(['a1', ['b1', 'c1']]);
@@ -481,11 +484,19 @@
     var newExtension = new proto.jspb.test.CloneExtension();
     newExtension.setExt('e2');
     clone.setExtension(proto.jspb.test.CloneExtension.extField, newExtension);
-    assertArrayEquals(['v2',, ['a1', ['b1', 'c1']],,
-      [['a2', ['b2', 'c2']], ['a3', ['b3', 'c3']]], bytes2,, { 100: [, 'e2'] }],
+    assertArrayEquals(
+        [
+          'v2', , ['a1', ['b1', 'c1']], ,
+          [['a2', ['b2', 'c2']], ['a3', ['b3', 'c3']]], bytes2, ,
+          {100: [, 'e2']}
+        ],
         clone.toArray());
-    assertArrayEquals(['v1',, ['x1', ['y1', 'z1']],,
-      [['x2', ['y2', 'z2']], ['x3', ['y3', 'z3']]], bytes1,, { 100: [, 'e1'] }],
+    assertArrayEquals(
+        [
+          'v1', , ['x1', ['y1', 'z1']], ,
+          [['x2', ['y2', 'z2']], ['x3', ['y3', 'z3']]], bytes1, ,
+          {100: [, 'e1']}
+        ],
         original.toArray());
   });
 
@@ -517,11 +528,12 @@
     jspb.Message.copyInto(original, dest);
     assertArrayEquals(original.toArray(), dest.toArray());
     assertEquals('x1', dest.getSimple1().getAString());
-    assertEquals('e1',
+    assertEquals(
+        'e1',
         dest.getExtension(proto.jspb.test.CloneExtension.extField).getExt());
     dest.getSimple1().setAString('new value');
-    assertNotEquals(dest.getSimple1().getAString(),
-        original.getSimple1().getAString());
+    assertNotEquals(
+        dest.getSimple1().getAString(), original.getSimple1().getAString());
     if (supportsUint8Array) {
       dest.getBytesField()[0] = 7;
       assertObjectEquals(bytes1, original.getBytesField());
@@ -531,12 +543,12 @@
       assertObjectEquals(bytes1, original.getBytesField());
       assertObjectEquals('789', dest.getBytesField());
     }
-    dest.getExtension(proto.jspb.test.CloneExtension.extField).
-        setExt('new value');
+    dest.getExtension(proto.jspb.test.CloneExtension.extField)
+        .setExt('new value');
     assertNotEquals(
         dest.getExtension(proto.jspb.test.CloneExtension.extField).getExt(),
-        original.getExtension(
-            proto.jspb.test.CloneExtension.extField).getExt());
+        original.getExtension(proto.jspb.test.CloneExtension.extField)
+            .getExt());
   });
 
   it('testCopyInto_notSameType', function() {
@@ -554,26 +566,32 @@
     var extension2 = new proto.jspb.test.Simple1(['str', ['s1', 's2']]);
     var extendable = new proto.jspb.test.HasExtensions(['v1', 'v2', 'v3']);
     extendable.setExtension(proto.jspb.test.IsExtension.extField, extension1);
-    extendable.setExtension(proto.jspb.test.IndirectExtension.simple,
-                            extension2);
+    extendable.setExtension(
+        proto.jspb.test.IndirectExtension.simple, extension2);
     extendable.setExtension(proto.jspb.test.IndirectExtension.str, 'xyzzy');
-    extendable.setExtension(proto.jspb.test.IndirectExtension.repeatedStrList,
-        ['a', 'b']);
+    extendable.setExtension(
+        proto.jspb.test.IndirectExtension.repeatedStrList, ['a', 'b']);
     var s1 = new proto.jspb.test.Simple1(['foo', ['s1', 's2']]);
     var s2 = new proto.jspb.test.Simple1(['bar', ['t1', 't2']]);
     extendable.setExtension(
-        proto.jspb.test.IndirectExtension.repeatedSimpleList,
-        [s1, s2]);
-    assertObjectEquals(extension1,
+        proto.jspb.test.IndirectExtension.repeatedSimpleList, [s1, s2]);
+    assertObjectEquals(
+        extension1,
         extendable.getExtension(proto.jspb.test.IsExtension.extField));
-    assertObjectEquals(extension2,
+    assertObjectEquals(
+        extension2,
         extendable.getExtension(proto.jspb.test.IndirectExtension.simple));
-    assertObjectEquals('xyzzy',
+    assertObjectEquals(
+        'xyzzy',
         extendable.getExtension(proto.jspb.test.IndirectExtension.str));
-    assertObjectEquals(['a', 'b'], extendable.getExtension(
-        proto.jspb.test.IndirectExtension.repeatedStrList));
-    assertObjectEquals([s1, s2], extendable.getExtension(
-        proto.jspb.test.IndirectExtension.repeatedSimpleList));
+    assertObjectEquals(
+        ['a', 'b'],
+        extendable.getExtension(
+            proto.jspb.test.IndirectExtension.repeatedStrList));
+    assertObjectEquals(
+        [s1, s2],
+        extendable.getExtension(
+            proto.jspb.test.IndirectExtension.repeatedSimpleList));
     // Not supported yet, but it should work...
     extendable.setExtension(proto.jspb.test.IndirectExtension.simple, null);
     assertNull(
@@ -592,29 +610,35 @@
     var extendable = new proto.jspb.test.HasExtensions(['v1', 'v2', 'v3']);
     var extension = new proto.jspb.test.Simple1(['foo', ['s1', 's2']]);
     extendable.setExtension(proto.jspb.test.simple1, extension);
-    assertObjectEquals(extension,
-        extendable.getExtension(proto.jspb.test.simple1));
+    assertObjectEquals(
+        extension, extendable.getExtension(proto.jspb.test.simple1));
 
     // From _lib mode.
     extension = new proto.jspb.test.ExtensionMessage(['s1']);
     extendable = new proto.jspb.test.TestExtensionsMessage([16]);
     extendable.setExtension(proto.jspb.test.floatingMsgField, extension);
     extendable.setExtension(proto.jspb.test.floatingStrField, 's2');
-    assertObjectEquals(extension,
-        extendable.getExtension(proto.jspb.test.floatingMsgField));
-    assertObjectEquals('s2',
-        extendable.getExtension(proto.jspb.test.floatingStrField));
+    assertObjectEquals(
+        extension, extendable.getExtension(proto.jspb.test.floatingMsgField));
+    assertObjectEquals(
+        's2', extendable.getExtension(proto.jspb.test.floatingStrField));
     assertNotUndefined(proto.jspb.exttest.floatingMsgField);
     assertNotUndefined(proto.jspb.exttest.floatingMsgFieldTwo);
     assertNotUndefined(proto.jspb.exttest.beta.floatingStrField);
   });
 
   it('testNestedExtensions', function() {
-    var extendable = new proto.jspb.exttest.nested.TestNestedExtensionsMessage();
-    var extension = new proto.jspb.exttest.nested.TestOuterMessage.NestedExtensionMessage(['s1']);
-    extendable.setExtension(proto.jspb.exttest.nested.TestOuterMessage.innerExtension, extension);
-    assertObjectEquals(extension,
-        extendable.getExtension(proto.jspb.exttest.nested.TestOuterMessage.innerExtension));
+    var extendable =
+        new proto.jspb.exttest.nested.TestNestedExtensionsMessage();
+    var extension =
+        new proto.jspb.exttest.nested.TestOuterMessage.NestedExtensionMessage(
+            ['s1']);
+    extendable.setExtension(
+        proto.jspb.exttest.nested.TestOuterMessage.innerExtension, extension);
+    assertObjectEquals(
+        extension,
+        extendable.getExtension(
+            proto.jspb.exttest.nested.TestOuterMessage.innerExtension));
   });
 
   it('testToObject_extendedObject', function() {
@@ -622,60 +646,72 @@
     var extension2 = new proto.jspb.test.Simple1(['str', ['s1', 's2'], true]);
     var extendable = new proto.jspb.test.HasExtensions(['v1', 'v2', 'v3']);
     extendable.setExtension(proto.jspb.test.IsExtension.extField, extension1);
-    extendable.setExtension(proto.jspb.test.IndirectExtension.simple,
-                            extension2);
+    extendable.setExtension(
+        proto.jspb.test.IndirectExtension.simple, extension2);
     extendable.setExtension(proto.jspb.test.IndirectExtension.str, 'xyzzy');
-    extendable.setExtension(proto.jspb.test.IndirectExtension.repeatedStrList,
-        ['a', 'b']);
+    extendable.setExtension(
+        proto.jspb.test.IndirectExtension.repeatedStrList, ['a', 'b']);
     var s1 = new proto.jspb.test.Simple1(['foo', ['s1', 's2'], true]);
     var s2 = new proto.jspb.test.Simple1(['bar', ['t1', 't2'], false]);
     extendable.setExtension(
-        proto.jspb.test.IndirectExtension.repeatedSimpleList,
-        [s1, s2]);
-    assertObjectEquals({
-      str1: 'v1', str2: 'v2', str3: 'v3',
-      extField: { ext1: 'ext1field' },
-      simple: {
-        aString: 'str', aRepeatedStringList: ['s1', 's2'], aBoolean: true
-      },
-      str: 'xyzzy',
-      repeatedStrList: ['a', 'b'],
-      repeatedSimpleList: [
-        { aString: 'foo', aRepeatedStringList: ['s1', 's2'], aBoolean: true},
-        { aString: 'bar', aRepeatedStringList: ['t1', 't2'], aBoolean: false}
-      ]
-    }, extendable.toObject());
+        proto.jspb.test.IndirectExtension.repeatedSimpleList, [s1, s2]);
+    assertObjectEquals(
+        {
+          str1: 'v1',
+          str2: 'v2',
+          str3: 'v3',
+          extField: {ext1: 'ext1field'},
+          simple: {
+            aString: 'str',
+            aRepeatedStringList: ['s1', 's2'],
+            aBoolean: true
+          },
+          str: 'xyzzy',
+          repeatedStrList: ['a', 'b'],
+          repeatedSimpleList: [
+            {aString: 'foo', aRepeatedStringList: ['s1', 's2'], aBoolean: true},
+            {aString: 'bar', aRepeatedStringList: ['t1', 't2'], aBoolean: false}
+          ]
+        },
+        extendable.toObject());
 
     // Now, with instances included.
-    assertObjectEquals({
-      str1: 'v1', str2: 'v2', str3: 'v3',
-      extField: {
-        ext1: 'ext1field',
-        $jspbMessageInstance:
-            extendable.getExtension(proto.jspb.test.IsExtension.extField)
-      },
-      simple: {
-        aString: 'str',
-        aRepeatedStringList: ['s1', 's2'],
-        aBoolean: true,
-        $jspbMessageInstance:
-            extendable.getExtension(proto.jspb.test.IndirectExtension.simple)
-      },
-      str: 'xyzzy',
-      repeatedStrList: ['a', 'b'],
-      repeatedSimpleList: [{
-        aString: 'foo',
-        aRepeatedStringList: ['s1', 's2'],
-        aBoolean: true,
-        $jspbMessageInstance: s1
-      }, {
-        aString: 'bar',
-        aRepeatedStringList: ['t1', 't2'],
-        aBoolean: false,
-        $jspbMessageInstance: s2
-      }],
-      $jspbMessageInstance: extendable
-    }, extendable.toObject(true /* opt_includeInstance */));
+    assertObjectEquals(
+        {
+          str1: 'v1',
+          str2: 'v2',
+          str3: 'v3',
+          extField: {
+            ext1: 'ext1field',
+            $jspbMessageInstance:
+                extendable.getExtension(proto.jspb.test.IsExtension.extField)
+          },
+          simple: {
+            aString: 'str',
+            aRepeatedStringList: ['s1', 's2'],
+            aBoolean: true,
+            $jspbMessageInstance: extendable.getExtension(
+                proto.jspb.test.IndirectExtension.simple)
+          },
+          str: 'xyzzy',
+          repeatedStrList: ['a', 'b'],
+          repeatedSimpleList: [
+            {
+              aString: 'foo',
+              aRepeatedStringList: ['s1', 's2'],
+              aBoolean: true,
+              $jspbMessageInstance: s1
+            },
+            {
+              aString: 'bar',
+              aRepeatedStringList: ['t1', 't2'],
+              aBoolean: false,
+              $jspbMessageInstance: s2
+            }
+          ],
+          $jspbMessageInstance: extendable
+        },
+        extendable.toObject(true /* opt_includeInstance */));
   });
 
   it('testInitialization_emptyArray', function() {
@@ -708,7 +744,8 @@
      });
 
   it('testToObject_hasExtensionField', function() {
-    var data = new proto.jspb.test.HasExtensions(['str1', {100: ['ext1'], 102: ''}]);
+    var data =
+        new proto.jspb.test.HasExtensions(['str1', {100: ['ext1'], 102: ''}]);
     var obj = data.toObject();
     assertEquals('str1', obj.str1);
     assertEquals('ext1', obj.extField.ext1);
@@ -728,8 +765,7 @@
     var extensionMessage = new proto.jspb.test.IsExtension(['is_extension']);
     data.setExtension(proto.jspb.test.IsExtension.extField, extensionMessage);
     var obj = data.toObject();
-    assertNotNull(
-        data.getExtension(proto.jspb.test.IsExtension.extField));
+    assertNotNull(data.getExtension(proto.jspb.test.IsExtension.extField));
     assertEquals('is_extension', obj.extField.ext1);
   });
 
@@ -746,16 +782,18 @@
     var groups = group.getRepeatedGroupList();
     assertEquals('g1', groups[0].getId());
     assertObjectEquals([true, false], groups[0].getSomeBoolList());
-    assertObjectEquals({id: 'g1', someBoolList: [true, false]},
-        groups[0].toObject());
-    assertObjectEquals({
-      repeatedGroupList: [{id: 'g1', someBoolList: [true, false]}],
-      requiredGroup: {id: undefined},
-      optionalGroup: undefined,
-      requiredSimple: {aRepeatedStringList: [], aString: undefined},
-      optionalSimple: undefined,
-      id: undefined
-    }, group.toObject());
+    assertObjectEquals(
+        {id: 'g1', someBoolList: [true, false]}, groups[0].toObject());
+    assertObjectEquals(
+        {
+          repeatedGroupList: [{id: 'g1', someBoolList: [true, false]}],
+          requiredGroup: {id: undefined},
+          optionalGroup: undefined,
+          requiredSimple: {aRepeatedStringList: [], aString: undefined},
+          optionalSimple: undefined,
+          id: undefined
+        },
+        group.toObject());
     var group1 = new proto.jspb.test.TestGroup1();
     group1.setGroup(someGroup);
     assertEquals(someGroup, group1.getGroup());
@@ -772,28 +810,29 @@
     message.setExtension$(11);
     message.setExtension(proto.jspb.test.TestReservedNamesExtension.foo, 12);
     assertEquals(11, message.getExtension$());
-    assertEquals(12, message.getExtension(
-        proto.jspb.test.TestReservedNamesExtension.foo));
+    assertEquals(
+        12,
+        message.getExtension(proto.jspb.test.TestReservedNamesExtension.foo));
     assertObjectEquals({extension: 11, foo: 12}, message.toObject());
   });
 
   it('testInitializeMessageWithUnsetOneof', function() {
     var message = new proto.jspb.test.TestMessageWithOneof([]);
     assertEquals(
-        proto.jspb.test.TestMessageWithOneof.PartialOneofCase.
-            PARTIAL_ONEOF_NOT_SET,
+        proto.jspb.test.TestMessageWithOneof.PartialOneofCase
+            .PARTIAL_ONEOF_NOT_SET,
         message.getPartialOneofCase());
     assertEquals(
-        proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase.
-            RECURSIVE_ONEOF_NOT_SET,
+        proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase
+            .RECURSIVE_ONEOF_NOT_SET,
         message.getRecursiveOneofCase());
   });
 
   it('testUnsetsOneofCaseWhenFieldIsCleared', function() {
     var message = new proto.jspb.test.TestMessageWithOneof;
     assertEquals(
-        proto.jspb.test.TestMessageWithOneof.PartialOneofCase.
-            PARTIAL_ONEOF_NOT_SET,
+        proto.jspb.test.TestMessageWithOneof.PartialOneofCase
+            .PARTIAL_ONEOF_NOT_SET,
         message.getPartialOneofCase());
 
     message.setPone('hi');
@@ -803,20 +842,20 @@
 
     message.clearPone();
     assertEquals(
-        proto.jspb.test.TestMessageWithOneof.PartialOneofCase.
-            PARTIAL_ONEOF_NOT_SET,
+        proto.jspb.test.TestMessageWithOneof.PartialOneofCase
+            .PARTIAL_ONEOF_NOT_SET,
         message.getPartialOneofCase());
   });
 
   it('testFloatingPointFieldsSupportNan', function() {
     var assertNan = function(x) {
-      assertTrue('Expected ' + x + ' (' + goog.typeOf(x) + ') to be NaN.',
+      assertTrue(
+          'Expected ' + x + ' (' + goog.typeOf(x) + ') to be NaN.',
           goog.isNumber(x) && isNaN(x));
     };
 
     var message = new proto.jspb.test.FloatingPointFields([
-      'NaN', 'NaN', ['NaN', 'NaN'], 'NaN',
-      'NaN', 'NaN', ['NaN', 'NaN'], 'NaN'
+      'NaN', 'NaN', ['NaN', 'NaN'], 'NaN', 'NaN', 'NaN', ['NaN', 'NaN'], 'NaN'
     ]);
     assertNan(message.getOptionalFloatField());
     assertNan(message.getRequiredFloatField());
@@ -837,12 +876,9 @@
     message2.setExtension(
         proto.jspb.exttest.reverse.TestExtensionReverseOrderMessage1.a, 233);
     message2.setExtension(
-        proto
-            .jspb
-            .exttest
-            .reverse
-            .TestExtensionReverseOrderMessage1
-            .TestExtensionReverseOrderNestedMessage1.b, 2333);
+        proto.jspb.exttest.reverse.TestExtensionReverseOrderMessage1
+            .TestExtensionReverseOrderNestedMessage1.b,
+        2333);
     message2.setExtension(proto.jspb.exttest.reverse.c, 23333);
 
     assertEquals(
@@ -852,15 +888,9 @@
     assertEquals(
         2333,
         message2.getExtension(
-            proto
-                .jspb
-                .exttest
-                .reverse
-                .TestExtensionReverseOrderMessage1
+            proto.jspb.exttest.reverse.TestExtensionReverseOrderMessage1
                 .TestExtensionReverseOrderNestedMessage1.b));
-    assertEquals(
-        23333,
-        message2.getExtension(proto.jspb.exttest.reverse.c));
+    assertEquals(23333, message2.getExtension(proto.jspb.exttest.reverse.c));
   });
 
   it('testCircularDepsBaseOnMessageField', function() {
@@ -983,16 +1013,14 @@
     var package1Message = new proto.jspb.filenametest.package1.TestMessage;
     var package2Message = new proto.jspb.filenametest.package2.TestMessage;
 
-    package1Message.setExtension(
-        proto.jspb.filenametest.package1.a, 10);
-    package1Message.setExtension(
-        proto.jspb.filenametest.package1.b, 11);
+    package1Message.setExtension(proto.jspb.filenametest.package1.a, 10);
+    package1Message.setExtension(proto.jspb.filenametest.package1.b, 11);
     package2Message.setA(12);
 
-    assertEquals(10,
-        package1Message.getExtension(proto.jspb.filenametest.package1.a));
-    assertEquals(11,
-        package1Message.getExtension(proto.jspb.filenametest.package1.b));
+    assertEquals(
+        10, package1Message.getExtension(proto.jspb.filenametest.package1.a));
+    assertEquals(
+        11, package1Message.getExtension(proto.jspb.filenametest.package1.b));
     assertEquals(12, package2Message.getA());
   });
 
diff --git a/python/google/protobuf/internal/json_format_test.py b/python/google/protobuf/internal/json_format_test.py
index 9112f5e..abec864 100644
--- a/python/google/protobuf/internal/json_format_test.py
+++ b/python/google/protobuf/internal/json_format_test.py
@@ -49,9 +49,11 @@
 from google.protobuf import struct_pb2
 from google.protobuf import timestamp_pb2
 from google.protobuf import wrappers_pb2
+from google.protobuf import any_test_pb2
 from google.protobuf import unittest_mset_pb2
 from google.protobuf import unittest_pb2
 from google.protobuf.internal import well_known_types
+from google.protobuf import descriptor_pool
 from google.protobuf import json_format
 from google.protobuf.util import json_format_proto3_pb2
 
@@ -202,8 +204,8 @@
 
   def testJsonParseDictToAnyDoesNotAlterInput(self):
     orig_dict = {
-        "int32Value": 20,
-        "@type": "type.googleapis.com/proto3.TestMessage"
+        'int32Value': 20,
+        '@type': 'type.googleapis.com/proto3.TestMessage'
     }
     copied_dict = json.loads(json.dumps(orig_dict))
     parsed_message = any_pb2.Any()
@@ -628,6 +630,19 @@
         '  "value": {\n'
         '    "@type": "type.googleapis.com/proto3.TestMessage"')
 
+  def testAnyMessageDescriptorPoolMissingType(self):
+    packed_message = unittest_pb2.OneString()
+    packed_message.data = 'string'
+    message = any_test_pb2.TestAny()
+    message.any_value.Pack(packed_message)
+    empty_pool = descriptor_pool.DescriptorPool()
+    with self.assertRaises(TypeError) as cm:
+      json_format.MessageToJson(message, True, descriptor_pool=empty_pool)
+    self.assertEqual(
+        'Can not find message descriptor by type_url:'
+        ' type.googleapis.com/protobuf_unittest.OneString.',
+        str(cm.exception))
+
   def testWellKnownInAnyMessage(self):
     message = any_pb2.Any()
     int32_value = wrappers_pb2.Int32Value()
@@ -1016,6 +1031,32 @@
     json_format.ParseDict(js_dict, message)
     self.assertEqual(expected, message.int32_value)
 
+  def testParseDictAnyDescriptorPoolMissingType(self):
+    # Confirm that ParseDict does not raise ParseError with default pool
+    js_dict = {
+        'any_value': {
+            '@type': 'type.googleapis.com/proto3.MessageType',
+            'value': 1234
+        }
+    }
+    json_format.ParseDict(js_dict, any_test_pb2.TestAny())
+    # Check ParseDict raises ParseError with empty pool
+    js_dict = {
+        'any_value': {
+            '@type': 'type.googleapis.com/proto3.MessageType',
+            'value': 1234
+        }
+    }
+    with self.assertRaises(json_format.ParseError) as cm:
+      empty_pool = descriptor_pool.DescriptorPool()
+      json_format.ParseDict(js_dict,
+                            any_test_pb2.TestAny(),
+                            descriptor_pool=empty_pool)
+    self.assertEqual(
+        str(cm.exception),
+        'Failed to parse any_value field: Can not find message descriptor by'
+        ' type_url: type.googleapis.com/proto3.MessageType..')
+
   def testMessageToDict(self):
     message = json_format_proto3_pb2.TestMessage()
     message.int32_value = 12345
diff --git a/python/google/protobuf/internal/missing_enum_values.proto b/python/google/protobuf/internal/missing_enum_values.proto
index 1850be5..5c0f499 100644
--- a/python/google/protobuf/internal/missing_enum_values.proto
+++ b/python/google/protobuf/internal/missing_enum_values.proto
@@ -30,6 +30,7 @@
 
 syntax = "proto2";
 
+
 package google.protobuf.python.internal;
 
 message TestEnumValues {
diff --git a/python/google/protobuf/internal/python_message.py b/python/google/protobuf/internal/python_message.py
index f77c44b..4b5df99 100755
--- a/python/google/protobuf/internal/python_message.py
+++ b/python/google/protobuf/internal/python_message.py
@@ -1406,7 +1406,11 @@
   self._unknown_field_set = None      # pylint: disable=protected-access
   for field, value in self.ListFields():
     if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
-      if field.label == _FieldDescriptor.LABEL_REPEATED:
+      if _IsMapField(field):
+        if _IsMessageMapField(field):
+          for key in value:
+            value[key].DiscardUnknownFields()
+      elif field.label == _FieldDescriptor.LABEL_REPEATED:
         for sub_message in value:
           sub_message.DiscardUnknownFields()
       else:
diff --git a/python/google/protobuf/internal/text_format_test.py b/python/google/protobuf/internal/text_format_test.py
index 3580677..16a3f53 100755
--- a/python/google/protobuf/internal/text_format_test.py
+++ b/python/google/protobuf/internal/text_format_test.py
@@ -715,6 +715,24 @@
     self.assertEqual(m.optional_string, self._GOLDEN_UNICODE)
     self.assertEqual(m.repeated_bytes[0], self._GOLDEN_BYTES)
 
+  def testParseDuplicateMessages(self, message_module):
+    message = message_module.TestAllTypes()
+    text = ('optional_nested_message { bb: 1 } '
+            'optional_nested_message { bb: 2 }')
+    six.assertRaisesRegex(self, text_format.ParseError, (
+        r'1:59 : Message type "\w+.TestAllTypes" '
+        r'should not have multiple "optional_nested_message" fields.'),
+                          text_format.Parse, text,
+                          message)
+
+  def testParseDuplicateScalars(self, message_module):
+    message = message_module.TestAllTypes()
+    text = ('optional_int32: 42 ' 'optional_int32: 67')
+    six.assertRaisesRegex(self, text_format.ParseError, (
+        r'1:36 : Message type "\w+.TestAllTypes" should not '
+        r'have multiple "optional_int32" fields.'), text_format.Parse, text,
+                          message)
+
 
 @_parameterized.parameters(unittest_pb2, unittest_proto3_arena_pb2)
 class TextFormatMergeTests(TextFormatBase):
@@ -1293,16 +1311,6 @@
         '"protobuf_unittest.optional_int32_extension" extensions.'),
                           text_format.Parse, text, message)
 
-  def testParseDuplicateMessages(self):
-    message = unittest_pb2.TestAllTypes()
-    text = ('optional_nested_message { bb: 1 } '
-            'optional_nested_message { bb: 2 }')
-    six.assertRaisesRegex(self, text_format.ParseError, (
-        '1:59 : Message type "protobuf_unittest.TestAllTypes" '
-        'should not have multiple "optional_nested_message" fields.'),
-                          text_format.Parse, text,
-                          message)
-
   def testParseDuplicateExtensionMessages(self):
     message = unittest_pb2.TestAllExtensions()
     text = ('[protobuf_unittest.optional_nested_message_extension]: {} '
@@ -1313,14 +1321,6 @@
         '"protobuf_unittest.optional_nested_message_extension" extensions.'),
                           text_format.Parse, text, message)
 
-  def testParseDuplicateScalars(self):
-    message = unittest_pb2.TestAllTypes()
-    text = ('optional_int32: 42 ' 'optional_int32: 67')
-    six.assertRaisesRegex(self, text_format.ParseError, (
-        '1:36 : Message type "protobuf_unittest.TestAllTypes" should not '
-        'have multiple "optional_int32" fields.'), text_format.Parse, text,
-                          message)
-
   def testParseGroupNotClosed(self):
     message = unittest_pb2.TestAllTypes()
     text = 'RepeatedGroup: <'
diff --git a/python/google/protobuf/internal/unknown_fields_test.py b/python/google/protobuf/internal/unknown_fields_test.py
index fceadf7..ab0260e 100755
--- a/python/google/protobuf/internal/unknown_fields_test.py
+++ b/python/google/protobuf/internal/unknown_fields_test.py
@@ -39,6 +39,7 @@
   import unittest2 as unittest  #PY26
 except ImportError:
   import unittest
+from google.protobuf import map_unittest_pb2
 from google.protobuf import unittest_mset_pb2
 from google.protobuf import unittest_pb2
 from google.protobuf import unittest_proto3_arena_pb2
@@ -138,6 +139,18 @@
     self.assertEqual(
         b'', message.repeated_nested_message[0].SerializeToString())
 
+    msg = map_unittest_pb2.TestMap()
+    msg.map_int32_all_types[1].optional_nested_message.ParseFromString(
+        other_message.SerializeToString())
+    msg.map_string_string['1'] = 'test'
+    self.assertNotEqual(
+        b'',
+        msg.map_int32_all_types[1].optional_nested_message.SerializeToString())
+    msg.DiscardUnknownFields()
+    self.assertEqual(
+        b'',
+        msg.map_int32_all_types[1].optional_nested_message.SerializeToString())
+
 
 class UnknownFieldsAccessorsTest(BaseTestCase):
 
diff --git a/python/google/protobuf/json_format.py b/python/google/protobuf/json_format.py
index 3f2c1bf..a184fa9 100644
--- a/python/google/protobuf/json_format.py
+++ b/python/google/protobuf/json_format.py
@@ -96,12 +96,14 @@
   """Thrown in case of parsing error."""
 
 
-def MessageToJson(message,
-                  including_default_value_fields=False,
-                  preserving_proto_field_name=False,
-                  indent=2,
-                  sort_keys=False,
-                  use_integers_for_enums=False):
+def MessageToJson(
+    message,
+    including_default_value_fields=False,
+    preserving_proto_field_name=False,
+    indent=2,
+    sort_keys=False,
+    use_integers_for_enums=False,
+    descriptor_pool=None):
   """Converts protobuf message to JSON format.
 
   Args:
@@ -117,20 +119,26 @@
         An indent level of 0 or negative will only insert newlines.
     sort_keys: If True, then the output will be sorted by field names.
     use_integers_for_enums: If true, print integers instead of enum names.
+    descriptor_pool: A Descriptor Pool for resolving types. If None use the
+        default.
 
   Returns:
     A string containing the JSON formatted protocol buffer message.
   """
-  printer = _Printer(including_default_value_fields,
-                     preserving_proto_field_name,
-                     use_integers_for_enums)
+  printer = _Printer(
+      including_default_value_fields,
+      preserving_proto_field_name,
+      use_integers_for_enums,
+      descriptor_pool)
   return printer.ToJsonString(message, indent, sort_keys)
 
 
-def MessageToDict(message,
-                  including_default_value_fields=False,
-                  preserving_proto_field_name=False,
-                  use_integers_for_enums=False):
+def MessageToDict(
+    message,
+    including_default_value_fields=False,
+    preserving_proto_field_name=False,
+    use_integers_for_enums=False,
+    descriptor_pool=None):
   """Converts protobuf message to a dictionary.
 
   When the dictionary is encoded to JSON, it conforms to proto3 JSON spec.
@@ -145,13 +153,17 @@
         names as defined in the .proto file. If False, convert the field
         names to lowerCamelCase.
     use_integers_for_enums: If true, print integers instead of enum names.
+    descriptor_pool: A Descriptor Pool for resolving types. If None use the
+        default.
 
   Returns:
     A dict representation of the protocol buffer message.
   """
-  printer = _Printer(including_default_value_fields,
-                     preserving_proto_field_name,
-                     use_integers_for_enums)
+  printer = _Printer(
+      including_default_value_fields,
+      preserving_proto_field_name,
+      use_integers_for_enums,
+      descriptor_pool)
   # pylint: disable=protected-access
   return printer._MessageToJsonObject(message)
 
@@ -165,13 +177,16 @@
 class _Printer(object):
   """JSON format printer for protocol message."""
 
-  def __init__(self,
-               including_default_value_fields=False,
-               preserving_proto_field_name=False,
-               use_integers_for_enums=False):
+  def __init__(
+      self,
+      including_default_value_fields=False,
+      preserving_proto_field_name=False,
+      use_integers_for_enums=False,
+      descriptor_pool=None):
     self.including_default_value_fields = including_default_value_fields
     self.preserving_proto_field_name = preserving_proto_field_name
     self.use_integers_for_enums = use_integers_for_enums
+    self.descriptor_pool = descriptor_pool
 
   def ToJsonString(self, message, indent, sort_keys):
     js = self._MessageToJsonObject(message)
@@ -300,7 +315,7 @@
     js = OrderedDict()
     type_url = message.type_url
     js['@type'] = type_url
-    sub_message = _CreateMessageFromTypeUrl(type_url)
+    sub_message = _CreateMessageFromTypeUrl(type_url, self.descriptor_pool)
     sub_message.ParseFromString(message.value)
     message_descriptor = sub_message.DESCRIPTOR
     full_name = message_descriptor.full_name
@@ -366,13 +381,13 @@
   return result
 
 
-def _CreateMessageFromTypeUrl(type_url):
-  # TODO(jieluo): Should add a way that users can register the type resolver
-  # instead of the default one.
+def _CreateMessageFromTypeUrl(type_url, descriptor_pool):
+  """Creates a message from a type URL."""
   db = symbol_database.Default()
+  pool = db.pool if descriptor_pool is None else descriptor_pool
   type_name = type_url.split('/')[-1]
   try:
-    message_descriptor = db.pool.FindMessageTypeByName(type_name)
+    message_descriptor = pool.FindMessageTypeByName(type_name)
   except KeyError:
     raise TypeError(
         'Can not find message descriptor by type_url: {0}.'.format(type_url))
@@ -380,13 +395,15 @@
   return message_class()
 
 
-def Parse(text, message, ignore_unknown_fields=False):
+def Parse(text, message, ignore_unknown_fields=False, descriptor_pool=None):
   """Parses a JSON representation of a protocol message into a message.
 
   Args:
     text: Message JSON representation.
     message: A protocol buffer message to merge into.
     ignore_unknown_fields: If True, do not raise errors for unknown fields.
+    descriptor_pool: A Descriptor Pool for resolving types. If None use the
+        default.
 
   Returns:
     The same message passed as argument.
@@ -399,21 +416,26 @@
     js = json.loads(text, object_pairs_hook=_DuplicateChecker)
   except ValueError as e:
     raise ParseError('Failed to load JSON: {0}.'.format(str(e)))
-  return ParseDict(js, message, ignore_unknown_fields)
+  return ParseDict(js, message, ignore_unknown_fields, descriptor_pool)
 
 
-def ParseDict(js_dict, message, ignore_unknown_fields=False):
+def ParseDict(js_dict,
+              message,
+              ignore_unknown_fields=False,
+              descriptor_pool=None):
   """Parses a JSON dictionary representation into a message.
 
   Args:
     js_dict: Dict representation of a JSON message.
     message: A protocol buffer message to merge into.
     ignore_unknown_fields: If True, do not raise errors for unknown fields.
+    descriptor_pool: A Descriptor Pool for resolving types. If None use the
+      default.
 
   Returns:
     The same message passed as argument.
   """
-  parser = _Parser(ignore_unknown_fields)
+  parser = _Parser(ignore_unknown_fields, descriptor_pool)
   parser.ConvertMessage(js_dict, message)
   return message
 
@@ -424,9 +446,9 @@
 class _Parser(object):
   """JSON format parser for protocol message."""
 
-  def __init__(self,
-               ignore_unknown_fields):
+  def __init__(self, ignore_unknown_fields, descriptor_pool):
     self.ignore_unknown_fields = ignore_unknown_fields
+    self.descriptor_pool = descriptor_pool
 
   def ConvertMessage(self, value, message):
     """Convert a JSON object into a message.
@@ -562,7 +584,7 @@
     except KeyError:
       raise ParseError('@type is missing when parsing any message.')
 
-    sub_message = _CreateMessageFromTypeUrl(type_url)
+    sub_message = _CreateMessageFromTypeUrl(type_url, self.descriptor_pool)
     message_descriptor = sub_message.DESCRIPTOR
     full_name = message_descriptor.full_name
     if _IsWrapperMessage(message_descriptor):
diff --git a/python/google/protobuf/pyext/map_container.cc b/python/google/protobuf/pyext/map_container.cc
index 9f74e2a..d858402 100644
--- a/python/google/protobuf/pyext/map_container.cc
+++ b/python/google/protobuf/pyext/map_container.cc
@@ -346,11 +346,11 @@
   const Message* other_message = other_map->message;
   const Reflection* reflection = message->GetReflection();
   const Reflection* other_reflection = other_message->GetReflection();
-  internal::MapFieldBase* field = reflection->MapData(
+  internal::MapFieldBase* field = reflection->MutableMapData(
       message, self->parent_field_descriptor);
-  internal::MapFieldBase* other_field =
-      other_reflection->MapData(const_cast<Message*>(other_message),
-                                self->parent_field_descriptor);
+  const internal::MapFieldBase* other_field =
+      other_reflection->GetMapData(*other_message,
+                                   self->parent_field_descriptor);
   field->MergeFrom(*other_field);
   self->version++;
   Py_RETURN_NONE;
diff --git a/python/google/protobuf/text_format.py b/python/google/protobuf/text_format.py
index f7053c6..1d965fa 100755
--- a/python/google/protobuf/text_format.py
+++ b/python/google/protobuf/text_format.py
@@ -937,11 +937,9 @@
       else:
         getattr(message, field.name).append(value)
     else:
-      # Proto3 doesn't represent presence so we can't test if multiple scalars
-      # have occurred. We have to allow them.
-      can_check_presence = not self._IsProto3Syntax(message)
       if field.is_extension:
-        if (not self._allow_multiple_scalars and can_check_presence and
+        if (not self._allow_multiple_scalars and
+            not self._IsProto3Syntax(message) and
             message.HasExtension(field)):
           raise tokenizer.ParseErrorPreviousToken(
               'Message type "%s" should not have multiple "%s" extensions.' %
@@ -949,8 +947,16 @@
         else:
           message.Extensions[field] = value
       else:
-        if (not self._allow_multiple_scalars and can_check_presence and
-            message.HasField(field.name)):
+        duplicate_error = False
+        if not self._allow_multiple_scalars:
+          if self._IsProto3Syntax(message):
+            # Proto3 doesn't represent presence so we try best effort to check
+            # multiple scalars by compare to default values.
+            duplicate_error = bool(getattr(message, field.name))
+          else:
+            duplicate_error = message.HasField(field.name)
+
+        if duplicate_error:
           raise tokenizer.ParseErrorPreviousToken(
               'Message type "%s" should not have multiple "%s" fields.' %
               (message.DESCRIPTOR.full_name, field.name))
diff --git a/src/google/protobuf/any.pb.cc b/src/google/protobuf/any.pb.cc
index d37b23c..1c95380 100644
--- a/src/google/protobuf/any.pb.cc
+++ b/src/google/protobuf/any.pb.cc
@@ -201,13 +201,13 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // string type_url = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.Any.type_url");
         auto str = msg->mutable_type_url();
@@ -226,7 +226,7 @@
       // bytes value = 2;
       case 2: {
         if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         auto str = msg->mutable_value();
         if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
@@ -242,7 +242,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -256,13 +256,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool Any::MergePartialFromCodedStream(
@@ -352,8 +348,7 @@
 }
 
 ::google::protobuf::uint8* Any::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Any)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
diff --git a/src/google/protobuf/any.pb.h b/src/google/protobuf/any.pb.h
index a56549a..ba93762 100644
--- a/src/google/protobuf/any.pb.h
+++ b/src/google/protobuf/any.pb.h
@@ -148,7 +148,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
diff --git a/src/google/protobuf/api.pb.cc b/src/google/protobuf/api.pb.cc
index 846ea6b..2a5c466 100644
--- a/src/google/protobuf/api.pb.cc
+++ b/src/google/protobuf/api.pb.cc
@@ -307,13 +307,13 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // string name = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.Api.name");
         auto str = msg->mutable_name();
@@ -333,7 +333,7 @@
       case 2: {
         if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::Method::_InternalParse;
           object = msg->add_methods();
@@ -351,7 +351,7 @@
       case 3: {
         if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::Option::_InternalParse;
           object = msg->add_options();
@@ -368,7 +368,7 @@
       // string version = 4;
       case 4: {
         if (static_cast<::google::protobuf::uint8>(tag) != 34) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.Api.version");
         auto str = msg->mutable_version();
@@ -387,7 +387,7 @@
       // .google.protobuf.SourceContext source_context = 5;
       case 5: {
         if (static_cast<::google::protobuf::uint8>(tag) != 42) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         parser_till_end = ::google::protobuf::SourceContext::_InternalParse;
         object = msg->mutable_source_context();
@@ -403,7 +403,7 @@
       case 6: {
         if (static_cast<::google::protobuf::uint8>(tag) != 50) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::Mixin::_InternalParse;
           object = msg->add_mixins();
@@ -421,14 +421,14 @@
       case 7: {
         if (static_cast<::google::protobuf::uint8>(tag) != 56) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ::google::protobuf::Syntax value = static_cast<::google::protobuf::Syntax>(val);
         msg->set_syntax(value);
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -442,13 +442,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool Api::MergePartialFromCodedStream(
@@ -643,8 +639,7 @@
 }
 
 ::google::protobuf::uint8* Api::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Api)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -665,7 +660,7 @@
       n = static_cast<unsigned int>(this->methods_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        2, this->methods(static_cast<int>(i)), deterministic, target);
+        2, this->methods(static_cast<int>(i)), target);
   }
 
   // repeated .google.protobuf.Option options = 3;
@@ -673,7 +668,7 @@
       n = static_cast<unsigned int>(this->options_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        3, this->options(static_cast<int>(i)), deterministic, target);
+        3, this->options(static_cast<int>(i)), target);
   }
 
   // string version = 4;
@@ -691,7 +686,7 @@
   if (this->has_source_context()) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        5, HasBitSetters::source_context(this), deterministic, target);
+        5, HasBitSetters::source_context(this), target);
   }
 
   // repeated .google.protobuf.Mixin mixins = 6;
@@ -699,7 +694,7 @@
       n = static_cast<unsigned int>(this->mixins_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        6, this->mixins(static_cast<int>(i)), deterministic, target);
+        6, this->mixins(static_cast<int>(i)), target);
   }
 
   // .google.protobuf.Syntax syntax = 7;
@@ -983,13 +978,13 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // string name = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.Method.name");
         auto str = msg->mutable_name();
@@ -1008,7 +1003,7 @@
       // string request_type_url = 2;
       case 2: {
         if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.Method.request_type_url");
         auto str = msg->mutable_request_type_url();
@@ -1028,7 +1023,7 @@
       case 3: {
         if (static_cast<::google::protobuf::uint8>(tag) != 24) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         bool value = val;
         msg->set_request_streaming(value);
@@ -1037,7 +1032,7 @@
       // string response_type_url = 4;
       case 4: {
         if (static_cast<::google::protobuf::uint8>(tag) != 34) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.Method.response_type_url");
         auto str = msg->mutable_response_type_url();
@@ -1057,7 +1052,7 @@
       case 5: {
         if (static_cast<::google::protobuf::uint8>(tag) != 40) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         bool value = val;
         msg->set_response_streaming(value);
@@ -1067,7 +1062,7 @@
       case 6: {
         if (static_cast<::google::protobuf::uint8>(tag) != 50) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::Option::_InternalParse;
           object = msg->add_options();
@@ -1085,14 +1080,14 @@
       case 7: {
         if (static_cast<::google::protobuf::uint8>(tag) != 56) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ::google::protobuf::Syntax value = static_cast<::google::protobuf::Syntax>(val);
         msg->set_syntax(value);
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -1106,13 +1101,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool Method::MergePartialFromCodedStream(
@@ -1311,8 +1302,7 @@
 }
 
 ::google::protobuf::uint8* Method::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Method)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -1365,7 +1355,7 @@
       n = static_cast<unsigned int>(this->options_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        6, this->options(static_cast<int>(i)), deterministic, target);
+        6, this->options(static_cast<int>(i)), target);
   }
 
   // .google.protobuf.Syntax syntax = 7;
@@ -1617,13 +1607,13 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // string name = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.Mixin.name");
         auto str = msg->mutable_name();
@@ -1642,7 +1632,7 @@
       // string root = 2;
       case 2: {
         if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.Mixin.root");
         auto str = msg->mutable_root();
@@ -1659,7 +1649,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -1673,13 +1663,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool Mixin::MergePartialFromCodedStream(
@@ -1777,8 +1763,7 @@
 }
 
 ::google::protobuf::uint8* Mixin::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Mixin)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
diff --git a/src/google/protobuf/api.pb.h b/src/google/protobuf/api.pb.h
index 10edb98..518c6be 100644
--- a/src/google/protobuf/api.pb.h
+++ b/src/google/protobuf/api.pb.h
@@ -142,7 +142,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -332,7 +332,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -515,7 +515,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
index a1cceec..dc540cf 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
@@ -74,20 +74,90 @@
   return StringReplace(name, ".", "::", true);
 }
 
-const char* const kKeywordList[] = {
-  "alignas", "alignof", "and", "and_eq", "asm", "auto", "bitand", "bitor",
-  "bool", "break", "case", "catch", "char", "class", "compl", "const",
-  "constexpr", "const_cast", "continue", "decltype", "default", "delete", "do",
-  "double", "dynamic_cast", "else", "enum", "explicit", "export", "extern",
-  "false", "float", "for", "friend", "goto", "if", "inline", "int", "long",
-  "mutable", "namespace", "new", "noexcept", "not", "not_eq", "nullptr",
-  "operator", "or", "or_eq", "private", "protected", "public", "register",
-  "reinterpret_cast", "return", "short", "signed", "sizeof", "static",
-  "static_assert", "static_cast", "struct", "switch", "template", "this",
-  "thread_local", "throw", "true", "try", "typedef", "typeid", "typename",
-  "union", "unsigned", "using", "virtual", "void", "volatile", "wchar_t",
-  "while", "xor", "xor_eq"
-};
+const char* const kKeywordList[] = {  //
+    "NULL",
+    "alignas",
+    "alignof",
+    "and",
+    "and_eq",
+    "asm",
+    "auto",
+    "bitand",
+    "bitor",
+    "bool",
+    "break",
+    "case",
+    "catch",
+    "char",
+    "class",
+    "compl",
+    "const",
+    "constexpr",
+    "const_cast",
+    "continue",
+    "decltype",
+    "default",
+    "delete",
+    "do",
+    "double",
+    "dynamic_cast",
+    "else",
+    "enum",
+    "explicit",
+    "export",
+    "extern",
+    "false",
+    "float",
+    "for",
+    "friend",
+    "goto",
+    "if",
+    "inline",
+    "int",
+    "long",
+    "mutable",
+    "namespace",
+    "new",
+    "noexcept",
+    "not",
+    "not_eq",
+    "nullptr",
+    "operator",
+    "or",
+    "or_eq",
+    "private",
+    "protected",
+    "public",
+    "register",
+    "reinterpret_cast",
+    "return",
+    "short",
+    "signed",
+    "sizeof",
+    "static",
+    "static_assert",
+    "static_cast",
+    "struct",
+    "switch",
+    "template",
+    "this",
+    "thread_local",
+    "throw",
+    "true",
+    "try",
+    "typedef",
+    "typeid",
+    "typename",
+    "union",
+    "unsigned",
+    "using",
+    "virtual",
+    "void",
+    "volatile",
+    "wchar_t",
+    "while",
+    "xor",
+    "xor_eq"};
 
 std::unordered_set<string> MakeKeywordsMap() {
   std::unordered_set<string> result;
@@ -173,9 +243,15 @@
     // split them.  It might not strictly matter since we don't generate google3
     // code in open-source.  But it's good to prevent surprising things from
     // happening.
-    (*variables)["GOOGLE_PROTOBUF"] = "GOOGLE3" "_PROTOBUF";
-    (*variables)["CHK"] = "CH" "ECK";
-    (*variables)["DCHK"] = "DCH" "ECK";
+    (*variables)["GOOGLE_PROTOBUF"] =
+        "GOOGLE3"
+        "_PROTOBUF";
+    (*variables)["CHK"] =
+        "CH"
+        "ECK";
+    (*variables)["DCHK"] =
+        "DCH"
+        "ECK";
   }
 
   SetIntVar(options, "uint8", variables);
@@ -212,9 +288,9 @@
 }
 
 const char kThickSeparator[] =
-  "// ===================================================================\n";
+    "// ===================================================================\n";
 const char kThinSeparator[] =
-  "// -------------------------------------------------------------------\n";
+    "// -------------------------------------------------------------------\n";
 
 bool CanInitializeByZeroing(const FieldDescriptor* field) {
   if (field->is_repeated() || field->is_extension()) return false;
@@ -250,7 +326,7 @@
 }
 
 string ClassName(const EnumDescriptor* enum_descriptor) {
-  if (enum_descriptor->containing_type() == NULL) {
+  if (enum_descriptor->containing_type() == nullptr) {
     return enum_descriptor->name();
   } else {
     return ClassName(enum_descriptor->containing_type()) + "_" +
@@ -280,7 +356,7 @@
 string DefaultInstanceName(const Descriptor* descriptor) {
   string prefix = descriptor->file()->package().empty() ? "" : "::";
   return prefix + DotsToColons(descriptor->file()->package()) + "::_" +
-      ClassName(descriptor, false) + "_default_instance_";
+         ClassName(descriptor, false) + "_default_instance_";
 }
 
 string ReferenceFunctionName(const Descriptor* descriptor) {
@@ -311,7 +387,7 @@
 }
 
 int EstimateAlignmentSize(const FieldDescriptor* field) {
-  if (field == NULL) return 0;
+  if (field == nullptr) return 0;
   if (field->is_repeated()) return 8;
   switch (field->cpp_type()) {
     case FieldDescriptor::CPPTYPE_BOOL:
@@ -334,13 +410,13 @@
   return -1;  // Make compiler happy.
 }
 
-string FieldConstantName(const FieldDescriptor *field) {
+string FieldConstantName(const FieldDescriptor* field) {
   string field_name = UnderscoresToCamelCase(field->name(), true);
   string result = "k" + field_name + "FieldNumber";
 
   if (!field->is_extension() &&
       field->containing_type()->FindFieldByCamelcaseName(
-        field->camelcase_name()) != field) {
+          field->camelcase_name()) != field) {
     // This field's camelcase name is not unique.  As a hack, add the field
     // number to the constant name.  This makes the constant rather useless,
     // but what can we do?
@@ -366,23 +442,33 @@
 
 const char* PrimitiveTypeName(FieldDescriptor::CppType type) {
   switch (type) {
-    case FieldDescriptor::CPPTYPE_INT32  : return "::google::protobuf::int32";
-    case FieldDescriptor::CPPTYPE_INT64  : return "::google::protobuf::int64";
-    case FieldDescriptor::CPPTYPE_UINT32 : return "::google::protobuf::uint32";
-    case FieldDescriptor::CPPTYPE_UINT64 : return "::google::protobuf::uint64";
-    case FieldDescriptor::CPPTYPE_DOUBLE : return "double";
-    case FieldDescriptor::CPPTYPE_FLOAT  : return "float";
-    case FieldDescriptor::CPPTYPE_BOOL   : return "bool";
-    case FieldDescriptor::CPPTYPE_ENUM   : return "int";
-    case FieldDescriptor::CPPTYPE_STRING : return "::std::string";
-    case FieldDescriptor::CPPTYPE_MESSAGE: return NULL;
+    case FieldDescriptor::CPPTYPE_INT32:
+      return "::google::protobuf::int32";
+    case FieldDescriptor::CPPTYPE_INT64:
+      return "::google::protobuf::int64";
+    case FieldDescriptor::CPPTYPE_UINT32:
+      return "::google::protobuf::uint32";
+    case FieldDescriptor::CPPTYPE_UINT64:
+      return "::google::protobuf::uint64";
+    case FieldDescriptor::CPPTYPE_DOUBLE:
+      return "double";
+    case FieldDescriptor::CPPTYPE_FLOAT:
+      return "float";
+    case FieldDescriptor::CPPTYPE_BOOL:
+      return "bool";
+    case FieldDescriptor::CPPTYPE_ENUM:
+      return "int";
+    case FieldDescriptor::CPPTYPE_STRING:
+      return "::std::string";
+    case FieldDescriptor::CPPTYPE_MESSAGE:
+      return nullptr;
 
-    // No default because we want the compiler to complain if any new
-    // CppTypes are added.
+      // No default because we want the compiler to complain if any new
+      // CppTypes are added.
   }
 
   GOOGLE_LOG(FATAL) << "Can't get here.";
-  return NULL;
+  return nullptr;
 }
 
 string PrimitiveTypeName(const Options& options,
@@ -419,29 +505,47 @@
 
 const char* DeclaredTypeMethodName(FieldDescriptor::Type type) {
   switch (type) {
-    case FieldDescriptor::TYPE_INT32   : return "Int32";
-    case FieldDescriptor::TYPE_INT64   : return "Int64";
-    case FieldDescriptor::TYPE_UINT32  : return "UInt32";
-    case FieldDescriptor::TYPE_UINT64  : return "UInt64";
-    case FieldDescriptor::TYPE_SINT32  : return "SInt32";
-    case FieldDescriptor::TYPE_SINT64  : return "SInt64";
-    case FieldDescriptor::TYPE_FIXED32 : return "Fixed32";
-    case FieldDescriptor::TYPE_FIXED64 : return "Fixed64";
-    case FieldDescriptor::TYPE_SFIXED32: return "SFixed32";
-    case FieldDescriptor::TYPE_SFIXED64: return "SFixed64";
-    case FieldDescriptor::TYPE_FLOAT   : return "Float";
-    case FieldDescriptor::TYPE_DOUBLE  : return "Double";
+    case FieldDescriptor::TYPE_INT32:
+      return "Int32";
+    case FieldDescriptor::TYPE_INT64:
+      return "Int64";
+    case FieldDescriptor::TYPE_UINT32:
+      return "UInt32";
+    case FieldDescriptor::TYPE_UINT64:
+      return "UInt64";
+    case FieldDescriptor::TYPE_SINT32:
+      return "SInt32";
+    case FieldDescriptor::TYPE_SINT64:
+      return "SInt64";
+    case FieldDescriptor::TYPE_FIXED32:
+      return "Fixed32";
+    case FieldDescriptor::TYPE_FIXED64:
+      return "Fixed64";
+    case FieldDescriptor::TYPE_SFIXED32:
+      return "SFixed32";
+    case FieldDescriptor::TYPE_SFIXED64:
+      return "SFixed64";
+    case FieldDescriptor::TYPE_FLOAT:
+      return "Float";
+    case FieldDescriptor::TYPE_DOUBLE:
+      return "Double";
 
-    case FieldDescriptor::TYPE_BOOL    : return "Bool";
-    case FieldDescriptor::TYPE_ENUM    : return "Enum";
+    case FieldDescriptor::TYPE_BOOL:
+      return "Bool";
+    case FieldDescriptor::TYPE_ENUM:
+      return "Enum";
 
-    case FieldDescriptor::TYPE_STRING  : return "String";
-    case FieldDescriptor::TYPE_BYTES   : return "Bytes";
-    case FieldDescriptor::TYPE_GROUP   : return "Group";
-    case FieldDescriptor::TYPE_MESSAGE : return "Message";
+    case FieldDescriptor::TYPE_STRING:
+      return "String";
+    case FieldDescriptor::TYPE_BYTES:
+      return "Bytes";
+    case FieldDescriptor::TYPE_GROUP:
+      return "Group";
+    case FieldDescriptor::TYPE_MESSAGE:
+      return "Message";
 
-    // No default because we want the compiler to complain if any new
-    // types are added.
+      // No default because we want the compiler to complain if any new
+      // types are added.
   }
   GOOGLE_LOG(FATAL) << "Can't get here.";
   return "";
@@ -504,39 +608,37 @@
         return SimpleDtoa(value);
       }
     }
-    case FieldDescriptor::CPPTYPE_FLOAT:
-      {
-        float value = field->default_value_float();
-        if (value == std::numeric_limits<float>::infinity()) {
-          return "std::numeric_limits<float>::infinity()";
-        } else if (value == -std::numeric_limits<float>::infinity()) {
-          return "-std::numeric_limits<float>::infinity()";
-        } else if (value != value) {
-          return "std::numeric_limits<float>::quiet_NaN()";
-        } else {
-          string float_value = SimpleFtoa(value);
-          // If floating point value contains a period (.) or an exponent
-          // (either E or e), then append suffix 'f' to make it a float
-          // literal.
-          if (float_value.find_first_of(".eE") != string::npos) {
-            float_value.push_back('f');
-          }
-          return float_value;
+    case FieldDescriptor::CPPTYPE_FLOAT: {
+      float value = field->default_value_float();
+      if (value == std::numeric_limits<float>::infinity()) {
+        return "std::numeric_limits<float>::infinity()";
+      } else if (value == -std::numeric_limits<float>::infinity()) {
+        return "-std::numeric_limits<float>::infinity()";
+      } else if (value != value) {
+        return "std::numeric_limits<float>::quiet_NaN()";
+      } else {
+        string float_value = SimpleFtoa(value);
+        // If floating point value contains a period (.) or an exponent
+        // (either E or e), then append suffix 'f' to make it a float
+        // literal.
+        if (float_value.find_first_of(".eE") != string::npos) {
+          float_value.push_back('f');
         }
+        return float_value;
       }
+    }
     case FieldDescriptor::CPPTYPE_BOOL:
       return field->default_value_bool() ? "true" : "false";
     case FieldDescriptor::CPPTYPE_ENUM:
       // Lazy:  Generate a static_cast because we don't have a helper function
       //   that constructs the full name of an enum value.
       return strings::Substitute(
-          "static_cast< $0 >($1)",
-          ClassName(field->enum_type(), true),
+          "static_cast< $0 >($1)", ClassName(field->enum_type(), true),
           Int32ToString(field->default_value_enum()->number()));
     case FieldDescriptor::CPPTYPE_STRING:
-      return "\"" + EscapeTrigraphs(
-        CEscape(field->default_value_string())) +
-        "\"";
+      return "\"" +
+             EscapeTrigraphs(CEscape(field->default_value_string())) +
+             "\"";
     case FieldDescriptor::CPPTYPE_MESSAGE:
       return "*" + FieldMessageTypeName(field) +
              "::internal_default_instance()";
@@ -583,8 +685,7 @@
 
 // Escaped function name to eliminate naming conflict.
 string SafeFunctionName(const Descriptor* descriptor,
-                        const FieldDescriptor* field,
-                        const string& prefix) {
+                        const FieldDescriptor* field, const string& prefix) {
   // Do not use FieldName() since it will escape keywords.
   string name = field->name();
   LowerString(&name);
@@ -601,6 +702,25 @@
   return function_name;
 }
 
+bool IsStringInlined(const FieldDescriptor* descriptor,
+                     const Options& options) {
+  if (options.opensource_runtime) return false;
+
+  // TODO(ckennelly): Handle inlining for any.proto.
+  if (IsAnyMessage(descriptor->containing_type(), options)) return false;
+  if (descriptor->containing_type()->options().map_entry()) return false;
+
+  // Limit to proto2, as we rely on has bits to distinguish field presence for
+  // release_$name$.  On proto3, we cannot use the address of the string
+  // instance when the field has been inlined.
+  if (!HasFieldPresence(descriptor->file())) return false;
+
+  if (options.access_info_map) {
+    if (descriptor->is_required()) return true;
+  }
+  return false;
+}
+
 static bool HasLazyFields(const Descriptor* descriptor,
                           const Options& options) {
   for (int field_idx = 0; field_idx < descriptor->field_count(); field_idx++) {
@@ -809,7 +929,7 @@
 enum Utf8CheckMode {
   STRICT = 0,  // Parsing will fail if non UTF-8 data is in string fields.
   VERIFY = 1,  // Only log an error but parsing will succeed.
-  NONE = 2,  // No UTF-8 check.
+  NONE = 2,    // No UTF-8 check.
 };
 
 static bool FieldEnforceUtf8(const FieldDescriptor* field,
@@ -954,7 +1074,7 @@
   return UsingImplicitWeakFields(field->file(), options) &&
          field->type() == FieldDescriptor::TYPE_MESSAGE &&
          !field->is_required() && !field->is_map() &&
-         field->containing_oneof() == NULL &&
+         field->containing_oneof() == nullptr &&
          !IsWellKnownMessage(field->message_type()->file()) &&
          // We do not support implicit weak fields between messages in the same
          // strongly-connected component.
@@ -1114,8 +1234,8 @@
           "#define PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PB_H\n"
           "#include \"$forward_to_basename$.pb.h\"  // IWYU pragma: export\n"
           "#endif  // PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PB_H\n",
-          "forward_to_basename", forward_to_basename,
-          "filename_identifier", FilenameIdentifier(*basename));
+          "forward_to_basename", forward_to_basename, "filename_identifier",
+          FilenameIdentifier(*basename));
 
       if (!options.opensource_runtime) {
         // HACK HACK HACK, tech debt from the deeps of proto1 and SWIG
@@ -1141,8 +1261,8 @@
           "export\n"
           "#endif  // "
           "PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PROTO_H\n",
-          "forward_to_basename", forward_to_basename,
-          "filename_identifier", FilenameIdentifier(*basename));
+          "forward_to_basename", forward_to_basename, "filename_identifier",
+          FilenameIdentifier(*basename));
     }
 
     {
@@ -1174,502 +1294,571 @@
           wiretype != internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
 }
 
-void GenerateStrings(const FieldDescriptor* field, const Options& options,
-                     const Formatter& format, bool check_utf8) {
-  string utf8;
-  if (check_utf8) {
-    utf8 = GetUtf8Suffix(field, options);
-    if (!utf8.empty()) {
-      string name = "nullptr";
-      if (HasDescriptorMethods(field->file(), options)) {
-        name = "\"" + field->full_name() + "\"";
-      }
-      format("ctx->extra_parse_data().SetFieldName($1$);\n", name);
-    }
-  }
-  format(
-      "auto str = msg->$1$_$2$();\n"
-      "if (size > end - ptr + "
-      "::$proto_ns$::internal::ParseContext::kSlopBytes) {\n"
-      "  object = str;\n",
-      field->is_repeated() && !field->is_packable() ? "add" : "mutable",
-      FieldName(field));
-  string name;
-  if (field->options().ctype() == FieldOptions::STRING ||
-      (IsProto1(field->file(), options) &&
-       field->options().ctype() == FieldOptions::STRING_PIECE)) {
-    name = "GreedyStringParser";
-    format("  str->clear();\n");
-    // TODO(gerbens) evaluate security
-    format("  str->reserve(size);\n");
-  } else if (field->options().ctype() == FieldOptions::CORD) {
-    name = "CordParser";
-    format("  str->Clear();\n");
-  } else if (field->options().ctype() == FieldOptions::STRING_PIECE) {
-    name = "StringPieceParser";
-    format("  str->Clear();\n");
-  }
-  format(
-      "  parser_till_end = ::$proto_ns$::internal::$1$$2$;\n"
-      "  goto len_delim_till_end;\n"
-      "}\n"
-      "$GOOGLE_PROTOBUF$_PARSER_ASSERT(::$proto_ns$::internal::StringCheck$2$("
-      "ptr, size, ctx));\n"
-      "::$proto_ns$::internal::Inline$1$(str, ptr, size, ctx);\n"
-      "ptr += size;\n",
-      name, utf8);
-}
+class ParseLoopGenerator {
+ public:
+  ParseLoopGenerator(const Options& options, MessageSCCAnalyzer* scc_analyzer,
+                     io::Printer* printer)
+      : scc_analyzer_(scc_analyzer), options_(options), format_(printer) {}
 
-void GenerateLengthDelim(
-                      const FieldDescriptor* field, const Options& options,
-                      MessageSCCAnalyzer* scc_analyzer,
-                      const Formatter& format) {
-  format(
-      "ptr = Varint::Parse32Inline(ptr, &size);\n"
-      "$GOOGLE_PROTOBUF$_PARSER_ASSERT(ptr);\n");
-  if (!IsProto1(field->file(), options) && field->is_packable()) {
-    if (!HasPreservingUnknownEnumSemantics(field->file()) &&
-        field->type() == FieldDescriptor::TYPE_ENUM) {
-      format(
-          "ctx->extra_parse_data().SetEnumValidator($1$_IsValid, "
-          "msg->mutable_unknown_fields(), $2$);\n"
-          "parser_till_end = "
-          "::$proto_ns$::internal::PackedValidEnumParser$3$;\n"
-          "object = msg->mutable_$4$();\n",
-          QualifiedClassName(field->enum_type()), field->number(),
-          UseUnknownFieldSet(field->file(), options) ? "" : "Lite",
-          FieldName(field));
+  void GenerateParserLoop(const Descriptor* descriptor) {
+    format_.Set("classname", ClassName(descriptor));
+    format_.Set("proto_ns", ProtobufNamespace(options_));
+    format_.Set("GOOGLE_PROTOBUF", MacroPrefix(options_));
+    std::map<string, string> vars;
+    SetCommonVars(options_, &vars);
+    format_.AddMap(vars);
+
+    std::vector<const FieldDescriptor*> ordered_fields;
+    for (auto field : FieldRange(descriptor)) {
+      ordered_fields.push_back(field);
+    }
+    std::sort(ordered_fields.begin(), ordered_fields.end(),
+              [](const FieldDescriptor* a, const FieldDescriptor* b) {
+                return a->number() < b->number();
+              });
+
+    format_(
+        "const char* $classname$::_InternalParse(const char* begin, const "
+        "char* "
+        "end, void* object,\n"
+        "                  ::$proto_ns$::internal::ParseContext* ctx) {\n"
+        "  auto msg = static_cast<$classname$*>(object);\n"
+        "  $uint32$ size; (void)size;\n"
+        "  int depth; (void)depth;\n"
+        "  $uint32$ tag;\n"
+        "  ::$proto_ns$::internal::ParseFunc parser_till_end; "
+        "(void)parser_till_end;\n"
+        "  auto ptr = begin;\n"
+        "  while (ptr < end) {\n"
+        "    ptr = ::$proto_ns$::io::Parse32(ptr, &tag);\n"
+        "    $GOOGLE_PROTOBUF$_PARSER_ASSERT(ptr);\n"
+        "    switch (tag >> 3) {\n");
+
+    format_.Indent();
+    format_.Indent();
+    format_.Indent();
+
+    bool use_handle_unusual = false;
+    for (const auto* field : ordered_fields) {
+      if (IsProto1(descriptor->file(), options_)) {
+        if (field->number() >= (1 << 14)) continue;
+      }
+      // Print the field's (or oneof's) proto-syntax definition as a comment.
+      // We don't want to print group bodies so we cut off after the first
+      // line.
+      string def;
+      {
+        DebugStringOptions options;
+        options.elide_group_body = true;
+        options.elide_oneof_body = true;
+        def = field->DebugStringWithOptions(options);
+        def = def.substr(0, def.find_first_of('\n'));
+      }
+      format_(
+          "// $1$\n"
+          "case $2$: {\n",
+          def, field->number());
+      format_.Indent();
+      use_handle_unusual = true;
+      GenerateCaseBody(field);
+      format_.Outdent();
+      format_("}\n");  // case
+    }                  // for fields
+    format_("default: {\n");
+    if (use_handle_unusual) format_("handle_unusual:\n");
+    format_(
+        "  if ((tag & 7) == 4 || tag == 0) {\n"
+        "    ctx->EndGroup(tag);\n"
+        "    return ptr;\n"
+        "  }\n");
+    if (IsMapEntryMessage(descriptor)) {
+      format_(
+          "  break;\n"
+          "}\n");
     } else {
-      format(
-          "parser_till_end = ::$proto_ns$::internal::Packed$1$Parser;\n"
-          "object = msg->mutable_$2$();\n",
-          DeclaredTypeMethodName(field->type()), FieldName(field));
-    }
-    format(
-        "if (size > end - ptr) goto len_delim_till_end;\n"
-        "auto newend = ptr + size;\n"
-        "if (size) ptr = parser_till_end(ptr, newend, object, ctx);\n"
-        "$GOOGLE_PROTOBUF$_PARSER_ASSERT(ptr == newend);\n");
-  } else {
-    auto field_type = field->type();
-    if (IsProto1(field->file(), options)) {
-      if (field->is_packable()) {
-        // Sigh ... packed fields endup as a string in proto1
-        field_type = FieldDescriptor::TYPE_BYTES;
-      }
-      if (field_type == FieldDescriptor::TYPE_STRING) {
-        // In proto1 strings are treated as bytes
-        field_type = FieldDescriptor::TYPE_BYTES;
-      }
-    }
-    switch (field_type) {
-      case FieldDescriptor::TYPE_STRING:
-        GenerateStrings(field, options, format, true /* utf8 */);
-        break;
-      case FieldDescriptor::TYPE_BYTES:
-        GenerateStrings(field, options, format, false /* utf8 */);
-        break;
-      case FieldDescriptor::TYPE_MESSAGE: {
-        GOOGLE_CHECK(field->message_type());
-        if (!IsProto1(field->file(), options) && field->is_map()) {
-          const FieldDescriptor* val =
-              field->message_type()->FindFieldByName("value");
-          GOOGLE_CHECK(val);
-          if (HasFieldPresence(field->file()) &&
-              val->type() == FieldDescriptor::TYPE_ENUM) {
-            format(
-                "ctx->extra_parse_data().field_number = $1$;\n"
-                "ctx->extra_parse_data().unknown_fields = "
-                "&msg->_internal_metadata_;\n",
-                field->number());
-          }
-          format(
-              "parser_till_end = ::$proto_ns$::internal::SlowMapEntryParser;\n"
-              "auto parse_map = $1$::_ParseMap;\n"
-              "ctx->extra_parse_data().payload.clear();\n"
-              "ctx->extra_parse_data().parse_map = parse_map;\n"
-              "object = &msg->$2$_;\n"
-              "if (size > end - ptr) goto len_delim_till_end;\n"
-              "auto newend = ptr + size;\n"
-              "GOOGLE_PROTOBUF_PARSER_ASSERT(parse_map(ptr, newend, "
-              "object, ctx));\n"
-              "ptr = newend;\n",
-              QualifiedClassName(field->message_type()), FieldName(field));
-          break;
-        }
-        if (!IsProto1(field->file(), options) && IsLazy(field, options)) {
-          if (field->containing_oneof() != nullptr) {
-            format(
-                "if (!msg->has_$1$()) {\n"
-                "  msg->clear_$1$();\n"
-                "  msg->$2$_.$1$_ = ::google::protobuf::Arena::CreateMessage<\n"
-                "      ::google::protobuf::internal::LazyField>(msg->GetArenaNoVirtual());\n"
-                "  msg->set_has_$1$();\n"
-                "}\n"
-                "auto parse_closure = msg->$2$_.$1$_->_ParseClosure();\n",
-                FieldName(field), field->containing_oneof()->name());
-          } else if (HasFieldPresence(field->file())) {
-            format(
-                "HasBitSetters::set_has_$1$(msg);\n"
-                "auto parse_closure = msg->$1$_._ParseClosure();\n",
-                FieldName(field));
+      if (descriptor->extension_range_count() > 0) {
+        format_("if (");
+        for (int i = 0; i < descriptor->extension_range_count(); i++) {
+          const Descriptor::ExtensionRange* range =
+              descriptor->extension_range(i);
+          if (i > 0) format_(" ||\n    ");
+
+          uint32 start_tag = WireFormatLite::MakeTag(
+              range->start, static_cast<WireFormatLite::WireType>(0));
+          uint32 end_tag = WireFormatLite::MakeTag(
+              range->end, static_cast<WireFormatLite::WireType>(0));
+
+          if (range->end > FieldDescriptor::kMaxNumber) {
+            format_("($1$u <= tag)", start_tag);
           } else {
-            format(
-                "auto parse_closure = msg->$1$_._ParseClosure();\n",
-                FieldName(field));
+            format_("($1$u <= tag && tag < $2$u)", start_tag, end_tag);
           }
-          format(
-              "parser_till_end = parse_closure.func;\n"
-              "object = parse_closure.object;\n"
-              "if (size > end - ptr) goto len_delim_till_end;\n"
-              "auto newend = ptr + size;\n"
-              "GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(parse_closure, ptr, newend));\n"
-              "ptr = newend;\n");
-          break;
         }
-        if (IsImplicitWeakField(field, options, scc_analyzer)) {
-          if (!field->is_repeated()) {
-            format("object = HasBitSetters::mutable_$1$(msg);\n",
-                   FieldName(field));
-          } else {
-            format(
-                "object = "
-                "CastToBase(&msg->$1$_)->AddWeak(reinterpret_cast<const "
-                "::google::protobuf::MessageLite*>(&$2$::_$3$_default_instance_));\n",
-                FieldName(field), Namespace(field->message_type()),
-                ClassName(field->message_type()));
-          }
-          format(
-              "parser_till_end = static_cast<::$proto_ns$::MessageLite*>("
-              "object)->_ParseFunc();\n");
-        } else if (IsWeak(field, options)) {
-          if (IsProto1(field->file(), options)) {
-            format("object = msg->internal_mutable_$1$();\n",
-                   FieldName(field));
-          } else {
-            format(
-                "object = msg->_weak_field_map_.MutableMessage($1$, "
-                "_$classname$_default_instance_.$2$_);\n",
-                field->number(), FieldName(field));
-          }
-          format(
-              "parser_till_end = static_cast<::$proto_ns$::MessageLite*>("
-              "object)->_ParseFunc();\n");
-        } else {
-          format(
-              "parser_till_end = $1$::_InternalParse;\n"
-              "object = msg->$2$_$3$();\n",
-              QualifiedClassName(field->message_type()),
-              field->is_repeated() ? "add" : "mutable", FieldName(field));
-        }
-        format(
-            "if (size > end - ptr) goto len_delim_till_end;\n"
-            "auto newend = ptr + size;\n"
-            "bool ok = ctx->ParseExactRange({parser_till_end, object},\n"
-            "                               ptr, newend);\n"
-            "$GOOGLE_PROTOBUF$_PARSER_ASSERT(ok);\n"
-            "ptr = newend;\n");
-        break;
+        format_(") {\n");
+        format_(
+            "  auto res = msg->_extensions_.ParseField(tag, {_InternalParse, "
+            "msg}, ptr, end,\n"
+            "      internal_default_instance(), &msg->_internal_metadata_, "
+            "ctx);\n"
+            "  ptr = res.first;\n"
+            "  $GOOGLE_PROTOBUF$_PARSER_ASSERT(ptr != nullptr);\n"
+            "  if (res.second) return ptr;\n"
+            "  continue;\n"
+            "}\n");
       }
-      default:
-        GOOGLE_LOG(FATAL) << "Illegal combination for length delimited wiretype "
-                   << " filed type is " << field->type();
-    }
-  }
-}
-
-void GenerateCaseBody(internal::WireFormatLite::WireType wiretype,
-                      const FieldDescriptor* field, const Options& options,
-                      MessageSCCAnalyzer* scc_analyzer,
-                      const Formatter& format) {
-  using internal::WireFormat;
-  using internal::WireFormatLite;
-
-  if (ShouldRepeat(field, wiretype)) {
-    format("do {\n");
-    format.Indent();
-  }
-  switch (wiretype) {
-    case WireFormatLite::WIRETYPE_VARINT: {
-      format(
-          "$uint64$ val;\n"
-          "ptr = Varint::Parse64(ptr, &val);\n"
-          "$GOOGLE_PROTOBUF$_PARSER_ASSERT(ptr);\n");
-      string type = PrimitiveTypeName(options, field->cpp_type());
-      if ((field->type() == FieldDescriptor::TYPE_SINT32 ||
-           field->type() == FieldDescriptor::TYPE_SINT64) &&
-          !IsProto1(field->file(), options)) {
-        int size = EstimateAlignmentSize(field) * 8;
-        format(
-            "$1$ value = "
-            "::$proto_ns$::internal::WireFormatLite::ZigZagDecode$2$(val);\n",
-            type, size);
-      } else if (field->type() == FieldDescriptor::TYPE_ENUM &&
-                 !IsProto1(field->file(), options)) {
-        if (!HasPreservingUnknownEnumSemantics(field->file())) {
-          format(
-              "if (!$1$_IsValid(val)) {\n"
-              "  ::$proto_ns$::internal::WriteVarint($2$, val, "
-              "msg->mutable_unknown_fields());\n"
-              "  break;\n"
-              "}\n",
-              QualifiedClassName(field->enum_type()), field->number());
-        }
-        format("$1$ value = static_cast<$1$>(val);\n",
-               QualifiedClassName(field->enum_type()));
-      } else {
-        format("$1$ value = val;\n", type);
-      }
-      if (field->is_repeated()) {
-        format("msg->add_$1$(value);\n", FieldName(field));
-      } else {
-        format("msg->set_$1$(value);\n", FieldName(field));
-      }
-      break;
-    }
-    case WireFormatLite::WIRETYPE_FIXED64: {
-      string type = PrimitiveTypeName(options, field->cpp_type());
-      format(
-          "$1$ val;\n"
-          "::std::memcpy(&val, ptr, 8);\n"
-          "ptr += 8;\n",
-          type);
-      if (field->is_repeated()) {
-        format("msg->add_$1$(val);\n", FieldName(field));
-      } else {
-        format("msg->set_$1$(val);\n", FieldName(field));
-      }
-      break;
-    }
-    case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: {
-      GenerateLengthDelim(field, options, scc_analyzer, format);
-      break;
-    }
-    case WireFormatLite::WIRETYPE_START_GROUP: {
-      format(
-          "parser_till_end = $1$::_InternalParse;\n"
-          "object = msg->$2$_$3$();\n"
-          "auto res = ctx->ParseGroup(tag, {parser_till_end, object}, ptr, "
-          "end, "
-          "&depth);\n"
-          "ptr = res.first;\n"
-          "$GOOGLE_PROTOBUF$_PARSER_ASSERT(ptr);\n"
-          "if (res.second) goto group_continues;\n",
-          QualifiedClassName(field->message_type()),
-          field->is_repeated() ? "add" : "mutable", FieldName(field));
-      break;
-    }
-    case WireFormatLite::WIRETYPE_END_GROUP: {
-      GOOGLE_LOG(FATAL) << "Can't have end group field\n";
-      break;
-    }
-    case WireFormatLite::WIRETYPE_FIXED32: {
-      string type = PrimitiveTypeName(options, field->cpp_type());
-      format(
-          "$1$ val;\n"
-          "std::memcpy(&val, ptr, 4);\n"
-          "ptr += 4;\n",
-          type);
-      if (field->is_repeated()) {
-        format("msg->add_$1$(val);\n", FieldName(field));
-      } else {
-        format("msg->set_$1$(val);\n", FieldName(field));
-      }
-      break;
-    }
-  }  // switch (wire_type)
-
-  if (ShouldRepeat(field, wiretype)) {
-    format("if (ptr >= end) break;\n");
-    uint32 x = field->number() * 8 + wiretype;
-    uint64 y = 0;
-    int cnt = 0;
-    do {
-      y += static_cast<uint64>((x & 0x7F) + (x >= 128 ? 128 : 0))
-           << (cnt++ * 8);
-      x >>= 7;
-    } while (x);
-    uint64 mask = (1ull << (cnt * 8)) - 1;
-    format.Outdent();
-    format(
-        "} while ((::$proto_ns$::io::UnalignedLoad<$uint64$>(ptr) & $1$) == "
-        "$2$ && (ptr += $3$));\n",
-        mask, y, cnt);
-  }
-  format("break;\n");
-}
-
-void GenerateCaseBody(const FieldDescriptor* field, const Options& options,
-                      MessageSCCAnalyzer* scc_analyzer,
-                      const Formatter& format) {
-  using internal::WireFormat;
-  using internal::WireFormatLite;
-
-  if (!IsProto1(field->file(), options) && field->is_packable()) {
-    auto expected_wiretype = WireFormat::WireTypeForFieldType(field->type());
-    GOOGLE_CHECK(expected_wiretype != WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
-    uint32 expected_tag =
-        WireFormatLite::MakeTag(field->number(), expected_wiretype);
-    auto fallback_wiretype = WireFormatLite::WIRETYPE_LENGTH_DELIMITED;
-    uint32 fallback_tag =
-        WireFormatLite::MakeTag(field->number(), fallback_wiretype);
-
-    if (field->is_packed()) {
-      std::swap(expected_tag, fallback_tag);
-      std::swap(expected_wiretype, fallback_wiretype);
-    }
-
-    format("if (static_cast<$uint8$>(tag) == $1$) {\n", expected_tag & 0xFF);
-    format.Indent();
-    GenerateCaseBody(expected_wiretype, field, options, scc_analyzer, format);
-    format.Outdent();
-    format(
-        "} else if (static_cast<$uint8$>(tag) != $1$) goto handle_unusual;\n",
-        fallback_tag & 0xFF);
-    GenerateCaseBody(fallback_wiretype, field, options, scc_analyzer, format);
-  } else {
-    auto wiretype = WireFormat::WireTypeForField(field);
-    format("if (static_cast<$uint8$>(tag) != $1$) goto handle_unusual;\n",
-           WireFormat::MakeTag(field) & 0xFF);
-    GenerateCaseBody(wiretype, field, options, scc_analyzer, format);
-  }
-}
-
-void GenerateParserLoop(const Descriptor* descriptor, const Options& options,
-                        MessageSCCAnalyzer* scc_analyzer,
-                        io::Printer* printer) {
-  using internal::WireFormat;
-  using internal::WireFormatLite;
-
-  Formatter format(printer);
-  format.Set("classname", ClassName(descriptor));
-  format.Set("proto_ns", ProtobufNamespace(options));
-  std::map<string, string> vars;
-  SetCommonVars(options, &vars);
-  format.AddMap(vars);
-
-  std::vector<const FieldDescriptor*> ordered_fields;
-  for (auto field : FieldRange(descriptor)) {
-    ordered_fields.push_back(field);
-  }
-  std::sort(ordered_fields.begin(), ordered_fields.end(),
-            [](const FieldDescriptor* a, const FieldDescriptor* b) {
-              return a->number() < b->number();
-            });
-
-  format(
-      "const char* $classname$::_InternalParse(const char* begin, const char* "
-      "end, void* object,\n"
-      "                  ::$proto_ns$::internal::ParseContext* ctx) {\n"
-      "  auto msg = static_cast<$classname$*>(object);\n"
-      "  $uint32$ size; (void)size;\n"
-      "  int depth; (void)depth;\n"
-      "  $uint32$ tag;\n"
-      "  ::$proto_ns$::internal::ParseFunc parser_till_end; "
-      "(void)parser_till_end;\n"
-      "  auto ptr = begin;\n"
-      "  while (ptr < end) {\n"
-      "    ptr = Varint::Parse32Inline(ptr, &tag);\n"
-      "    $GOOGLE_PROTOBUF$_PARSER_ASSERT(ptr);\n"
-      "    switch (tag >> 3) {\n");
-
-  format.Indent();
-  format.Indent();
-  format.Indent();
-
-  for (const auto* field : ordered_fields) {
-    if (IsProto1(descriptor->file(), options)) {
-      if (field->number() >= (1 << 14)) continue;
-    }
-    // Print the field's (or oneof's) proto-syntax definition as a comment.
-    // We don't want to print group bodies so we cut off after the first
-    // line.
-    string def;
-    {
-      DebugStringOptions options;
-      options.elide_group_body = true;
-      options.elide_oneof_body = true;
-      def = field->DebugStringWithOptions(options);
-      def = def.substr(0, def.find_first_of('\n'));
-    }
-    format(
-        "// $1$\n"
-        "case $2$: {\n",
-        def, field->number());
-    format.Indent();
-    GenerateCaseBody(field, options, scc_analyzer, format);
-    format.Outdent();
-    format("}\n");  // case
-  }                 // for fields
-  format(
-      "default: {\n"
-      "handle_unusual: (void)&&handle_unusual;\n"
-      "  if ((tag & 7) == 4 || tag == 0) {\n"
-      "    ctx->EndGroup(tag);\n"
-      "    return ptr;\n"
-      "  }\n");
-  if (IsMapEntryMessage(descriptor)) {
-    format(
-        "  break;\n"
-        "}\n");
-  } else {
-    if (descriptor->extension_range_count() > 0) {
-      format("if (");
-      for (int i = 0; i < descriptor->extension_range_count(); i++) {
-        const Descriptor::ExtensionRange* range =
-            descriptor->extension_range(i);
-        if (i > 0) format(" ||\n    ");
-
-        uint32 start_tag = WireFormatLite::MakeTag(
-            range->start, static_cast<WireFormatLite::WireType>(0));
-        uint32 end_tag = WireFormatLite::MakeTag(
-            range->end, static_cast<WireFormatLite::WireType>(0));
-
-        if (range->end > FieldDescriptor::kMaxNumber) {
-          format("($1$u <= tag)", start_tag);
-        } else {
-          format("($1$u <= tag && tag < $2$u)", start_tag, end_tag);
-        }
-      }
-      format(") {\n");
-      format(
-          "  auto res = msg->_extensions_.ParseField(tag, {_InternalParse, "
-          "msg}, ptr, end,\n"
-          "      internal_default_instance(), &msg->_internal_metadata_, "
+      format_(
+          "  auto res = UnknownFieldParse(tag, {_InternalParse, msg},\n"
+          "    ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), "
           "ctx);\n"
           "  ptr = res.first;\n"
           "  $GOOGLE_PROTOBUF$_PARSER_ASSERT(ptr != nullptr);\n"
           "  if (res.second) return ptr;\n"
-          "  continue;\n"
-          "}\n");
+          "}\n");  // default case
     }
-    format(
-        "  auto res = UnknownFieldParse(tag, {_InternalParse, msg},\n"
-        "    ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), "
-        "ctx);\n"
-        "  ptr = res.first;\n"
-        "  $GOOGLE_PROTOBUF$_PARSER_ASSERT(ptr != nullptr);\n"
-        "  if (res.second) return ptr;\n"
-        "}\n");  // default case
-  }
-  format.Outdent();
-  format.Outdent();
-  format.Outdent();
-  format(
-      "    }  // switch\n"
-      "  }  // while\n"
-      "  return ptr;\n"
-      "len_delim_till_end: (void)&&len_delim_till_end;\n"
-      "  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},\n"
-      "                                 {parser_till_end, object}, size);\n"
-      "group_continues: (void)&&group_continues;\n"
-      "  $DCHK$(ptr >= end);\n"
+    format_.Outdent();
+    format_.Outdent();
+    format_.Outdent();
+    format_(
+        "    }  // switch\n"
+        "  }  // while\n"
+        "  return ptr;\n");
+    if (use_length_delimited_) {
+      format_(
+          "len_delim_till_end:\n"
+          "  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},\n"
+          "                               {parser_till_end, object}, size);\n");
+    }
+    if (use_group_) {
       // Group crossed end and must be continued. Either this a parse failure
       // or we need to resume on the next chunk and thus save the state.
-      "  $GOOGLE_PROTOBUF$_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg},"
-      " {parser_till_end, object}, depth, tag));\n"
-      "  return ptr;\n"
-      "}\n");
+      format_(
+          "group_continues:\n"
+          "  $DCHK$(ptr >= end);\n"
+          "  $GOOGLE_PROTOBUF$_PARSER_ASSERT(ctx->StoreGroup(\n   "
+          "   {_InternalParse, msg}, {parser_till_end, object}, depth, tag));\n"
+          "  return ptr;\n");
+    }
+    format_("}\n");
+  }
+
+ private:
+  MessageSCCAnalyzer* scc_analyzer_;
+  const Options& options_;
+  Formatter format_;
+  bool use_length_delimited_ = false;
+  bool use_group_ = false;
+
+  using WireFormat = internal::WireFormat;
+  using WireFormatLite = internal::WireFormatLite;
+
+  void GenerateArenaString(const FieldDescriptor* field, const string& utf8) {
+    format_(
+        "if (size > end - ptr + "
+        "::$proto_ns$::internal::ParseContext::kSlopBytes) {\n"
+        "  auto str = msg->mutable_$1$();\n"
+        "  str->clear();\n"
+        // TODO(gerbens) evaluate security
+        "  str->reserve(size);\n"
+        "  object = str;\n"
+        "  parser_till_end = ::$proto_ns$::internal::GreedyStringParser$2$;\n"
+        "  goto len_delim_till_end;\n"
+        "}\n"
+        "$GOOGLE_PROTOBUF$_PARSER_ASSERT(::$proto_ns$::internal::StringCheck$2$"
+        "(ptr, size, ctx));\n",
+        FieldName(field), utf8);
+    if (HasFieldPresence(field->file())) {
+      format_("HasBitSetters::set_has_$1$(msg);\n", FieldName(field));
+    }
+    format_(
+        "::$proto_ns$::internal::CopyIntoArenaString(ptr, size, &msg->$1$_, "
+        "msg->GetArenaNoVirtual());\n"
+        "ptr += size;\n",
+        FieldName(field));
+  }
+
+  void GenerateStrings(const FieldDescriptor* field, bool check_utf8) {
+    string utf8;
+    if (check_utf8) {
+      utf8 = GetUtf8Suffix(field, options_);
+      if (!utf8.empty()) {
+        string name = "nullptr";
+        if (HasDescriptorMethods(field->file(), options_)) {
+          name = "\"" + field->full_name() + "\"";
+        }
+        format_("ctx->extra_parse_data().SetFieldName($1$);\n", name);
+      }
+    }
+    FieldOptions::CType ctype = FieldOptions::STRING;
+    if (!options_.opensource_runtime) {
+      // Open source doesn't support other ctypes;
+      ctype = field->options().ctype();
+      if (IsProto1(field->file(), options_) &&
+          ctype == FieldOptions::STRING_PIECE) {
+        // proto1 doesn't support STRING_PIECE
+        ctype = FieldOptions::STRING;
+      }
+    }
+    if (field->file()->options().cc_enable_arenas() && !field->is_repeated() &&
+        !options_.opensource_runtime &&
+        GetOptimizeFor(field->file(), options_) != FileOptions::LITE_RUNTIME &&
+        // For now only use arena string for strings with empty defaults.
+        field->default_value_string().empty() &&
+        !IsProto1(field->file(), options_) &&
+        !IsStringInlined(field, options_) &&
+        field->containing_oneof() == nullptr && ctype == FieldOptions::STRING) {
+      GenerateArenaString(field, utf8);
+      return;
+    }
+    format_(
+        "auto str = msg->$1$_$2$();\n"
+        "if (size > end - ptr + "
+        "::$proto_ns$::internal::ParseContext::kSlopBytes) {\n"
+        "  object = str;\n",
+        field->is_repeated() && !field->is_packable() ? "add" : "mutable",
+        FieldName(field));
+    string name;
+    switch (ctype) {
+      case FieldOptions::STRING:
+        name = "GreedyStringParser";
+        format_(
+            "  str->clear();\n"
+            // TODO(gerbens) evaluate security
+            "  str->reserve(size);\n");
+        break;
+      case FieldOptions::CORD:
+        name = "CordParser";
+        format_("  str->Clear();\n");
+        break;
+      case FieldOptions::STRING_PIECE:
+        name = "StringPieceParser";
+        format_("  str->Clear();\n");
+        break;
+    }
+    format_(
+        "  parser_till_end = ::$proto_ns$::internal::$1$$2$;\n"
+        "  goto len_delim_till_end;\n"
+        "}\n"
+        "$GOOGLE_PROTOBUF$_PARSER_ASSERT(::$proto_ns$::internal::StringCheck$2$"
+        "("
+        "ptr, size, ctx));\n"
+        "::$proto_ns$::internal::Inline$1$(str, ptr, size, ctx);\n"
+        "ptr += size;\n",
+        name, utf8);
+  }
+
+  void GenerateLengthDelim(const FieldDescriptor* field) {
+    format_(
+        "ptr = ::$proto_ns$::io::Parse32(ptr, &size);\n"
+        "$GOOGLE_PROTOBUF$_PARSER_ASSERT(ptr);\n");
+    if (!IsProto1(field->file(), options_) && field->is_packable()) {
+      if (!HasPreservingUnknownEnumSemantics(field->file()) &&
+          field->type() == FieldDescriptor::TYPE_ENUM) {
+        format_(
+            "ctx->extra_parse_data().SetEnumValidator($1$_IsValid, "
+            "msg->mutable_unknown_fields(), $2$);\n"
+            "parser_till_end = "
+            "::$proto_ns$::internal::PackedValidEnumParser$3$;\n"
+            "object = msg->mutable_$4$();\n",
+            QualifiedClassName(field->enum_type()), field->number(),
+            UseUnknownFieldSet(field->file(), options_) ? "" : "Lite",
+            FieldName(field));
+      } else {
+        format_(
+            "parser_till_end = ::$proto_ns$::internal::Packed$1$Parser;\n"
+            "object = msg->mutable_$2$();\n",
+            DeclaredTypeMethodName(field->type()), FieldName(field));
+      }
+      format_(
+          "if (size > end - ptr) goto len_delim_till_end;\n"
+          "auto newend = ptr + size;\n"
+          "if (size) ptr = parser_till_end(ptr, newend, object, ctx);\n"
+          "$GOOGLE_PROTOBUF$_PARSER_ASSERT(ptr == newend);\n");
+    } else {
+      auto field_type = field->type();
+      if (IsProto1(field->file(), options_)) {
+        if (field->is_packable()) {
+          // Sigh ... packed fields endup as a string in proto1
+          field_type = FieldDescriptor::TYPE_BYTES;
+        }
+        if (field_type == FieldDescriptor::TYPE_STRING) {
+          // In proto1 strings are treated as bytes
+          field_type = FieldDescriptor::TYPE_BYTES;
+        }
+      }
+      switch (field_type) {
+        case FieldDescriptor::TYPE_STRING:
+          GenerateStrings(field, true /* utf8 */);
+          break;
+        case FieldDescriptor::TYPE_BYTES:
+          GenerateStrings(field, false /* utf8 */);
+          break;
+        case FieldDescriptor::TYPE_MESSAGE: {
+          GOOGLE_CHECK(field->message_type());
+          if (!IsProto1(field->file(), options_) && field->is_map()) {
+            const FieldDescriptor* val =
+                field->message_type()->FindFieldByName("value");
+            GOOGLE_CHECK(val);
+            if (HasFieldPresence(field->file()) &&
+                val->type() == FieldDescriptor::TYPE_ENUM) {
+              format_(
+                  "ctx->extra_parse_data().field_number = $1$;\n"
+                  "ctx->extra_parse_data().unknown_fields = "
+                  "&msg->_internal_metadata_;\n",
+                  field->number());
+            }
+            format_(
+                "parser_till_end = "
+                "::$proto_ns$::internal::SlowMapEntryParser;\n"
+                "auto parse_map = $1$::_ParseMap;\n"
+                "ctx->extra_parse_data().payload.clear();\n"
+                "ctx->extra_parse_data().parse_map = parse_map;\n"
+                "object = &msg->$2$_;\n"
+                "if (size > end - ptr) goto len_delim_till_end;\n"
+                "auto newend = ptr + size;\n"
+                "$GOOGLE_PROTOBUF$_PARSER_ASSERT(parse_map(ptr, newend, "
+                "object, ctx));\n"
+                "ptr = newend;\n",
+                QualifiedClassName(field->message_type()), FieldName(field));
+            break;
+          }
+          if (!IsProto1(field->file(), options_) && IsLazy(field, options_)) {
+            if (field->containing_oneof() != nullptr) {
+              format_(
+                  "if (!msg->has_$1$()) {\n"
+                  "  msg->clear_$1$();\n"
+                  "  msg->$2$_.$1$_ = ::$proto_ns$::Arena::CreateMessage<\n"
+                  "      ::$proto_ns$::internal::LazyField>("
+                  "msg->GetArenaNoVirtual());\n"
+                  "  msg->set_has_$1$();\n"
+                  "}\n"
+                  "auto parse_closure = msg->$2$_.$1$_->_ParseClosure();\n",
+                  FieldName(field), field->containing_oneof()->name());
+            } else if (HasFieldPresence(field->file())) {
+              format_(
+                  "HasBitSetters::set_has_$1$(msg);\n"
+                  "auto parse_closure = msg->$1$_._ParseClosure();\n",
+                  FieldName(field));
+            } else {
+              format_("auto parse_closure = msg->$1$_._ParseClosure();\n",
+                      FieldName(field));
+            }
+            format_(
+                "parser_till_end = parse_closure.func;\n"
+                "object = parse_closure.object;\n"
+                "if (size > end - ptr) goto len_delim_till_end;\n"
+                "auto newend = ptr + size;\n"
+                "$GOOGLE_PROTOBUF$_PARSER_ASSERT(ctx->ParseExactRange(\n"
+                "    parse_closure, ptr, newend));\n"
+                "ptr = newend;\n");
+            break;
+          }
+          if (IsImplicitWeakField(field, options_, scc_analyzer_)) {
+            if (!field->is_repeated()) {
+              format_("object = HasBitSetters::mutable_$1$(msg);\n",
+                      FieldName(field));
+            } else {
+              format_(
+                  "object = "
+                  "CastToBase(&msg->$1$_)->AddWeak(reinterpret_cast<const "
+                  "::$proto_ns$::MessageLite*>(&$2$::_$3$_default_instance_));"
+                  "\n",
+                  FieldName(field), Namespace(field->message_type()),
+                  ClassName(field->message_type()));
+            }
+            format_(
+                "parser_till_end = static_cast<::$proto_ns$::MessageLite*>("
+                "object)->_ParseFunc();\n");
+          } else if (IsWeak(field, options_)) {
+            if (IsProto1(field->file(), options_)) {
+              format_("object = msg->internal_mutable_$1$();\n",
+                      FieldName(field));
+            } else {
+              format_(
+                  "object = msg->_weak_field_map_.MutableMessage($1$, "
+                  "_$classname$_default_instance_.$2$_);\n",
+                  field->number(), FieldName(field));
+            }
+            format_(
+                "parser_till_end = static_cast<::$proto_ns$::MessageLite*>("
+                "object)->_ParseFunc();\n");
+          } else {
+            format_(
+                "parser_till_end = $1$::_InternalParse;\n"
+                "object = msg->$2$_$3$();\n",
+                QualifiedClassName(field->message_type()),
+                field->is_repeated() ? "add" : "mutable", FieldName(field));
+          }
+          format_(
+              "if (size > end - ptr) goto len_delim_till_end;\n"
+              "auto newend = ptr + size;\n"
+              "bool ok = ctx->ParseExactRange({parser_till_end, object},\n"
+              "                               ptr, newend);\n"
+              "$GOOGLE_PROTOBUF$_PARSER_ASSERT(ok);\n"
+              "ptr = newend;\n");
+          break;
+        }
+        default:
+          GOOGLE_LOG(FATAL) << "Illegal combination for length delimited wiretype "
+                     << " filed type is " << field->type();
+      }
+    }
+  }
+
+  void GenerateCaseBody(internal::WireFormatLite::WireType wiretype,
+                        const FieldDescriptor* field) {
+    if (ShouldRepeat(field, wiretype)) {
+      format_("do {\n");
+      format_.Indent();
+    }
+    switch (wiretype) {
+      case WireFormatLite::WIRETYPE_VARINT: {
+        format_(
+            "$uint64$ val;\n"
+            "ptr = ::$proto_ns$::io::Parse64(ptr, &val);\n"
+            "$GOOGLE_PROTOBUF$_PARSER_ASSERT(ptr);\n");
+        string type = PrimitiveTypeName(options_, field->cpp_type());
+        if ((field->type() == FieldDescriptor::TYPE_SINT32 ||
+             field->type() == FieldDescriptor::TYPE_SINT64) &&
+            !IsProto1(field->file(), options_)) {
+          int size = field->type() == FieldDescriptor::TYPE_SINT32 ? 32 : 64;
+          format_(
+              "$1$ value = "
+              "::$proto_ns$::internal::WireFormatLite::ZigZagDecode$2$(val);\n",
+              type, size);
+        } else if (field->type() == FieldDescriptor::TYPE_ENUM &&
+                   !IsProto1(field->file(), options_)) {
+          if (!HasPreservingUnknownEnumSemantics(field->file())) {
+            format_(
+                "if (!$1$_IsValid(val)) {\n"
+                "  ::$proto_ns$::internal::WriteVarint($2$, val, "
+                "msg->mutable_unknown_fields());\n"
+                "  break;\n"
+                "}\n",
+                QualifiedClassName(field->enum_type()), field->number());
+          }
+          format_("$1$ value = static_cast<$1$>(val);\n",
+                  QualifiedClassName(field->enum_type()));
+        } else {
+          format_("$1$ value = val;\n", type);
+        }
+        if (field->is_repeated()) {
+          format_("msg->add_$1$(value);\n", FieldName(field));
+        } else {
+          format_("msg->set_$1$(value);\n", FieldName(field));
+        }
+        break;
+      }
+      case WireFormatLite::WIRETYPE_FIXED64: {
+        string type = PrimitiveTypeName(options_, field->cpp_type());
+        format_(
+            "$1$ val;\n"
+            "::std::memcpy(&val, ptr, 8);\n"
+            "ptr += 8;\n",
+            type);
+        if (field->is_repeated()) {
+          format_("msg->add_$1$(val);\n", FieldName(field));
+        } else {
+          format_("msg->set_$1$(val);\n", FieldName(field));
+        }
+        break;
+      }
+      case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: {
+        use_length_delimited_ = true;
+        GenerateLengthDelim(field);
+        break;
+      }
+      case WireFormatLite::WIRETYPE_START_GROUP: {
+        use_group_ = true;
+        format_(
+            "parser_till_end = $1$::_InternalParse;\n"
+            "object = msg->$2$_$3$();\n"
+            "auto res = ctx->ParseGroup(tag, {parser_till_end, object}, ptr, "
+            "end, "
+            "&depth);\n"
+            "ptr = res.first;\n"
+            "$GOOGLE_PROTOBUF$_PARSER_ASSERT(ptr);\n"
+            "if (res.second) goto group_continues;\n",
+            QualifiedClassName(field->message_type()),
+            field->is_repeated() ? "add" : "mutable", FieldName(field));
+        break;
+      }
+      case WireFormatLite::WIRETYPE_END_GROUP: {
+        GOOGLE_LOG(FATAL) << "Can't have end group field\n";
+        break;
+      }
+      case WireFormatLite::WIRETYPE_FIXED32: {
+        string type = PrimitiveTypeName(options_, field->cpp_type());
+        format_(
+            "$1$ val;\n"
+            "std::memcpy(&val, ptr, 4);\n"
+            "ptr += 4;\n",
+            type);
+        if (field->is_repeated()) {
+          format_("msg->add_$1$(val);\n", FieldName(field));
+        } else {
+          format_("msg->set_$1$(val);\n", FieldName(field));
+        }
+        break;
+      }
+    }  // switch (wire_type)
+
+    if (ShouldRepeat(field, wiretype)) {
+      format_("if (ptr >= end) break;\n");
+      uint32 x = field->number() * 8 + wiretype;
+      uint64 y = 0;
+      int cnt = 0;
+      do {
+        y += static_cast<uint64>((x & 0x7F) + (x >= 128 ? 128 : 0))
+             << (cnt++ * 8);
+        x >>= 7;
+      } while (x);
+      uint64 mask = (1ull << (cnt * 8)) - 1;
+      format_.Outdent();
+      format_(
+          "} while ((::$proto_ns$::io::UnalignedLoad<$uint64$>(ptr) & $1$) == "
+          "$2$ && (ptr += $3$));\n",
+          mask, y, cnt);
+    }
+    format_("break;\n");
+  }
+
+  void GenerateCaseBody(const FieldDescriptor* field) {
+    if (!IsProto1(field->file(), options_) && field->is_packable()) {
+      auto expected_wiretype = WireFormat::WireTypeForFieldType(field->type());
+      GOOGLE_CHECK(expected_wiretype != WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
+      uint32 expected_tag =
+          WireFormatLite::MakeTag(field->number(), expected_wiretype);
+      auto fallback_wiretype = WireFormatLite::WIRETYPE_LENGTH_DELIMITED;
+      uint32 fallback_tag =
+          WireFormatLite::MakeTag(field->number(), fallback_wiretype);
+
+      if (field->is_packed()) {
+        std::swap(expected_tag, fallback_tag);
+        std::swap(expected_wiretype, fallback_wiretype);
+      }
+
+      format_("if (static_cast<$uint8$>(tag) == $1$) {\n", expected_tag & 0xFF);
+      format_.Indent();
+      GenerateCaseBody(expected_wiretype, field);
+      format_.Outdent();
+      format_(
+          "} else if (static_cast<$uint8$>(tag) != $1$) goto handle_unusual;\n",
+          fallback_tag & 0xFF);
+      GenerateCaseBody(fallback_wiretype, field);
+    } else {
+      auto wiretype = WireFormat::WireTypeForField(field);
+      format_("if (static_cast<$uint8$>(tag) != $1$) goto handle_unusual;\n",
+              WireFormat::MakeTag(field) & 0xFF);
+      GenerateCaseBody(wiretype, field);
+    }
+  }
+};
+
+void GenerateParserLoop(const Descriptor* descriptor, const Options& options,
+                        MessageSCCAnalyzer* scc_analyzer,
+                        io::Printer* printer) {
+  ParseLoopGenerator generator(options, scc_analyzer, printer);
+  generator.GenerateParserLoop(descriptor);
 }
 
 }  // namespace cpp
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h
index 0701017..a055702 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.h
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h
@@ -271,6 +271,8 @@
   return false;
 }
 
+bool IsStringInlined(const FieldDescriptor* descriptor, const Options& options);
+
 // For a string field, returns the effective ctype.  If the actual ctype is
 // not supported, returns the default of STRING.
 FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field,
diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.cc b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
index c981673..b44677f 100644
--- a/src/google/protobuf/compiler/cpp/cpp_map_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
@@ -262,8 +262,7 @@
   if (to_array) {
     format(
         "target = ::$proto_ns$::internal::WireFormatLite::InternalWrite"
-        "$declared_type$NoVirtualToArray($number$, *entry, deterministic, "
-        "target);\n");
+        "$declared_type$NoVirtualToArray($number$, *entry, target);\n");
   } else {
     format(
         "::$proto_ns$::internal::WireFormatLite::Write$stream_writer$($number$,"
@@ -365,7 +364,7 @@
       "    items[static_cast<ptrdiff_t>(n)] = SortItem(&*it);\n"
       "  }\n"
       "  ::std::sort(&items[0], &items[static_cast<ptrdiff_t>(n)], Less());\n",
-      to_array ? "deterministic" : "output->IsSerializationDeterministic()");
+      to_array ? "false" : "output->IsSerializationDeterministic()");
   format.Indent();
   GenerateSerializationLoop(format, SupportsArenas(descriptor_), string_key,
                             string_value, to_array, true);
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
index 96354dd..a729282 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -800,7 +800,8 @@
       } else {
         format(
             "inline bool $classname$::has_$name$() const {\n"
-            "  return this != internal_default_instance() && $name$_ != nullptr;\n"
+            "  return this != internal_default_instance() "
+            "&& $name$_ != nullptr;\n"
             "}\n");
       }
     }
@@ -941,7 +942,7 @@
         "public:\n"
         "#if $GOOGLE_PROTOBUF$_ENABLE_EXPERIMENTAL_PARSER\n"
         "static bool _ParseMap(const char* begin, const "
-        "char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);\n"
+        "char* end, void* object, ::$proto_ns$::internal::ParseContext* ctx);\n"
         "#endif  // $GOOGLE_PROTOBUF$_ENABLE_EXPERIMENTAL_PARSER\n"
         "  typedef ::$proto_ns$::internal::MapEntry$lite$<$classname$, \n"
         "    $key_cpp$, $val_cpp$,\n"
@@ -1190,7 +1191,7 @@
     if (HasFastArraySerialization(descriptor_->file(), options_)) {
       format(
           "$uint8$* InternalSerializeWithCachedSizesToArray(\n"
-          "    bool deterministic, $uint8$* target) const final;\n");
+          "    $uint8$* target) const final;\n");
     }
   }
 
@@ -1654,8 +1655,10 @@
     return 2;
   }
   format(
-      "{PROTOBUF_FIELD_OFFSET($classtype$, _cached_size_), 0, 0, 0, nullptr},\n");
+      "{PROTOBUF_FIELD_OFFSET($classtype$, _cached_size_),"
+      " 0, 0, 0, nullptr},\n");
   std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
+  sorted_extensions.reserve(descriptor_->extension_range_count());
   for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
     sorted_extensions.push_back(descriptor_->extension_range(i));
   }
@@ -1864,8 +1867,8 @@
     }
     format(
         "#if $GOOGLE_PROTOBUF$_ENABLE_EXPERIMENTAL_PARSER\n"
-        "bool $classname$::_ParseMap(const char* begin, const "
-        "char* end, void* object, ::google::protobuf::internal::ParseContext* ctx) {\n"
+        "bool $classname$::_ParseMap(const char* begin, const char* end, "
+        "void* object, ::$proto_ns$::internal::ParseContext* ctx) {\n"
         "  using MF = ::$proto_ns$::internal::MapField$1$<\n"
         "      $classname$, EntryKeyType, EntryValueType,\n"
         "      kEntryKeyFieldType, kEntryValueFieldType,\n"
@@ -1885,7 +1888,8 @@
       format(
           "  DO_(parser.ParseMapEnumValidation(\n"
           "    begin, end, ctx->extra_parse_data().field_number,\n"
-          "    static_cast<::google::protobuf::internal::InternalMetadataWithArena$1$*>("
+          "    static_cast<::$proto_ns$::internal::"
+          "InternalMetadataWithArena$1$*>("
           "ctx->extra_parse_data().unknown_fields), $2$_IsValid));\n",
           HasDescriptorMethods(descriptor_->file(), options_) ? "" : "Lite",
           QualifiedClassName(val->enum_type()));
@@ -3769,7 +3773,7 @@
   if (to_array) {
     format(
         "target = _extensions_.InternalSerializeWithCachedSizesToArray(\n"
-        "    $start$, $end$, deterministic, target);\n\n");
+        "    $start$, $end$, target);\n\n");
   } else {
     format(
         "_extensions_.SerializeWithCachedSizes($start$, $end$, output);\n"
@@ -3819,10 +3823,9 @@
     // Special-case MessageSet.
     format(
         "$uint8$* $classname$::InternalSerializeWithCachedSizesToArray(\n"
-        "    bool deterministic, $uint8$* target) const {\n"
+        "    $uint8$* target) const {\n"
         "  target = _extensions_."
-        "InternalSerializeMessageSetWithCachedSizesToArray(\n"
-        "               deterministic, target);\n");
+        "InternalSerializeMessageSetWithCachedSizesToArray(target);\n");
     GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file(), options_));
     std::map<string, string> vars;
     SetUnknkownFieldsVariable(descriptor_, options_, &vars);
@@ -3839,10 +3842,9 @@
 
   format(
       "$uint8$* $classname$::InternalSerializeWithCachedSizesToArray(\n"
-      "    bool deterministic, $uint8$* target) const {\n");
+      "    $uint8$* target) const {\n");
   format.Indent();
 
-  format("(void)deterministic; // Unused\n");
   format("// @@protoc_insertion_point(serialize_to_array_start:$full_name$)\n");
 
   GenerateSerializeWithCachedSizesBody(printer, true);
@@ -3937,6 +3939,7 @@
       SortFieldsByNumber(descriptor_);
 
   std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
+  sorted_extensions.reserve(descriptor_->extension_range_count());
   for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
     sorted_extensions.push_back(descriptor_->extension_range(i));
   }
diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
index 1df2508..a29372d 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
@@ -477,7 +477,7 @@
   format(
       "target = ::$proto_ns$::internal::WireFormatLite::\n"
       "  InternalWrite$declared_type$ToArray(\n"
-      "    $number$, HasBitSetters::$name$(this), deterministic, target);\n");
+      "    $number$, HasBitSetters::$name$(this), target);\n");
 }
 
 void MessageFieldGenerator::
@@ -812,8 +812,7 @@
       "    n = static_cast<unsigned int>(this->$name$_size()); i < n; i++) {\n"
       "  target = ::$proto_ns$::internal::WireFormatLite::\n"
       "    InternalWrite$declared_type$ToArray(\n"
-      "      $number$, this->$name$(static_cast<int>(i)), deterministic, "
-      "target);\n"
+      "      $number$, this->$name$(static_cast<int>(i)), target);\n"
       "}\n");
 }
 
diff --git a/src/google/protobuf/compiler/cpp/cpp_options.h b/src/google/protobuf/compiler/cpp/cpp_options.h
index 181a562..4056ecc 100644
--- a/src/google/protobuf/compiler/cpp/cpp_options.h
+++ b/src/google/protobuf/compiler/cpp/cpp_options.h
@@ -43,8 +43,8 @@
 namespace cpp {
 
 enum class EnforceOptimizeMode {
-  kNoEnforcement, // Use the runtime specified by the file specific options.
-  kSpeed, // This is the full runtime.
+  kNoEnforcement,  // Use the runtime specified by the file specific options.
+  kSpeed,  // This is the full runtime.
   kLiteRuntime,
 };
 
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
index 2676bb5..74a3f34 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
@@ -89,21 +89,7 @@
                                            const Options& options)
     : FieldGenerator(descriptor, options),
       lite_(!HasDescriptorMethods(descriptor->file(), options)),
-      inlined_(false) {
-
-  // TODO(ckennelly): Handle inlining for any.proto.
-  if (IsAnyMessage(descriptor_->containing_type(), options_)) {
-    inlined_ = false;
-  }
-  if (descriptor_->containing_type()->options().map_entry()) {
-    inlined_ = false;
-  }
-
-  // Limit to proto2, as we rely on has bits to distinguish field presence for
-  // release_$name$.  On proto3, we cannot use the address of the string
-  // instance when the field has been inlined.
-  inlined_ = inlined_ && HasFieldPresence(descriptor_->file());
-
+      inlined_(IsStringInlined(descriptor, options)) {
   SetStringVariables(descriptor, &variables_, options);
 }
 
diff --git a/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
index 7fe9875..0f15f39 100644
--- a/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
+++ b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
@@ -147,6 +147,7 @@
   NOT_EQ = 1;           // NO_PROTO3
   volatile = 2;         // NO_PROTO3
   return = 3;           // NO_PROTO3
+  NULL = 4;             // NO_PROTO3
 }  // NO_PROTO3
 
 message DummyMessage {}
diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
index 2cf030e..a17ed8b 100644
--- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
@@ -107,12 +107,13 @@
   message.set_conflicting_enum(protobuf_unittest::TestConflictingEnumNames_NestedConflictingEnum_XOR);
   EXPECT_EQ(5, message.conflicting_enum());
 
-
   protobuf_unittest::ConflictingEnum conflicting_enum;
   conflicting_enum = protobuf_unittest::NOT_EQ;
   EXPECT_EQ(1, conflicting_enum);
   conflicting_enum = protobuf_unittest::return_;
   EXPECT_EQ(3, conflicting_enum);
+  conflicting_enum = protobuf_unittest::NULL_;
+  EXPECT_EQ(4, conflicting_enum);
 }
 
 }  // namespace cpp_unittest
diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.inc b/src/google/protobuf/compiler/cpp/cpp_unittest.inc
index 0323e4e..e6aded7 100644
--- a/src/google/protobuf/compiler/cpp/cpp_unittest.inc
+++ b/src/google/protobuf/compiler/cpp/cpp_unittest.inc
@@ -2154,6 +2154,7 @@
   MessageSCCAnalyzer scc_analyzer((Options()));
   const SCC* scc = scc_analyzer.GetSCC(a.GetDescriptor());
   std::vector<string> names;
+  names.reserve(scc->descriptors.size());
   for (int i = 0; i < scc->descriptors.size(); i++) {
     names.push_back(scc->descriptors[i]->full_name());
   }
diff --git a/src/google/protobuf/compiler/js/js_generator.cc b/src/google/protobuf/compiler/js/js_generator.cc
index 7e547af..db19ff5 100644
--- a/src/google/protobuf/compiler/js/js_generator.cc
+++ b/src/google/protobuf/compiler/js/js_generator.cc
@@ -2430,6 +2430,9 @@
       " * @param {!Object} obj The object representation of this proto to\n"
       " *     load the data from.\n"
       " * @return {!$classname$}\n"
+      " * @suppress {missingProperties} To prevent JSCompiler errors at "
+      "the\n"
+      " *     `goog.isDef(obj.<fieldName>)` lookups.\n"
       " */\n"
       "$classname$.fromObject = function(obj) {\n"
       "  var msg = new $classname$();\n",
@@ -2437,7 +2440,9 @@
 
   for (int i = 0; i < desc->field_count(); i++) {
     const FieldDescriptor* field = desc->field(i);
-    GenerateClassFieldFromObject(options, printer, field);
+    if (!IgnoreField(field)) {
+      GenerateClassFieldFromObject(options, printer, field);
+    }
   }
 
   printer->Print(
@@ -2479,9 +2484,8 @@
         printer->Print(
             "  goog.isDef(obj.$name$) && "
             "jspb.Message.setRepeatedWrapperField(\n"
-            "      msg, $index$, goog.array.map(obj.$name$, function(i) {\n"
-            "        return $fieldclass$.fromObject(i);\n"
-            "      }));\n",
+            "      msg, $index$, obj.$name$.map(\n"
+            "          $fieldclass$.fromObject));\n",
             "name", JSObjectFieldName(options, field),
             "index", JSFieldIndex(field),
             "fieldclass", SubmessageTypeRef(options, field));
diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc
index c533c6a..1a3171a 100644
--- a/src/google/protobuf/compiler/parser.cc
+++ b/src/google/protobuf/compiler/parser.cc
@@ -1564,15 +1564,18 @@
 // name literals.
 bool Parser::ParseReserved(DescriptorProto* message,
                            const LocationRecorder& message_location) {
+  io::Tokenizer::Token start_token = input_->current();
   // Parse the declaration.
   DO(Consume("reserved"));
   if (LookingAtType(io::Tokenizer::TYPE_STRING)) {
     LocationRecorder location(message_location,
                               DescriptorProto::kReservedNameFieldNumber);
+    location.StartAt(start_token);
     return ParseReservedNames(message, location);
   } else {
     LocationRecorder location(message_location,
                               DescriptorProto::kReservedRangeFieldNumber);
+    location.StartAt(start_token);
     return ParseReservedNumbers(message, location);
   }
 }
@@ -1638,16 +1641,19 @@
 }
 
 bool Parser::ParseReserved(EnumDescriptorProto* message,
-                          const LocationRecorder& message_location) {
+                           const LocationRecorder& message_location) {
+  io::Tokenizer::Token start_token = input_->current();
   // Parse the declaration.
   DO(Consume("reserved"));
   if (LookingAtType(io::Tokenizer::TYPE_STRING)) {
     LocationRecorder location(message_location,
                               DescriptorProto::kReservedNameFieldNumber);
+    location.StartAt(start_token);
     return ParseReservedNames(message, location);
   } else {
     LocationRecorder location(message_location,
                               DescriptorProto::kReservedRangeFieldNumber);
+    location.StartAt(start_token);
     return ParseReservedNumbers(message, location);
   }
 }
diff --git a/src/google/protobuf/compiler/parser_unittest.cc b/src/google/protobuf/compiler/parser_unittest.cc
index e63739b..4c67c78 100644
--- a/src/google/protobuf/compiler/parser_unittest.cc
+++ b/src/google/protobuf/compiler/parser_unittest.cc
@@ -2739,6 +2739,33 @@
   EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
 }
 
+TEST_F(SourceInfoTest, ReservedRanges) {
+  EXPECT_TRUE(
+      Parse("message Message {\n"
+            "  $a$reserved $b$1$c$ to $d$4$e$, $f$6$g$;$h$\n"
+            "}\n"));
+
+  const DescriptorProto::ReservedRange& range1 =
+      file_.message_type(0).reserved_range(0);
+  const DescriptorProto::ReservedRange& range2 =
+      file_.message_type(0).reserved_range(1);
+
+  EXPECT_TRUE(HasSpan('a', 'h', file_.message_type(0), "reserved_range"));
+
+  EXPECT_TRUE(HasSpan('b', 'e', range1));
+  EXPECT_TRUE(HasSpan('b', 'c', range1, "start"));
+  EXPECT_TRUE(HasSpan('d', 'e', range1, "end"));
+
+  EXPECT_TRUE(HasSpan('f', 'g', range2));
+  EXPECT_TRUE(HasSpan('f', 'g', range2, "start"));
+  EXPECT_TRUE(HasSpan('f', 'g', range2, "end"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(file_.message_type(0)));
+  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
+}
+
 TEST_F(SourceInfoTest, Oneofs) {
   EXPECT_TRUE(Parse(
       "message Foo {\n"
diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc
index 89291a1..9b34152 100644
--- a/src/google/protobuf/compiler/plugin.pb.cc
+++ b/src/google/protobuf/compiler/plugin.pb.cc
@@ -320,14 +320,14 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // optional int32 major = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ::google::protobuf::int32 value = val;
         msg->set_major(value);
@@ -337,7 +337,7 @@
       case 2: {
         if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ::google::protobuf::int32 value = val;
         msg->set_minor(value);
@@ -347,7 +347,7 @@
       case 3: {
         if (static_cast<::google::protobuf::uint8>(tag) != 24) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ::google::protobuf::int32 value = val;
         msg->set_patch(value);
@@ -356,7 +356,7 @@
       // optional string suffix = 4;
       case 4: {
         if (static_cast<::google::protobuf::uint8>(tag) != 34) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.compiler.Version.suffix");
         auto str = msg->mutable_suffix();
@@ -373,7 +373,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -387,13 +387,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool Version::MergePartialFromCodedStream(
@@ -521,8 +517,7 @@
 }
 
 ::google::protobuf::uint8* Version::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.Version)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -804,14 +799,14 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // repeated string file_to_generate = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           ctx->extra_parse_data().SetFieldName("google.protobuf.compiler.CodeGeneratorRequest.file_to_generate");
           auto str = msg->add_file_to_generate();
@@ -832,7 +827,7 @@
       // optional string parameter = 2;
       case 2: {
         if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.compiler.CodeGeneratorRequest.parameter");
         auto str = msg->mutable_parameter();
@@ -851,7 +846,7 @@
       // optional .google.protobuf.compiler.Version compiler_version = 3;
       case 3: {
         if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         parser_till_end = ::google::protobuf::compiler::Version::_InternalParse;
         object = msg->mutable_compiler_version();
@@ -867,7 +862,7 @@
       case 15: {
         if (static_cast<::google::protobuf::uint8>(tag) != 122) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::FileDescriptorProto::_InternalParse;
           object = msg->add_proto_file();
@@ -882,7 +877,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -896,13 +891,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool CodeGeneratorRequest::MergePartialFromCodedStream(
@@ -1039,8 +1030,7 @@
 }
 
 ::google::protobuf::uint8* CodeGeneratorRequest::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorRequest)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -1071,7 +1061,7 @@
   if (cached_has_bits & 0x00000002u) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        3, HasBitSetters::compiler_version(this), deterministic, target);
+        3, HasBitSetters::compiler_version(this), target);
   }
 
   // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
@@ -1079,7 +1069,7 @@
       n = static_cast<unsigned int>(this->proto_file_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        15, this->proto_file(static_cast<int>(i)), deterministic, target);
+        15, this->proto_file(static_cast<int>(i)), target);
   }
 
   if (_internal_metadata_.have_unknown_fields()) {
@@ -1328,13 +1318,13 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // optional string name = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.compiler.CodeGeneratorResponse.File.name");
         auto str = msg->mutable_name();
@@ -1353,7 +1343,7 @@
       // optional string insertion_point = 2;
       case 2: {
         if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point");
         auto str = msg->mutable_insertion_point();
@@ -1372,7 +1362,7 @@
       // optional string content = 15;
       case 15: {
         if (static_cast<::google::protobuf::uint8>(tag) != 122) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.compiler.CodeGeneratorResponse.File.content");
         auto str = msg->mutable_content();
@@ -1389,7 +1379,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -1403,13 +1393,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool CodeGeneratorResponse_File::MergePartialFromCodedStream(
@@ -1533,8 +1519,7 @@
 }
 
 ::google::protobuf::uint8* CodeGeneratorResponse_File::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorResponse.File)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -1785,13 +1770,13 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // optional string error = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.compiler.CodeGeneratorResponse.error");
         auto str = msg->mutable_error();
@@ -1811,7 +1796,7 @@
       case 15: {
         if (static_cast<::google::protobuf::uint8>(tag) != 122) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::compiler::CodeGeneratorResponse_File::_InternalParse;
           object = msg->add_file();
@@ -1826,7 +1811,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -1840,13 +1825,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool CodeGeneratorResponse::MergePartialFromCodedStream(
@@ -1940,8 +1921,7 @@
 }
 
 ::google::protobuf::uint8* CodeGeneratorResponse::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorResponse)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -1963,7 +1943,7 @@
       n = static_cast<unsigned int>(this->file_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        15, this->file(static_cast<int>(i)), deterministic, target);
+        15, this->file(static_cast<int>(i)), target);
   }
 
   if (_internal_metadata_.have_unknown_fields()) {
diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h
index b33bc60..a8e4479 100644
--- a/src/google/protobuf/compiler/plugin.pb.h
+++ b/src/google/protobuf/compiler/plugin.pb.h
@@ -161,7 +161,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -313,7 +313,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -487,7 +487,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -647,7 +647,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
diff --git a/src/google/protobuf/compiler/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc
index ba7ecde..bbe8352 100644
--- a/src/google/protobuf/compiler/python/python_generator.cc
+++ b/src/google/protobuf/compiler/python/python_generator.cc
@@ -359,6 +359,22 @@
 
   return !printer.failed();
 }
+// BEGIN GOOGLE-INTERNAL
+// Strip the google3.third_party.py. prefix off of a module name as we
+// NEVER want that invalid module import path to be generated in google3.
+// Our sys.path has google3/third_party/py/ in it.  All modules from
+// that tree need to be imported using just their own name.
+// See http://go/ThirdPartyPython
+void StripThirdPartyPy(string* module_name) {
+  const string third_party_py_prefix = "google3.third_party.py.";
+  int len = third_party_py_prefix.length();
+  if (module_name->compare(0, len,
+                          third_party_py_prefix, 0,
+                          len) == 0) {
+    *module_name = module_name->erase(0, len);
+  }
+}
+// END GOOGLE-INTERNAL
 
 // Prints Python imports for all modules imported by |file|.
 void Generator::PrintImports() const {
@@ -367,6 +383,9 @@
 
     string module_name = ModuleName(filename);
     string module_alias = ModuleAlias(filename);
+    // BEGIN GOOGLE-INTERNAL
+    StripThirdPartyPy(&module_name);
+    // END GOOGLE-INTERNAL
     if (ContainsPythonKeyword(module_name)) {
       // If the module path contains a Python keyword, we have to quote the
       // module name and import it using importlib. Otherwise the usual kind of
@@ -397,6 +416,9 @@
   // Print public imports.
   for (int i = 0; i < file_->public_dependency_count(); ++i) {
     string module_name = ModuleName(file_->public_dependency(i)->name());
+    // BEGIN GOOGLE-INTERNAL
+    StripThirdPartyPy(&module_name);
+    // END GOOGLE-INTERNAL
     printer_->Print("from $module$ import *\n", "module", module_name);
   }
   printer_->Print("\n");
diff --git a/src/google/protobuf/compiler/zip_writer.h b/src/google/protobuf/compiler/zip_writer.h
index 9f56d68..a99bb78 100644
--- a/src/google/protobuf/compiler/zip_writer.h
+++ b/src/google/protobuf/compiler/zip_writer.h
@@ -60,9 +60,6 @@
 
 // Author: kenton@google.com (Kenton Varda)
 
-#ifndef GOOGLE_PROTOBUF_COMPILER_ZIP_WRITER_H__
-#define GOOGLE_PROTOBUF_COMPILER_ZIP_WRITER_H__
-
 #include <vector>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/io/zero_copy_stream.h>
@@ -94,5 +91,3 @@
 }  // namespace compiler
 }  // namespace protobuf
 }  // namespace google
-
-#endif  // GOOGLE_PROTOBUF_COMPILER_ZIP_WRITER_H__
diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc
index 5b7bd90..caed8a9 100644
--- a/src/google/protobuf/descriptor.cc
+++ b/src/google/protobuf/descriptor.cc
@@ -5073,10 +5073,12 @@
     if (!inserted && insert_result.first->second->name() != value->name() &&
         insert_result.first->second->number() != value->number()) {
       string error_message =
-          "When enum name is stripped and label is PascalCased (" + stripped +
-          "), this value label conflicts with " + values[stripped]->name() +
-          ". This will make the proto fail to compile for some languages, such "
-          "as C#.";
+          "Enum name " + value->name() + " has the same name as " +
+          values[stripped]->name() +
+          " if you ignore case and strip out the enum name prefix (if any). "
+          "This is error-prone and can lead to undefined behavior. "
+          "Please avoid doing this. If you are using allow_alias, please "
+          "assign the same numeric value to both enums.";
       // There are proto2 enums out there with conflicting names, so to preserve
       // compatibility we issue only a warning for proto2.
       if (result->file()->syntax() == FileDescriptor::SYNTAX_PROTO2) {
diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h
index cf0a52b..ac4d8b2 100644
--- a/src/google/protobuf/descriptor.h
+++ b/src/google/protobuf/descriptor.h
@@ -232,6 +232,8 @@
 // Use DescriptorPool to construct your own descriptors.
 class PROTOBUF_EXPORT Descriptor {
  public:
+  typedef DescriptorProto Proto;
+
   // The name of the message type, not including its scope.
   const std::string& name() const;
 
@@ -345,6 +347,8 @@
   // A range of field numbers which are designated for third-party
   // extensions.
   struct ExtensionRange {
+    typedef DescriptorProto_ExtensionRange Proto;
+
     typedef ExtensionRangeOptions OptionsType;
 
     // See Descriptor::CopyTo().
@@ -511,6 +515,8 @@
 // Use DescriptorPool to construct your own descriptors.
 class PROTOBUF_EXPORT FieldDescriptor {
  public:
+  typedef FieldDescriptorProto Proto;
+
   // Identifies a field type.  0 is reserved for errors.  The order is weird
   // for historical reasons.  Types 12 and up are new in proto2.
   enum Type {
@@ -821,6 +827,8 @@
 // Describes a oneof defined in a message type.
 class PROTOBUF_EXPORT OneofDescriptor {
  public:
+  typedef OneofDescriptorProto Proto;
+
   const std::string& name() const;       // Name of this oneof.
   const std::string& full_name() const;  // Fully-qualified name of the oneof.
 
@@ -895,6 +903,8 @@
 // to construct your own descriptors.
 class PROTOBUF_EXPORT EnumDescriptor {
  public:
+  typedef EnumDescriptorProto Proto;
+
   // The name of this enum type in the containing scope.
   const std::string& name() const;
 
@@ -1051,6 +1061,8 @@
 // your own descriptors.
 class PROTOBUF_EXPORT EnumValueDescriptor {
  public:
+  typedef EnumValueDescriptorProto Proto;
+
   const std::string& name() const;  // Name of this enum constant.
   int index() const;           // Index within the enums's Descriptor.
   int number() const;          // Numeric value of this enum constant.
@@ -1129,6 +1141,8 @@
 // ServiceDescriptor.  Use DescriptorPool to construct your own descriptors.
 class PROTOBUF_EXPORT ServiceDescriptor {
  public:
+  typedef ServiceDescriptorProto Proto;
+
   // The name of the service, not including its containing scope.
   const std::string& name() const;
   // The fully-qualified name of the service, scope delimited by periods.
@@ -1209,6 +1223,8 @@
 // own descriptors.
 class PROTOBUF_EXPORT MethodDescriptor {
  public:
+  typedef MethodDescriptorProto Proto;
+
   // Name of this method, not including containing scope.
   const std::string& name() const;
   // The fully-qualified name of the method, scope delimited by periods.
@@ -1294,6 +1310,8 @@
 // descriptor->file().  Use DescriptorPool to construct your own descriptors.
 class PROTOBUF_EXPORT FileDescriptor {
  public:
+  typedef FileDescriptorProto Proto;
+
   // The filename, relative to the source tree.
   // e.g. "foo/bar/baz.proto"
   const std::string& name() const;
diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc
index d455267..198bcca 100644
--- a/src/google/protobuf/descriptor.pb.cc
+++ b/src/google/protobuf/descriptor.pb.cc
@@ -1474,14 +1474,14 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // repeated .google.protobuf.FileDescriptorProto file = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::FileDescriptorProto::_InternalParse;
           object = msg->add_file();
@@ -1496,7 +1496,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -1510,13 +1510,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool FileDescriptorSet::MergePartialFromCodedStream(
@@ -1584,8 +1580,7 @@
 }
 
 ::google::protobuf::uint8* FileDescriptorSet::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FileDescriptorSet)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -1595,7 +1590,7 @@
       n = static_cast<unsigned int>(this->file_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        1, this->file(static_cast<int>(i)), deterministic, target);
+        1, this->file(static_cast<int>(i)), target);
   }
 
   if (_internal_metadata_.have_unknown_fields()) {
@@ -1935,13 +1930,13 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // optional string name = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.FileDescriptorProto.name");
         auto str = msg->mutable_name();
@@ -1960,7 +1955,7 @@
       // optional string package = 2;
       case 2: {
         if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.FileDescriptorProto.package");
         auto str = msg->mutable_package();
@@ -1980,7 +1975,7 @@
       case 3: {
         if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           ctx->extra_parse_data().SetFieldName("google.protobuf.FileDescriptorProto.dependency");
           auto str = msg->add_dependency();
@@ -2002,7 +1997,7 @@
       case 4: {
         if (static_cast<::google::protobuf::uint8>(tag) != 34) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::DescriptorProto::_InternalParse;
           object = msg->add_message_type();
@@ -2020,7 +2015,7 @@
       case 5: {
         if (static_cast<::google::protobuf::uint8>(tag) != 42) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::EnumDescriptorProto::_InternalParse;
           object = msg->add_enum_type();
@@ -2038,7 +2033,7 @@
       case 6: {
         if (static_cast<::google::protobuf::uint8>(tag) != 50) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::ServiceDescriptorProto::_InternalParse;
           object = msg->add_service();
@@ -2056,7 +2051,7 @@
       case 7: {
         if (static_cast<::google::protobuf::uint8>(tag) != 58) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::FieldDescriptorProto::_InternalParse;
           object = msg->add_extension();
@@ -2073,7 +2068,7 @@
       // optional .google.protobuf.FileOptions options = 8;
       case 8: {
         if (static_cast<::google::protobuf::uint8>(tag) != 66) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         parser_till_end = ::google::protobuf::FileOptions::_InternalParse;
         object = msg->mutable_options();
@@ -2088,7 +2083,7 @@
       // optional .google.protobuf.SourceCodeInfo source_code_info = 9;
       case 9: {
         if (static_cast<::google::protobuf::uint8>(tag) != 74) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         parser_till_end = ::google::protobuf::SourceCodeInfo::_InternalParse;
         object = msg->mutable_source_code_info();
@@ -2105,7 +2100,7 @@
         if (static_cast<::google::protobuf::uint8>(tag) == 80) {
           do {
             ::google::protobuf::uint64 val;
-            ptr = Varint::Parse64(ptr, &val);
+            ptr = ::google::protobuf::io::Parse64(ptr, &val);
             GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
             ::google::protobuf::int32 value = val;
             msg->add_public_dependency(value);
@@ -2113,7 +2108,7 @@
           } while ((::google::protobuf::io::UnalignedLoad<::google::protobuf::uint64>(ptr) & 255) == 80 && (ptr += 1));
           break;
         } else if (static_cast<::google::protobuf::uint8>(tag) != 82) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         parser_till_end = ::google::protobuf::internal::PackedInt32Parser;
         object = msg->mutable_public_dependency();
@@ -2128,7 +2123,7 @@
         if (static_cast<::google::protobuf::uint8>(tag) == 88) {
           do {
             ::google::protobuf::uint64 val;
-            ptr = Varint::Parse64(ptr, &val);
+            ptr = ::google::protobuf::io::Parse64(ptr, &val);
             GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
             ::google::protobuf::int32 value = val;
             msg->add_weak_dependency(value);
@@ -2136,7 +2131,7 @@
           } while ((::google::protobuf::io::UnalignedLoad<::google::protobuf::uint64>(ptr) & 255) == 88 && (ptr += 1));
           break;
         } else if (static_cast<::google::protobuf::uint8>(tag) != 90) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         parser_till_end = ::google::protobuf::internal::PackedInt32Parser;
         object = msg->mutable_weak_dependency();
@@ -2149,7 +2144,7 @@
       // optional string syntax = 12;
       case 12: {
         if (static_cast<::google::protobuf::uint8>(tag) != 98) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.FileDescriptorProto.syntax");
         auto str = msg->mutable_syntax();
@@ -2166,7 +2161,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -2180,13 +2175,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool FileDescriptorProto::MergePartialFromCodedStream(
@@ -2494,8 +2485,7 @@
 }
 
 ::google::protobuf::uint8* FileDescriptorProto::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FileDescriptorProto)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -2538,7 +2528,7 @@
       n = static_cast<unsigned int>(this->message_type_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        4, this->message_type(static_cast<int>(i)), deterministic, target);
+        4, this->message_type(static_cast<int>(i)), target);
   }
 
   // repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
@@ -2546,7 +2536,7 @@
       n = static_cast<unsigned int>(this->enum_type_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        5, this->enum_type(static_cast<int>(i)), deterministic, target);
+        5, this->enum_type(static_cast<int>(i)), target);
   }
 
   // repeated .google.protobuf.ServiceDescriptorProto service = 6;
@@ -2554,7 +2544,7 @@
       n = static_cast<unsigned int>(this->service_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        6, this->service(static_cast<int>(i)), deterministic, target);
+        6, this->service(static_cast<int>(i)), target);
   }
 
   // repeated .google.protobuf.FieldDescriptorProto extension = 7;
@@ -2562,21 +2552,21 @@
       n = static_cast<unsigned int>(this->extension_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        7, this->extension(static_cast<int>(i)), deterministic, target);
+        7, this->extension(static_cast<int>(i)), target);
   }
 
   // optional .google.protobuf.FileOptions options = 8;
   if (cached_has_bits & 0x00000008u) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        8, HasBitSetters::options(this), deterministic, target);
+        8, HasBitSetters::options(this), target);
   }
 
   // optional .google.protobuf.SourceCodeInfo source_code_info = 9;
   if (cached_has_bits & 0x00000010u) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        9, HasBitSetters::source_code_info(this), deterministic, target);
+        9, HasBitSetters::source_code_info(this), target);
   }
 
   // repeated int32 public_dependency = 10;
@@ -2986,14 +2976,14 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // optional int32 start = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ::google::protobuf::int32 value = val;
         msg->set_start(value);
@@ -3003,7 +2993,7 @@
       case 2: {
         if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ::google::protobuf::int32 value = val;
         msg->set_end(value);
@@ -3012,7 +3002,7 @@
       // optional .google.protobuf.ExtensionRangeOptions options = 3;
       case 3: {
         if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         parser_till_end = ::google::protobuf::ExtensionRangeOptions::_InternalParse;
         object = msg->mutable_options();
@@ -3025,7 +3015,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -3039,13 +3029,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool DescriptorProto_ExtensionRange::MergePartialFromCodedStream(
@@ -3147,8 +3133,7 @@
 }
 
 ::google::protobuf::uint8* DescriptorProto_ExtensionRange::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.DescriptorProto.ExtensionRange)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -3168,7 +3153,7 @@
   if (cached_has_bits & 0x00000001u) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        3, HasBitSetters::options(this), deterministic, target);
+        3, HasBitSetters::options(this), target);
   }
 
   if (_internal_metadata_.have_unknown_fields()) {
@@ -3411,14 +3396,14 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // optional int32 start = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ::google::protobuf::int32 value = val;
         msg->set_start(value);
@@ -3428,14 +3413,14 @@
       case 2: {
         if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ::google::protobuf::int32 value = val;
         msg->set_end(value);
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -3449,13 +3434,6 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
-  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool DescriptorProto_ReservedRange::MergePartialFromCodedStream(
@@ -3540,8 +3518,7 @@
 }
 
 ::google::protobuf::uint8* DescriptorProto_ReservedRange::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.DescriptorProto.ReservedRange)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -3849,13 +3826,13 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // optional string name = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.DescriptorProto.name");
         auto str = msg->mutable_name();
@@ -3875,7 +3852,7 @@
       case 2: {
         if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::FieldDescriptorProto::_InternalParse;
           object = msg->add_field();
@@ -3893,7 +3870,7 @@
       case 3: {
         if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::DescriptorProto::_InternalParse;
           object = msg->add_nested_type();
@@ -3911,7 +3888,7 @@
       case 4: {
         if (static_cast<::google::protobuf::uint8>(tag) != 34) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::EnumDescriptorProto::_InternalParse;
           object = msg->add_enum_type();
@@ -3929,7 +3906,7 @@
       case 5: {
         if (static_cast<::google::protobuf::uint8>(tag) != 42) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::DescriptorProto_ExtensionRange::_InternalParse;
           object = msg->add_extension_range();
@@ -3947,7 +3924,7 @@
       case 6: {
         if (static_cast<::google::protobuf::uint8>(tag) != 50) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::FieldDescriptorProto::_InternalParse;
           object = msg->add_extension();
@@ -3964,7 +3941,7 @@
       // optional .google.protobuf.MessageOptions options = 7;
       case 7: {
         if (static_cast<::google::protobuf::uint8>(tag) != 58) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         parser_till_end = ::google::protobuf::MessageOptions::_InternalParse;
         object = msg->mutable_options();
@@ -3980,7 +3957,7 @@
       case 8: {
         if (static_cast<::google::protobuf::uint8>(tag) != 66) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::OneofDescriptorProto::_InternalParse;
           object = msg->add_oneof_decl();
@@ -3998,7 +3975,7 @@
       case 9: {
         if (static_cast<::google::protobuf::uint8>(tag) != 74) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::DescriptorProto_ReservedRange::_InternalParse;
           object = msg->add_reserved_range();
@@ -4016,7 +3993,7 @@
       case 10: {
         if (static_cast<::google::protobuf::uint8>(tag) != 82) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           ctx->extra_parse_data().SetFieldName("google.protobuf.DescriptorProto.reserved_name");
           auto str = msg->add_reserved_name();
@@ -4035,7 +4012,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -4049,13 +4026,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool DescriptorProto::MergePartialFromCodedStream(
@@ -4312,8 +4285,7 @@
 }
 
 ::google::protobuf::uint8* DescriptorProto::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.DescriptorProto)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -4335,7 +4307,7 @@
       n = static_cast<unsigned int>(this->field_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        2, this->field(static_cast<int>(i)), deterministic, target);
+        2, this->field(static_cast<int>(i)), target);
   }
 
   // repeated .google.protobuf.DescriptorProto nested_type = 3;
@@ -4343,7 +4315,7 @@
       n = static_cast<unsigned int>(this->nested_type_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        3, this->nested_type(static_cast<int>(i)), deterministic, target);
+        3, this->nested_type(static_cast<int>(i)), target);
   }
 
   // repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
@@ -4351,7 +4323,7 @@
       n = static_cast<unsigned int>(this->enum_type_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        4, this->enum_type(static_cast<int>(i)), deterministic, target);
+        4, this->enum_type(static_cast<int>(i)), target);
   }
 
   // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
@@ -4359,7 +4331,7 @@
       n = static_cast<unsigned int>(this->extension_range_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        5, this->extension_range(static_cast<int>(i)), deterministic, target);
+        5, this->extension_range(static_cast<int>(i)), target);
   }
 
   // repeated .google.protobuf.FieldDescriptorProto extension = 6;
@@ -4367,14 +4339,14 @@
       n = static_cast<unsigned int>(this->extension_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        6, this->extension(static_cast<int>(i)), deterministic, target);
+        6, this->extension(static_cast<int>(i)), target);
   }
 
   // optional .google.protobuf.MessageOptions options = 7;
   if (cached_has_bits & 0x00000002u) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        7, HasBitSetters::options(this), deterministic, target);
+        7, HasBitSetters::options(this), target);
   }
 
   // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8;
@@ -4382,7 +4354,7 @@
       n = static_cast<unsigned int>(this->oneof_decl_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        8, this->oneof_decl(static_cast<int>(i)), deterministic, target);
+        8, this->oneof_decl(static_cast<int>(i)), target);
   }
 
   // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;
@@ -4390,7 +4362,7 @@
       n = static_cast<unsigned int>(this->reserved_range_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        9, this->reserved_range(static_cast<int>(i)), deterministic, target);
+        9, this->reserved_range(static_cast<int>(i)), target);
   }
 
   // repeated string reserved_name = 10;
@@ -4728,14 +4700,14 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
       case 999: {
         if (static_cast<::google::protobuf::uint8>(tag) != 58) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::UninterpretedOption::_InternalParse;
           object = msg->add_uninterpreted_option();
@@ -4750,7 +4722,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -4772,13 +4744,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool ExtensionRangeOptions::MergePartialFromCodedStream(
@@ -4855,8 +4823,7 @@
 }
 
 ::google::protobuf::uint8* ExtensionRangeOptions::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ExtensionRangeOptions)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -4866,12 +4833,12 @@
       n = static_cast<unsigned int>(this->uninterpreted_option_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        999, this->uninterpreted_option(static_cast<int>(i)), deterministic, target);
+        999, this->uninterpreted_option(static_cast<int>(i)), target);
   }
 
   // Extension range [1000, 536870912)
   target = _extensions_.InternalSerializeWithCachedSizesToArray(
-      1000, 536870912, deterministic, target);
+      1000, 536870912, target);
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
@@ -5214,13 +5181,13 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // optional string name = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.FieldDescriptorProto.name");
         auto str = msg->mutable_name();
@@ -5239,7 +5206,7 @@
       // optional string extendee = 2;
       case 2: {
         if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.FieldDescriptorProto.extendee");
         auto str = msg->mutable_extendee();
@@ -5259,7 +5226,7 @@
       case 3: {
         if (static_cast<::google::protobuf::uint8>(tag) != 24) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ::google::protobuf::int32 value = val;
         msg->set_number(value);
@@ -5269,7 +5236,7 @@
       case 4: {
         if (static_cast<::google::protobuf::uint8>(tag) != 32) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         if (!::google::protobuf::FieldDescriptorProto_Label_IsValid(val)) {
           ::google::protobuf::internal::WriteVarint(4, val, msg->mutable_unknown_fields());
@@ -5283,7 +5250,7 @@
       case 5: {
         if (static_cast<::google::protobuf::uint8>(tag) != 40) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         if (!::google::protobuf::FieldDescriptorProto_Type_IsValid(val)) {
           ::google::protobuf::internal::WriteVarint(5, val, msg->mutable_unknown_fields());
@@ -5296,7 +5263,7 @@
       // optional string type_name = 6;
       case 6: {
         if (static_cast<::google::protobuf::uint8>(tag) != 50) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.FieldDescriptorProto.type_name");
         auto str = msg->mutable_type_name();
@@ -5315,7 +5282,7 @@
       // optional string default_value = 7;
       case 7: {
         if (static_cast<::google::protobuf::uint8>(tag) != 58) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.FieldDescriptorProto.default_value");
         auto str = msg->mutable_default_value();
@@ -5334,7 +5301,7 @@
       // optional .google.protobuf.FieldOptions options = 8;
       case 8: {
         if (static_cast<::google::protobuf::uint8>(tag) != 66) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         parser_till_end = ::google::protobuf::FieldOptions::_InternalParse;
         object = msg->mutable_options();
@@ -5350,7 +5317,7 @@
       case 9: {
         if (static_cast<::google::protobuf::uint8>(tag) != 72) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ::google::protobuf::int32 value = val;
         msg->set_oneof_index(value);
@@ -5359,7 +5326,7 @@
       // optional string json_name = 10;
       case 10: {
         if (static_cast<::google::protobuf::uint8>(tag) != 82) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.FieldDescriptorProto.json_name");
         auto str = msg->mutable_json_name();
@@ -5376,7 +5343,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -5390,13 +5357,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool FieldDescriptorProto::MergePartialFromCodedStream(
@@ -5673,8 +5636,7 @@
 }
 
 ::google::protobuf::uint8* FieldDescriptorProto::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FieldDescriptorProto)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -5745,7 +5707,7 @@
   if (cached_has_bits & 0x00000020u) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        8, HasBitSetters::options(this), deterministic, target);
+        8, HasBitSetters::options(this), target);
   }
 
   // optional int32 oneof_index = 9;
@@ -6123,13 +6085,13 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // optional string name = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.OneofDescriptorProto.name");
         auto str = msg->mutable_name();
@@ -6148,7 +6110,7 @@
       // optional .google.protobuf.OneofOptions options = 2;
       case 2: {
         if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         parser_till_end = ::google::protobuf::OneofOptions::_InternalParse;
         object = msg->mutable_options();
@@ -6161,7 +6123,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -6175,13 +6137,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool OneofDescriptorProto::MergePartialFromCodedStream(
@@ -6272,8 +6230,7 @@
 }
 
 ::google::protobuf::uint8* OneofDescriptorProto::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.OneofDescriptorProto)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -6294,7 +6251,7 @@
   if (cached_has_bits & 0x00000002u) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        2, HasBitSetters::options(this), deterministic, target);
+        2, HasBitSetters::options(this), target);
   }
 
   if (_internal_metadata_.have_unknown_fields()) {
@@ -6526,14 +6483,14 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // optional int32 start = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ::google::protobuf::int32 value = val;
         msg->set_start(value);
@@ -6543,14 +6500,14 @@
       case 2: {
         if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ::google::protobuf::int32 value = val;
         msg->set_end(value);
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -6564,13 +6521,6 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
-  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool EnumDescriptorProto_EnumReservedRange::MergePartialFromCodedStream(
@@ -6655,8 +6605,7 @@
 }
 
 ::google::protobuf::uint8* EnumDescriptorProto_EnumReservedRange::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumDescriptorProto.EnumReservedRange)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -6944,13 +6893,13 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // optional string name = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.EnumDescriptorProto.name");
         auto str = msg->mutable_name();
@@ -6970,7 +6919,7 @@
       case 2: {
         if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::EnumValueDescriptorProto::_InternalParse;
           object = msg->add_value();
@@ -6987,7 +6936,7 @@
       // optional .google.protobuf.EnumOptions options = 3;
       case 3: {
         if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         parser_till_end = ::google::protobuf::EnumOptions::_InternalParse;
         object = msg->mutable_options();
@@ -7003,7 +6952,7 @@
       case 4: {
         if (static_cast<::google::protobuf::uint8>(tag) != 34) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::EnumDescriptorProto_EnumReservedRange::_InternalParse;
           object = msg->add_reserved_range();
@@ -7021,7 +6970,7 @@
       case 5: {
         if (static_cast<::google::protobuf::uint8>(tag) != 42) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           ctx->extra_parse_data().SetFieldName("google.protobuf.EnumDescriptorProto.reserved_name");
           auto str = msg->add_reserved_name();
@@ -7040,7 +6989,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -7054,13 +7003,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool EnumDescriptorProto::MergePartialFromCodedStream(
@@ -7217,8 +7162,7 @@
 }
 
 ::google::protobuf::uint8* EnumDescriptorProto::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumDescriptorProto)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -7240,14 +7184,14 @@
       n = static_cast<unsigned int>(this->value_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        2, this->value(static_cast<int>(i)), deterministic, target);
+        2, this->value(static_cast<int>(i)), target);
   }
 
   // optional .google.protobuf.EnumOptions options = 3;
   if (cached_has_bits & 0x00000002u) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        3, HasBitSetters::options(this), deterministic, target);
+        3, HasBitSetters::options(this), target);
   }
 
   // repeated .google.protobuf.EnumDescriptorProto.EnumReservedRange reserved_range = 4;
@@ -7255,7 +7199,7 @@
       n = static_cast<unsigned int>(this->reserved_range_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        4, this->reserved_range(static_cast<int>(i)), deterministic, target);
+        4, this->reserved_range(static_cast<int>(i)), target);
   }
 
   // repeated string reserved_name = 5;
@@ -7576,13 +7520,13 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // optional string name = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.EnumValueDescriptorProto.name");
         auto str = msg->mutable_name();
@@ -7602,7 +7546,7 @@
       case 2: {
         if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ::google::protobuf::int32 value = val;
         msg->set_number(value);
@@ -7611,7 +7555,7 @@
       // optional .google.protobuf.EnumValueOptions options = 3;
       case 3: {
         if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         parser_till_end = ::google::protobuf::EnumValueOptions::_InternalParse;
         object = msg->mutable_options();
@@ -7624,7 +7568,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -7638,13 +7582,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool EnumValueDescriptorProto::MergePartialFromCodedStream(
@@ -7753,8 +7693,7 @@
 }
 
 ::google::protobuf::uint8* EnumValueDescriptorProto::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumValueDescriptorProto)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -7780,7 +7719,7 @@
   if (cached_has_bits & 0x00000002u) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        3, HasBitSetters::options(this), deterministic, target);
+        3, HasBitSetters::options(this), target);
   }
 
   if (_internal_metadata_.have_unknown_fields()) {
@@ -8062,13 +8001,13 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // optional string name = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.ServiceDescriptorProto.name");
         auto str = msg->mutable_name();
@@ -8088,7 +8027,7 @@
       case 2: {
         if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::MethodDescriptorProto::_InternalParse;
           object = msg->add_method();
@@ -8105,7 +8044,7 @@
       // optional .google.protobuf.ServiceOptions options = 3;
       case 3: {
         if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         parser_till_end = ::google::protobuf::ServiceOptions::_InternalParse;
         object = msg->mutable_options();
@@ -8118,7 +8057,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -8132,13 +8071,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool ServiceDescriptorProto::MergePartialFromCodedStream(
@@ -8249,8 +8184,7 @@
 }
 
 ::google::protobuf::uint8* ServiceDescriptorProto::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ServiceDescriptorProto)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -8272,14 +8206,14 @@
       n = static_cast<unsigned int>(this->method_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        2, this->method(static_cast<int>(i)), deterministic, target);
+        2, this->method(static_cast<int>(i)), target);
   }
 
   // optional .google.protobuf.ServiceOptions options = 3;
   if (cached_has_bits & 0x00000002u) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        3, HasBitSetters::options(this), deterministic, target);
+        3, HasBitSetters::options(this), target);
   }
 
   if (_internal_metadata_.have_unknown_fields()) {
@@ -8603,13 +8537,13 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // optional string name = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.MethodDescriptorProto.name");
         auto str = msg->mutable_name();
@@ -8628,7 +8562,7 @@
       // optional string input_type = 2;
       case 2: {
         if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.MethodDescriptorProto.input_type");
         auto str = msg->mutable_input_type();
@@ -8647,7 +8581,7 @@
       // optional string output_type = 3;
       case 3: {
         if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.MethodDescriptorProto.output_type");
         auto str = msg->mutable_output_type();
@@ -8666,7 +8600,7 @@
       // optional .google.protobuf.MethodOptions options = 4;
       case 4: {
         if (static_cast<::google::protobuf::uint8>(tag) != 34) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         parser_till_end = ::google::protobuf::MethodOptions::_InternalParse;
         object = msg->mutable_options();
@@ -8682,7 +8616,7 @@
       case 5: {
         if (static_cast<::google::protobuf::uint8>(tag) != 40) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         bool value = val;
         msg->set_client_streaming(value);
@@ -8692,14 +8626,14 @@
       case 6: {
         if (static_cast<::google::protobuf::uint8>(tag) != 48) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         bool value = val;
         msg->set_server_streaming(value);
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -8713,13 +8647,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool MethodDescriptorProto::MergePartialFromCodedStream(
@@ -8896,8 +8826,7 @@
 }
 
 ::google::protobuf::uint8* MethodDescriptorProto::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.MethodDescriptorProto)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -8940,7 +8869,7 @@
   if (cached_has_bits & 0x00000008u) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        4, HasBitSetters::options(this), deterministic, target);
+        4, HasBitSetters::options(this), target);
   }
 
   // optional bool client_streaming = 5 [default = false];
@@ -9417,13 +9346,13 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // optional string java_package = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.FileOptions.java_package");
         auto str = msg->mutable_java_package();
@@ -9442,7 +9371,7 @@
       // optional string java_outer_classname = 8;
       case 8: {
         if (static_cast<::google::protobuf::uint8>(tag) != 66) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.FileOptions.java_outer_classname");
         auto str = msg->mutable_java_outer_classname();
@@ -9462,7 +9391,7 @@
       case 9: {
         if (static_cast<::google::protobuf::uint8>(tag) != 72) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         if (!::google::protobuf::FileOptions_OptimizeMode_IsValid(val)) {
           ::google::protobuf::internal::WriteVarint(9, val, msg->mutable_unknown_fields());
@@ -9476,7 +9405,7 @@
       case 10: {
         if (static_cast<::google::protobuf::uint8>(tag) != 80) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         bool value = val;
         msg->set_java_multiple_files(value);
@@ -9485,7 +9414,7 @@
       // optional string go_package = 11;
       case 11: {
         if (static_cast<::google::protobuf::uint8>(tag) != 90) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.FileOptions.go_package");
         auto str = msg->mutable_go_package();
@@ -9505,7 +9434,7 @@
       case 16: {
         if (static_cast<::google::protobuf::uint8>(tag) != 128) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         bool value = val;
         msg->set_cc_generic_services(value);
@@ -9515,7 +9444,7 @@
       case 17: {
         if (static_cast<::google::protobuf::uint8>(tag) != 136) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         bool value = val;
         msg->set_java_generic_services(value);
@@ -9525,7 +9454,7 @@
       case 18: {
         if (static_cast<::google::protobuf::uint8>(tag) != 144) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         bool value = val;
         msg->set_py_generic_services(value);
@@ -9535,7 +9464,7 @@
       case 20: {
         if (static_cast<::google::protobuf::uint8>(tag) != 160) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         bool value = val;
         msg->set_java_generate_equals_and_hash(value);
@@ -9545,7 +9474,7 @@
       case 23: {
         if (static_cast<::google::protobuf::uint8>(tag) != 184) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         bool value = val;
         msg->set_deprecated(value);
@@ -9555,7 +9484,7 @@
       case 27: {
         if (static_cast<::google::protobuf::uint8>(tag) != 216) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         bool value = val;
         msg->set_java_string_check_utf8(value);
@@ -9565,7 +9494,7 @@
       case 31: {
         if (static_cast<::google::protobuf::uint8>(tag) != 248) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         bool value = val;
         msg->set_cc_enable_arenas(value);
@@ -9574,7 +9503,7 @@
       // optional string objc_class_prefix = 36;
       case 36: {
         if (static_cast<::google::protobuf::uint8>(tag) != 34) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.FileOptions.objc_class_prefix");
         auto str = msg->mutable_objc_class_prefix();
@@ -9593,7 +9522,7 @@
       // optional string csharp_namespace = 37;
       case 37: {
         if (static_cast<::google::protobuf::uint8>(tag) != 42) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.FileOptions.csharp_namespace");
         auto str = msg->mutable_csharp_namespace();
@@ -9612,7 +9541,7 @@
       // optional string swift_prefix = 39;
       case 39: {
         if (static_cast<::google::protobuf::uint8>(tag) != 58) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.FileOptions.swift_prefix");
         auto str = msg->mutable_swift_prefix();
@@ -9631,7 +9560,7 @@
       // optional string php_class_prefix = 40;
       case 40: {
         if (static_cast<::google::protobuf::uint8>(tag) != 66) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.FileOptions.php_class_prefix");
         auto str = msg->mutable_php_class_prefix();
@@ -9650,7 +9579,7 @@
       // optional string php_namespace = 41;
       case 41: {
         if (static_cast<::google::protobuf::uint8>(tag) != 74) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.FileOptions.php_namespace");
         auto str = msg->mutable_php_namespace();
@@ -9670,7 +9599,7 @@
       case 42: {
         if (static_cast<::google::protobuf::uint8>(tag) != 80) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         bool value = val;
         msg->set_php_generic_services(value);
@@ -9679,7 +9608,7 @@
       // optional string php_metadata_namespace = 44;
       case 44: {
         if (static_cast<::google::protobuf::uint8>(tag) != 98) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.FileOptions.php_metadata_namespace");
         auto str = msg->mutable_php_metadata_namespace();
@@ -9698,7 +9627,7 @@
       // optional string ruby_package = 45;
       case 45: {
         if (static_cast<::google::protobuf::uint8>(tag) != 106) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.FileOptions.ruby_package");
         auto str = msg->mutable_ruby_package();
@@ -9718,7 +9647,7 @@
       case 999: {
         if (static_cast<::google::protobuf::uint8>(tag) != 58) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::UninterpretedOption::_InternalParse;
           object = msg->add_uninterpreted_option();
@@ -9733,7 +9662,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -9755,13 +9684,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool FileOptions::MergePartialFromCodedStream(
@@ -10276,8 +10201,7 @@
 }
 
 ::google::protobuf::uint8* FileOptions::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FileOptions)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -10449,12 +10373,12 @@
       n = static_cast<unsigned int>(this->uninterpreted_option_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        999, this->uninterpreted_option(static_cast<int>(i)), deterministic, target);
+        999, this->uninterpreted_option(static_cast<int>(i)), target);
   }
 
   // Extension range [1000, 536870912)
   target = _extensions_.InternalSerializeWithCachedSizesToArray(
-      1000, 536870912, deterministic, target);
+      1000, 536870912, target);
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
@@ -10916,14 +10840,14 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // optional bool message_set_wire_format = 1 [default = false];
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         bool value = val;
         msg->set_message_set_wire_format(value);
@@ -10933,7 +10857,7 @@
       case 2: {
         if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         bool value = val;
         msg->set_no_standard_descriptor_accessor(value);
@@ -10943,7 +10867,7 @@
       case 3: {
         if (static_cast<::google::protobuf::uint8>(tag) != 24) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         bool value = val;
         msg->set_deprecated(value);
@@ -10953,7 +10877,7 @@
       case 7: {
         if (static_cast<::google::protobuf::uint8>(tag) != 56) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         bool value = val;
         msg->set_map_entry(value);
@@ -10963,7 +10887,7 @@
       case 999: {
         if (static_cast<::google::protobuf::uint8>(tag) != 58) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::UninterpretedOption::_InternalParse;
           object = msg->add_uninterpreted_option();
@@ -10978,7 +10902,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -11000,13 +10924,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool MessageOptions::MergePartialFromCodedStream(
@@ -11156,8 +11076,7 @@
 }
 
 ::google::protobuf::uint8* MessageOptions::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.MessageOptions)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -11188,12 +11107,12 @@
       n = static_cast<unsigned int>(this->uninterpreted_option_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        999, this->uninterpreted_option(static_cast<int>(i)), deterministic, target);
+        999, this->uninterpreted_option(static_cast<int>(i)), target);
   }
 
   // Extension range [1000, 536870912)
   target = _extensions_.InternalSerializeWithCachedSizesToArray(
-      1000, 536870912, deterministic, target);
+      1000, 536870912, target);
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
@@ -11482,14 +11401,14 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         if (!::google::protobuf::FieldOptions_CType_IsValid(val)) {
           ::google::protobuf::internal::WriteVarint(1, val, msg->mutable_unknown_fields());
@@ -11503,7 +11422,7 @@
       case 2: {
         if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         bool value = val;
         msg->set_packed(value);
@@ -11513,7 +11432,7 @@
       case 3: {
         if (static_cast<::google::protobuf::uint8>(tag) != 24) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         bool value = val;
         msg->set_deprecated(value);
@@ -11523,7 +11442,7 @@
       case 5: {
         if (static_cast<::google::protobuf::uint8>(tag) != 40) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         bool value = val;
         msg->set_lazy(value);
@@ -11533,7 +11452,7 @@
       case 6: {
         if (static_cast<::google::protobuf::uint8>(tag) != 48) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         if (!::google::protobuf::FieldOptions_JSType_IsValid(val)) {
           ::google::protobuf::internal::WriteVarint(6, val, msg->mutable_unknown_fields());
@@ -11547,7 +11466,7 @@
       case 10: {
         if (static_cast<::google::protobuf::uint8>(tag) != 80) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         bool value = val;
         msg->set_weak(value);
@@ -11557,7 +11476,7 @@
       case 999: {
         if (static_cast<::google::protobuf::uint8>(tag) != 58) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::UninterpretedOption::_InternalParse;
           object = msg->add_uninterpreted_option();
@@ -11572,7 +11491,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -11594,13 +11513,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool FieldOptions::MergePartialFromCodedStream(
@@ -11800,8 +11715,7 @@
 }
 
 ::google::protobuf::uint8* FieldOptions::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FieldOptions)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -11844,12 +11758,12 @@
       n = static_cast<unsigned int>(this->uninterpreted_option_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        999, this->uninterpreted_option(static_cast<int>(i)), deterministic, target);
+        999, this->uninterpreted_option(static_cast<int>(i)), target);
   }
 
   // Extension range [1000, 536870912)
   target = _extensions_.InternalSerializeWithCachedSizesToArray(
-      1000, 536870912, deterministic, target);
+      1000, 536870912, target);
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
@@ -12122,14 +12036,14 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
       case 999: {
         if (static_cast<::google::protobuf::uint8>(tag) != 58) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::UninterpretedOption::_InternalParse;
           object = msg->add_uninterpreted_option();
@@ -12144,7 +12058,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -12166,13 +12080,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool OneofOptions::MergePartialFromCodedStream(
@@ -12249,8 +12159,7 @@
 }
 
 ::google::protobuf::uint8* OneofOptions::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.OneofOptions)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -12260,12 +12169,12 @@
       n = static_cast<unsigned int>(this->uninterpreted_option_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        999, this->uninterpreted_option(static_cast<int>(i)), deterministic, target);
+        999, this->uninterpreted_option(static_cast<int>(i)), target);
   }
 
   // Extension range [1000, 536870912)
   target = _extensions_.InternalSerializeWithCachedSizesToArray(
-      1000, 536870912, deterministic, target);
+      1000, 536870912, target);
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
@@ -12492,14 +12401,14 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // optional bool allow_alias = 2;
       case 2: {
         if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         bool value = val;
         msg->set_allow_alias(value);
@@ -12509,7 +12418,7 @@
       case 3: {
         if (static_cast<::google::protobuf::uint8>(tag) != 24) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         bool value = val;
         msg->set_deprecated(value);
@@ -12519,7 +12428,7 @@
       case 999: {
         if (static_cast<::google::protobuf::uint8>(tag) != 58) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::UninterpretedOption::_InternalParse;
           object = msg->add_uninterpreted_option();
@@ -12534,7 +12443,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -12556,13 +12465,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool EnumOptions::MergePartialFromCodedStream(
@@ -12676,8 +12581,7 @@
 }
 
 ::google::protobuf::uint8* EnumOptions::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumOptions)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -12698,12 +12602,12 @@
       n = static_cast<unsigned int>(this->uninterpreted_option_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        999, this->uninterpreted_option(static_cast<int>(i)), deterministic, target);
+        999, this->uninterpreted_option(static_cast<int>(i)), target);
   }
 
   // Extension range [1000, 536870912)
   target = _extensions_.InternalSerializeWithCachedSizesToArray(
-      1000, 536870912, deterministic, target);
+      1000, 536870912, target);
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
@@ -12945,14 +12849,14 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // optional bool deprecated = 1 [default = false];
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         bool value = val;
         msg->set_deprecated(value);
@@ -12962,7 +12866,7 @@
       case 999: {
         if (static_cast<::google::protobuf::uint8>(tag) != 58) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::UninterpretedOption::_InternalParse;
           object = msg->add_uninterpreted_option();
@@ -12977,7 +12881,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -12999,13 +12903,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool EnumValueOptions::MergePartialFromCodedStream(
@@ -13101,8 +13001,7 @@
 }
 
 ::google::protobuf::uint8* EnumValueOptions::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumValueOptions)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -13118,12 +13017,12 @@
       n = static_cast<unsigned int>(this->uninterpreted_option_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        999, this->uninterpreted_option(static_cast<int>(i)), deterministic, target);
+        999, this->uninterpreted_option(static_cast<int>(i)), target);
   }
 
   // Extension range [1000, 536870912)
   target = _extensions_.InternalSerializeWithCachedSizesToArray(
-      1000, 536870912, deterministic, target);
+      1000, 536870912, target);
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
@@ -13350,14 +13249,14 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // optional bool deprecated = 33 [default = false];
       case 33: {
         if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         bool value = val;
         msg->set_deprecated(value);
@@ -13367,7 +13266,7 @@
       case 999: {
         if (static_cast<::google::protobuf::uint8>(tag) != 58) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::UninterpretedOption::_InternalParse;
           object = msg->add_uninterpreted_option();
@@ -13382,7 +13281,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -13404,13 +13303,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool ServiceOptions::MergePartialFromCodedStream(
@@ -13506,8 +13401,7 @@
 }
 
 ::google::protobuf::uint8* ServiceOptions::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ServiceOptions)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -13523,12 +13417,12 @@
       n = static_cast<unsigned int>(this->uninterpreted_option_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        999, this->uninterpreted_option(static_cast<int>(i)), deterministic, target);
+        999, this->uninterpreted_option(static_cast<int>(i)), target);
   }
 
   // Extension range [1000, 536870912)
   target = _extensions_.InternalSerializeWithCachedSizesToArray(
-      1000, 536870912, deterministic, target);
+      1000, 536870912, target);
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
@@ -13768,14 +13662,14 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // optional bool deprecated = 33 [default = false];
       case 33: {
         if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         bool value = val;
         msg->set_deprecated(value);
@@ -13785,7 +13679,7 @@
       case 34: {
         if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         if (!::google::protobuf::MethodOptions_IdempotencyLevel_IsValid(val)) {
           ::google::protobuf::internal::WriteVarint(34, val, msg->mutable_unknown_fields());
@@ -13799,7 +13693,7 @@
       case 999: {
         if (static_cast<::google::protobuf::uint8>(tag) != 58) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::UninterpretedOption::_InternalParse;
           object = msg->add_uninterpreted_option();
@@ -13814,7 +13708,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -13836,13 +13730,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool MethodOptions::MergePartialFromCodedStream(
@@ -13963,8 +13853,7 @@
 }
 
 ::google::protobuf::uint8* MethodOptions::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.MethodOptions)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -13986,12 +13875,12 @@
       n = static_cast<unsigned int>(this->uninterpreted_option_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        999, this->uninterpreted_option(static_cast<int>(i)), deterministic, target);
+        999, this->uninterpreted_option(static_cast<int>(i)), target);
   }
 
   // Extension range [1000, 536870912)
   target = _extensions_.InternalSerializeWithCachedSizesToArray(
-      1000, 536870912, deterministic, target);
+      1000, 536870912, target);
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
@@ -14242,13 +14131,13 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // required string name_part = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.UninterpretedOption.NamePart.name_part");
         auto str = msg->mutable_name_part();
@@ -14268,14 +14157,14 @@
       case 2: {
         if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         bool value = val;
         msg->set_is_extension(value);
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -14289,13 +14178,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool UninterpretedOption_NamePart::MergePartialFromCodedStream(
@@ -14387,8 +14272,7 @@
 }
 
 ::google::protobuf::uint8* UninterpretedOption_NamePart::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.UninterpretedOption.NamePart)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -14705,14 +14589,14 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
       case 2: {
         if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::UninterpretedOption_NamePart::_InternalParse;
           object = msg->add_name();
@@ -14729,7 +14613,7 @@
       // optional string identifier_value = 3;
       case 3: {
         if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.UninterpretedOption.identifier_value");
         auto str = msg->mutable_identifier_value();
@@ -14749,7 +14633,7 @@
       case 4: {
         if (static_cast<::google::protobuf::uint8>(tag) != 32) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ::google::protobuf::uint64 value = val;
         msg->set_positive_int_value(value);
@@ -14759,7 +14643,7 @@
       case 5: {
         if (static_cast<::google::protobuf::uint8>(tag) != 40) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ::google::protobuf::int64 value = val;
         msg->set_negative_int_value(value);
@@ -14777,7 +14661,7 @@
       // optional bytes string_value = 7;
       case 7: {
         if (static_cast<::google::protobuf::uint8>(tag) != 58) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         auto str = msg->mutable_string_value();
         if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
@@ -14795,7 +14679,7 @@
       // optional string aggregate_value = 8;
       case 8: {
         if (static_cast<::google::protobuf::uint8>(tag) != 66) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.UninterpretedOption.aggregate_value");
         auto str = msg->mutable_aggregate_value();
@@ -14812,7 +14696,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -14826,13 +14710,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool UninterpretedOption::MergePartialFromCodedStream(
@@ -15022,8 +14902,7 @@
 }
 
 ::google::protobuf::uint8* UninterpretedOption::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.UninterpretedOption)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -15033,7 +14912,7 @@
       n = static_cast<unsigned int>(this->name_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        2, this->name(static_cast<int>(i)), deterministic, target);
+        2, this->name(static_cast<int>(i)), target);
   }
 
   cached_has_bits = _has_bits_[0];
@@ -15391,13 +15270,13 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // repeated int32 path = 1 [packed = true];
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) == 10) {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::internal::PackedInt32Parser;
           object = msg->mutable_path();
@@ -15409,7 +15288,7 @@
         } else if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
         do {
           ::google::protobuf::uint64 val;
-          ptr = Varint::Parse64(ptr, &val);
+          ptr = ::google::protobuf::io::Parse64(ptr, &val);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           ::google::protobuf::int32 value = val;
           msg->add_path(value);
@@ -15420,7 +15299,7 @@
       // repeated int32 span = 2 [packed = true];
       case 2: {
         if (static_cast<::google::protobuf::uint8>(tag) == 18) {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::internal::PackedInt32Parser;
           object = msg->mutable_span();
@@ -15432,7 +15311,7 @@
         } else if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
         do {
           ::google::protobuf::uint64 val;
-          ptr = Varint::Parse64(ptr, &val);
+          ptr = ::google::protobuf::io::Parse64(ptr, &val);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           ::google::protobuf::int32 value = val;
           msg->add_span(value);
@@ -15443,7 +15322,7 @@
       // optional string leading_comments = 3;
       case 3: {
         if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.SourceCodeInfo.Location.leading_comments");
         auto str = msg->mutable_leading_comments();
@@ -15462,7 +15341,7 @@
       // optional string trailing_comments = 4;
       case 4: {
         if (static_cast<::google::protobuf::uint8>(tag) != 34) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.SourceCodeInfo.Location.trailing_comments");
         auto str = msg->mutable_trailing_comments();
@@ -15482,7 +15361,7 @@
       case 6: {
         if (static_cast<::google::protobuf::uint8>(tag) != 50) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           ctx->extra_parse_data().SetFieldName("google.protobuf.SourceCodeInfo.Location.leading_detached_comments");
           auto str = msg->add_leading_detached_comments();
@@ -15501,7 +15380,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -15515,13 +15394,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool SourceCodeInfo_Location::MergePartialFromCodedStream(
@@ -15700,8 +15575,7 @@
 }
 
 ::google::protobuf::uint8* SourceCodeInfo_Location::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.SourceCodeInfo.Location)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -16022,14 +15896,14 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // repeated .google.protobuf.SourceCodeInfo.Location location = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::SourceCodeInfo_Location::_InternalParse;
           object = msg->add_location();
@@ -16044,7 +15918,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -16058,13 +15932,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool SourceCodeInfo::MergePartialFromCodedStream(
@@ -16132,8 +16002,7 @@
 }
 
 ::google::protobuf::uint8* SourceCodeInfo::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.SourceCodeInfo)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -16143,7 +16012,7 @@
       n = static_cast<unsigned int>(this->location_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        1, this->location(static_cast<int>(i)), deterministic, target);
+        1, this->location(static_cast<int>(i)), target);
   }
 
   if (_internal_metadata_.have_unknown_fields()) {
@@ -16376,13 +16245,13 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // repeated int32 path = 1 [packed = true];
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) == 10) {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::internal::PackedInt32Parser;
           object = msg->mutable_path();
@@ -16394,7 +16263,7 @@
         } else if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
         do {
           ::google::protobuf::uint64 val;
-          ptr = Varint::Parse64(ptr, &val);
+          ptr = ::google::protobuf::io::Parse64(ptr, &val);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           ::google::protobuf::int32 value = val;
           msg->add_path(value);
@@ -16405,7 +16274,7 @@
       // optional string source_file = 2;
       case 2: {
         if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.GeneratedCodeInfo.Annotation.source_file");
         auto str = msg->mutable_source_file();
@@ -16425,7 +16294,7 @@
       case 3: {
         if (static_cast<::google::protobuf::uint8>(tag) != 24) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ::google::protobuf::int32 value = val;
         msg->set_begin(value);
@@ -16435,14 +16304,14 @@
       case 4: {
         if (static_cast<::google::protobuf::uint8>(tag) != 32) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ::google::protobuf::int32 value = val;
         msg->set_end(value);
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -16456,13 +16325,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool GeneratedCodeInfo_Annotation::MergePartialFromCodedStream(
@@ -16599,8 +16464,7 @@
 }
 
 ::google::protobuf::uint8* GeneratedCodeInfo_Annotation::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.GeneratedCodeInfo.Annotation)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -16881,14 +16745,14 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::GeneratedCodeInfo_Annotation::_InternalParse;
           object = msg->add_annotation();
@@ -16903,7 +16767,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -16917,13 +16781,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool GeneratedCodeInfo::MergePartialFromCodedStream(
@@ -16991,8 +16851,7 @@
 }
 
 ::google::protobuf::uint8* GeneratedCodeInfo::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.GeneratedCodeInfo)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -17002,7 +16861,7 @@
       n = static_cast<unsigned int>(this->annotation_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        1, this->annotation(static_cast<int>(i)), deterministic, target);
+        1, this->annotation(static_cast<int>(i)), target);
   }
 
   if (_internal_metadata_.have_unknown_fields()) {
diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h
index 4775db7..5ec9398 100644
--- a/src/google/protobuf/descriptor.pb.h
+++ b/src/google/protobuf/descriptor.pb.h
@@ -386,7 +386,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -526,7 +526,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -855,7 +855,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -1011,7 +1011,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -1154,7 +1154,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -1436,7 +1436,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -1579,7 +1579,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -1962,7 +1962,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -2127,7 +2127,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -2270,7 +2270,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -2486,7 +2486,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -2659,7 +2659,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -2837,7 +2837,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -3068,7 +3068,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -3569,7 +3569,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -3744,7 +3744,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -3991,7 +3991,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -4134,7 +4134,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -4293,7 +4293,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -4444,7 +4444,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -4595,7 +4595,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -4782,7 +4782,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -4945,7 +4945,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -5186,7 +5186,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -5414,7 +5414,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -5556,7 +5556,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -5738,7 +5738,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc
index e48e440..3ed11aa 100644
--- a/src/google/protobuf/descriptor_unittest.cc
+++ b/src/google/protobuf/descriptor_unittest.cc
@@ -6005,6 +6005,34 @@
       "with an existing enum type.\n");
 }
 
+TEST_F(ValidationErrorTest, EnumValuesConflictWithDifferentCasing) {
+  BuildFileWithErrors(
+      "syntax: 'proto3'"
+      "name: 'foo.proto' "
+      "enum_type {"
+      "  name: 'FooEnum' "
+      "  value { name: 'BAR' number: 0 }"
+      "  value { name: 'bar' number: 1 }"
+      "}",
+      "foo.proto: bar: NAME: Enum name bar has the same name as BAR "
+      "if you ignore case and strip out the enum name prefix (if any). "
+      "This is error-prone and can lead to undefined behavior. "
+      "Please avoid doing this. If you are using allow_alias, please assign "
+      "the same numeric value to both enums.\n");
+
+  // Not an error because both enums are mapped to the same value.
+  BuildFile(
+      "syntax: 'proto3'"
+      "name: 'foo.proto' "
+      "enum_type {"
+      "  name: 'FooEnum' "
+      "  options { allow_alias: true }"
+      "  value { name: 'UNKNOWN' number: 0 }"
+      "  value { name: 'BAR' number: 1 }"
+      "  value { name: 'bar' number: 1 }"
+      "}");
+}
+
 TEST_F(ValidationErrorTest, EnumValuesConflictWhenPrefixesStripped) {
   BuildFileWithErrors(
       "syntax: 'proto3'"
@@ -6014,9 +6042,11 @@
       "  value { name: 'FOO_ENUM_BAZ' number: 0 }"
       "  value { name: 'BAZ' number: 1 }"
       "}",
-      "foo.proto: BAZ: NAME: When enum name is stripped and label is "
-      "PascalCased (Baz), this value label conflicts with FOO_ENUM_BAZ. This "
-      "will make the proto fail to compile for some languages, such as C#.\n");
+      "foo.proto: BAZ: NAME: Enum name BAZ has the same name as FOO_ENUM_BAZ "
+      "if you ignore case and strip out the enum name prefix (if any). "
+      "This is error-prone and can lead to undefined behavior. "
+      "Please avoid doing this. If you are using allow_alias, please assign "
+      "the same numeric value to both enums.\n");
 
   BuildFileWithErrors(
       "syntax: 'proto3'"
@@ -6026,9 +6056,11 @@
       "  value { name: 'FOOENUM_BAZ' number: 0 }"
       "  value { name: 'BAZ' number: 1 }"
       "}",
-      "foo.proto: BAZ: NAME: When enum name is stripped and label is "
-      "PascalCased (Baz), this value label conflicts with FOOENUM_BAZ. This "
-      "will make the proto fail to compile for some languages, such as C#.\n");
+      "foo.proto: BAZ: NAME: Enum name BAZ has the same name as FOOENUM_BAZ "
+      "if you ignore case and strip out the enum name prefix (if any). "
+      "This is error-prone and can lead to undefined behavior. "
+      "Please avoid doing this. If you are using allow_alias, please assign "
+      "the same numeric value to both enums.\n");
 
   BuildFileWithErrors(
       "syntax: 'proto3'"
@@ -6038,10 +6070,11 @@
       "  value { name: 'FOO_ENUM_BAR_BAZ' number: 0 }"
       "  value { name: 'BAR__BAZ' number: 1 }"
       "}",
-      "foo.proto: BAR__BAZ: NAME: When enum name is stripped and label is "
-      "PascalCased (BarBaz), this value label conflicts with "
-      "FOO_ENUM_BAR_BAZ. This will make the proto fail to compile for some "
-      "languages, such as C#.\n");
+      "foo.proto: BAR__BAZ: NAME: Enum name BAR__BAZ has the same name as "
+      "FOO_ENUM_BAR_BAZ if you ignore case and strip out the enum name prefix "
+      "(if any). This is error-prone and can lead to undefined behavior. "
+      "Please avoid doing this. If you are using allow_alias, please assign "
+      "the same numeric value to both enums.\n");
 
   BuildFileWithErrors(
       "syntax: 'proto3'"
@@ -6051,10 +6084,11 @@
       "  value { name: 'FOO_ENUM__BAR_BAZ' number: 0 }"
       "  value { name: 'BAR_BAZ' number: 1 }"
       "}",
-      "foo.proto: BAR_BAZ: NAME: When enum name is stripped and label is "
-      "PascalCased (BarBaz), this value label conflicts with "
-      "FOO_ENUM__BAR_BAZ. This will make the proto fail to compile for some "
-      "languages, such as C#.\n");
+      "foo.proto: BAR_BAZ: NAME: Enum name BAR_BAZ has the same name as "
+      "FOO_ENUM__BAR_BAZ if you ignore case and strip out the enum name prefix "
+      "(if any). This is error-prone and can lead to undefined behavior. "
+      "Please avoid doing this. If you are using allow_alias, please assign "
+      "the same numeric value to both enums.\n");
 
   // This isn't an error because the underscore will cause the PascalCase to
   // differ by case (BarBaz vs. Barbaz).
diff --git a/src/google/protobuf/duration.pb.cc b/src/google/protobuf/duration.pb.cc
index 53c1a55..41fdbec 100644
--- a/src/google/protobuf/duration.pb.cc
+++ b/src/google/protobuf/duration.pb.cc
@@ -182,14 +182,14 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // int64 seconds = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ::google::protobuf::int64 value = val;
         msg->set_seconds(value);
@@ -199,14 +199,14 @@
       case 2: {
         if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ::google::protobuf::int32 value = val;
         msg->set_nanos(value);
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -220,13 +220,6 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
-  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool Duration::MergePartialFromCodedStream(
@@ -310,8 +303,7 @@
 }
 
 ::google::protobuf::uint8* Duration::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Duration)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
diff --git a/src/google/protobuf/duration.pb.h b/src/google/protobuf/duration.pb.h
index 7735f2c..a3b55d3 100644
--- a/src/google/protobuf/duration.pb.h
+++ b/src/google/protobuf/duration.pb.h
@@ -139,7 +139,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
diff --git a/src/google/protobuf/empty.pb.cc b/src/google/protobuf/empty.pb.cc
index 1dd9047..7f401fe 100644
--- a/src/google/protobuf/empty.pb.cc
+++ b/src/google/protobuf/empty.pb.cc
@@ -168,11 +168,10 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       default: {
-      handle_unusual: (void)&&handle_unusual;
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -186,13 +185,6 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
-  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool Empty::MergePartialFromCodedStream(
@@ -235,8 +227,7 @@
 }
 
 ::google::protobuf::uint8* Empty::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Empty)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
diff --git a/src/google/protobuf/empty.pb.h b/src/google/protobuf/empty.pb.h
index 0a717a6..2e64a6f 100644
--- a/src/google/protobuf/empty.pb.h
+++ b/src/google/protobuf/empty.pb.h
@@ -139,7 +139,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
diff --git a/src/google/protobuf/extension_set.h b/src/google/protobuf/extension_set.h
index 57dbdef..e5ae3d4 100644
--- a/src/google/protobuf/extension_set.h
+++ b/src/google/protobuf/extension_set.h
@@ -48,6 +48,7 @@
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/parse_context.h>
+#include <google/protobuf/io/coded_stream.h>
 #include <google/protobuf/port.h>
 #include <google/protobuf/repeated_field.h>
 #include <google/protobuf/wire_format_lite.h>
@@ -461,13 +462,11 @@
   // Returns a pointer past the last written byte.
   uint8* InternalSerializeWithCachedSizesToArray(int start_field_number,
                                                  int end_field_number,
-                                                 bool deterministic,
                                                  uint8* target) const;
 
   // Like above but serializes in MessageSet format.
   void SerializeMessageSetWithCachedSizes(io::CodedOutputStream* output) const;
-  uint8* InternalSerializeMessageSetWithCachedSizesToArray(bool deterministic,
-                                                           uint8* target) const;
+  uint8* InternalSerializeMessageSetWithCachedSizesToArray(uint8* target) const;
 
   // For backward-compatibility, versions of two of the above methods that
   // serialize deterministically iff SetDefaultSerializationDeterministic()
@@ -531,12 +530,6 @@
     virtual void WriteMessage(int number,
                               io::CodedOutputStream* output) const = 0;
     virtual uint8* WriteMessageToArray(int number, uint8* target) const = 0;
-    virtual uint8* InternalWriteMessageToArray(int number, bool,
-                                               uint8* target) const {
-      // TODO(gpike): make this pure virtual. This is a placeholder because we
-      // need to update third_party/upb, for example.
-      return WriteMessageToArray(number, target);
-    }
 
    private:
     virtual void UnusedKeyMethod();  // Dummy key method to avoid weak vtable.
@@ -606,12 +599,11 @@
     void SerializeFieldWithCachedSizes(int number,
                                        io::CodedOutputStream* output) const;
     uint8* InternalSerializeFieldWithCachedSizesToArray(int number,
-                                                        bool deterministic,
                                                         uint8* target) const;
     void SerializeMessageSetItemWithCachedSizes(
         int number, io::CodedOutputStream* output) const;
     uint8* InternalSerializeMessageSetItemWithCachedSizesToArray(
-        int number, bool deterministic, uint8* target) const;
+        int number, uint8* target) const;
     size_t ByteSize(int number) const;
     size_t MessageSetItemByteSize(int number) const;
     void Clear();
@@ -819,11 +811,10 @@
                             ExtensionSet* ext, Metadata* metadata,
                             internal::ParseContext* ctx) {
   auto ptr = begin;
-  int depth;
-  (void)depth;
+  int depth = 0;
   while (ptr < end) {
     uint32 tag;
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     if (tag == WireFormatLite::kMessageSetItemStartTag) {
       ctx->extra_parse_data().payload.clear();
@@ -848,6 +839,7 @@
   }
   return ptr;
 }
+
 #endif
 
 // These are just for convenience...
diff --git a/src/google/protobuf/extension_set_heavy.cc b/src/google/protobuf/extension_set_heavy.cc
index 90a96b5..3642250 100644
--- a/src/google/protobuf/extension_set_heavy.cc
+++ b/src/google/protobuf/extension_set_heavy.cc
@@ -399,7 +399,7 @@
     uint32 tag = *ptr++;
     if (tag == WireFormatLite::kMessageSetTypeIdTag) {
       uint32 type_id;
-      ptr = Varint::Parse32(ptr, &type_id);
+      ptr = io::Parse32(ptr, &type_id);
       GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
 
       if (ctx->extra_parse_data().payload.empty()) {
@@ -439,7 +439,7 @@
       break;
     } else if (tag == WireFormatLite::kMessageSetMessageTag) {
       uint32 size;
-      ptr = Varint::Parse32Inline(ptr, &size);
+      ptr = io::Parse32(ptr, &size);
       GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
       ParseClosure child = {internal::StringParser,
                             &ctx->extra_parse_data().payload};
@@ -452,7 +452,7 @@
       }
     } else {
       ptr--;
-      ptr = Varint::Parse32(ptr, &tag);
+      ptr = io::Parse32(ptr, &tag);
       GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
       auto res =
           ParseField(tag, parent, ptr, end, containing_type, metadata, ctx);
@@ -555,26 +555,23 @@
 uint8* ExtensionSet::SerializeWithCachedSizesToArray(int start_field_number,
                                                      int end_field_number,
                                                      uint8* target) const {
-  return InternalSerializeWithCachedSizesToArray(
-      start_field_number, end_field_number,
-      io::CodedOutputStream::IsDefaultSerializationDeterministic(), target);
+  return InternalSerializeWithCachedSizesToArray(start_field_number,
+                                                 end_field_number, target);
 }
 
 uint8* ExtensionSet::SerializeMessageSetWithCachedSizesToArray(
     uint8* target) const {
-  return InternalSerializeMessageSetWithCachedSizesToArray(
-      io::CodedOutputStream::IsDefaultSerializationDeterministic(), target);
+  return InternalSerializeMessageSetWithCachedSizesToArray(target);
 }
 
 uint8* ExtensionSet::InternalSerializeWithCachedSizesToArray(
-    int start_field_number, int end_field_number, bool deterministic,
-    uint8* target) const {
+    int start_field_number, int end_field_number, uint8* target) const {
   if (PROTOBUF_PREDICT_FALSE(is_large())) {
     const auto& end = map_.large->end();
     for (auto it = map_.large->lower_bound(start_field_number);
          it != end && it->first < end_field_number; ++it) {
       target = it->second.InternalSerializeFieldWithCachedSizesToArray(
-          it->first, deterministic, target);
+          it->first, target);
     }
     return target;
   }
@@ -582,23 +579,23 @@
   for (const KeyValue* it = std::lower_bound(
            flat_begin(), end, start_field_number, KeyValue::FirstComparator());
        it != end && it->first < end_field_number; ++it) {
-    target = it->second.InternalSerializeFieldWithCachedSizesToArray(
-        it->first, deterministic, target);
+    target = it->second.InternalSerializeFieldWithCachedSizesToArray(it->first,
+                                                                     target);
   }
   return target;
 }
 
 uint8* ExtensionSet::InternalSerializeMessageSetWithCachedSizesToArray(
-    bool deterministic, uint8* target) const {
-  ForEach([deterministic, &target](int number, const Extension& ext) {
-    target = ext.InternalSerializeMessageSetItemWithCachedSizesToArray(
-        number, deterministic, target);
+    uint8* target) const {
+  ForEach([&target](int number, const Extension& ext) {
+    target = ext.InternalSerializeMessageSetItemWithCachedSizesToArray(number,
+                                                                       target);
   });
   return target;
 }
 
 uint8* ExtensionSet::Extension::InternalSerializeFieldWithCachedSizesToArray(
-    int number, bool deterministic, uint8* target) const {
+    int number, uint8* target) const {
   if (is_repeated) {
     if (is_packed) {
       if (cached_size == 0) return target;
@@ -666,14 +663,13 @@
         HANDLE_TYPE(   BYTES,    Bytes,  string);
         HANDLE_TYPE(    ENUM,     Enum,    enum);
 #undef HANDLE_TYPE
-#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE)                        \
-        case FieldDescriptor::TYPE_##UPPERCASE:                             \
-          for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) {  \
-            target = WireFormatLite::InternalWrite##CAMELCASE##ToArray(     \
-                      number, repeated_##LOWERCASE##_value->Get(i),         \
-                      deterministic, target);                               \
-          }                                                                 \
-          break
+#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE)                 \
+  case FieldDescriptor::TYPE_##UPPERCASE:                            \
+    for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \
+      target = WireFormatLite::InternalWrite##CAMELCASE##ToArray(    \
+          number, repeated_##LOWERCASE##_value->Get(i), target);     \
+    }                                                                \
+    break
 
         HANDLE_TYPE(   GROUP,    Group, message);
         HANDLE_TYPE( MESSAGE,  Message, message);
@@ -708,11 +704,10 @@
 #undef HANDLE_TYPE
       case FieldDescriptor::TYPE_MESSAGE:
         if (is_lazy) {
-          target = lazymessage_value->InternalWriteMessageToArray(
-              number, deterministic, target);
+          target = lazymessage_value->WriteMessageToArray(number, target);
         } else {
           target = WireFormatLite::InternalWriteMessageToArray(
-              number, *message_value, deterministic, target);
+              number, *message_value, target);
         }
         break;
     }
@@ -722,12 +717,11 @@
 
 uint8*
 ExtensionSet::Extension::InternalSerializeMessageSetItemWithCachedSizesToArray(
-    int number, bool deterministic, uint8* target) const {
+    int number, uint8* target) const {
   if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) {
     // Not a valid MessageSet extension, but serialize it the normal way.
     GOOGLE_LOG(WARNING) << "Invalid message set extension.";
-    return InternalSerializeFieldWithCachedSizesToArray(number, deterministic,
-                                                        target);
+    return InternalSerializeFieldWithCachedSizesToArray(number, target);
   }
 
   if (is_cleared) return target;
@@ -740,12 +734,11 @@
       WireFormatLite::kMessageSetTypeIdNumber, number, target);
   // Write message.
   if (is_lazy) {
-    target = lazymessage_value->InternalWriteMessageToArray(
-        WireFormatLite::kMessageSetMessageNumber, deterministic, target);
+    target = lazymessage_value->WriteMessageToArray(
+        WireFormatLite::kMessageSetMessageNumber, target);
   } else {
     target = WireFormatLite::InternalWriteMessageToArray(
-        WireFormatLite::kMessageSetMessageNumber, *message_value, deterministic,
-        target);
+        WireFormatLite::kMessageSetMessageNumber, *message_value, target);
   }
   // End group.
   target = io::CodedOutputStream::WriteTagToArray(
diff --git a/src/google/protobuf/extension_set_inl.h b/src/google/protobuf/extension_set_inl.h
index 93a0558..ed9f19c 100644
--- a/src/google/protobuf/extension_set_inl.h
+++ b/src/google/protobuf/extension_set_inl.h
@@ -92,7 +92,7 @@
 #define HANDLE_VARINT_TYPE(UPPERCASE, CPP_CAMELCASE)                        \
   case WireFormatLite::TYPE_##UPPERCASE: {                                  \
     uint64 value;                                                           \
-    ptr = Varint::Parse64(ptr, &value);                                     \
+    ptr = io::Parse64(ptr, &value);                                     \
     GOOGLE_PROTOBUF_ASSERT_RETURN(ptr, std::make_pair(nullptr, true));     \
     if (extension.is_repeated) {                                            \
       Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE,          \
@@ -111,7 +111,7 @@
 #define HANDLE_SVARINT_TYPE(UPPERCASE, CPP_CAMELCASE, SIZE)                 \
   case WireFormatLite::TYPE_##UPPERCASE: {                                  \
     uint64 val;                                                             \
-    ptr = Varint::Parse64(ptr, &val);                                       \
+    ptr = io::Parse64(ptr, &val);                                       \
     GOOGLE_PROTOBUF_ASSERT_RETURN(ptr, std::make_pair(nullptr, true));     \
     auto value = WireFormatLite::ZigZagDecode##SIZE(val);                   \
     if (extension.is_repeated) {                                            \
@@ -151,7 +151,7 @@
 
       case WireFormatLite::TYPE_ENUM: {
         uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_ASSERT_RETURN(ptr, std::make_pair(nullptr, true));
         int value = val;
 
@@ -221,7 +221,7 @@
 
 length_delim:
   uint32 size;
-  ptr = Varint::Parse32Inline(ptr, &size);
+  ptr = io::Parse32(ptr, &size);
   GOOGLE_PROTOBUF_ASSERT_RETURN(ptr, std::make_pair(nullptr, true));
   if (size > end - ptr) goto len_delim_till_end;
   {
diff --git a/src/google/protobuf/field_mask.pb.cc b/src/google/protobuf/field_mask.pb.cc
index f58a99e..f266ca2 100644
--- a/src/google/protobuf/field_mask.pb.cc
+++ b/src/google/protobuf/field_mask.pb.cc
@@ -176,14 +176,14 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // repeated string paths = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           ctx->extra_parse_data().SetFieldName("google.protobuf.FieldMask.paths");
           auto str = msg->add_paths();
@@ -202,7 +202,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -216,13 +216,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool FieldMask::MergePartialFromCodedStream(
@@ -296,8 +292,7 @@
 }
 
 ::google::protobuf::uint8* FieldMask::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FieldMask)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
diff --git a/src/google/protobuf/field_mask.pb.h b/src/google/protobuf/field_mask.pb.h
index 1015521..8ad3f6b 100644
--- a/src/google/protobuf/field_mask.pb.h
+++ b/src/google/protobuf/field_mask.pb.h
@@ -139,7 +139,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc
index f926da2..96852ea 100644
--- a/src/google/protobuf/generated_message_reflection.cc
+++ b/src/google/protobuf/generated_message_reflection.cc
@@ -1706,8 +1706,6 @@
   if (field->cpp_type() != cpptype)
     ReportReflectionUsageTypeError(descriptor_,
         field, "MutableRawRepeatedField", cpptype);
-  if (ctype >= 0 && !field->is_extension())
-    GOOGLE_CHECK_EQ(field->options().ctype(), ctype) << "subtype mismatch";
   if (desc != NULL)
     GOOGLE_CHECK_EQ(field->message_type(), desc) << "wrong submessage type";
   if (field->is_extension()) {
@@ -2224,7 +2222,7 @@
   }
 }
 
-MapFieldBase* GeneratedMessageReflection::MapData(
+MapFieldBase* GeneratedMessageReflection::MutableMapData(
     Message* message, const FieldDescriptor* field) const {
   USAGE_CHECK(IsMapFieldInApi(field),
               "GetMapData",
@@ -2232,6 +2230,14 @@
   return MutableRaw<MapFieldBase>(message, field);
 }
 
+const MapFieldBase* GeneratedMessageReflection::GetMapData(
+    const Message& message, const FieldDescriptor* field) const {
+  USAGE_CHECK(IsMapFieldInApi(field),
+              "GetMapData",
+              "Field is not a map field.");
+  return &(GetRaw<MapFieldBase>(message, field));
+}
+
 namespace {
 
 // Helper function to transform migration schema into reflection schema.
diff --git a/src/google/protobuf/generated_message_reflection.h b/src/google/protobuf/generated_message_reflection.h
index 0ffb3ff..d154478 100644
--- a/src/google/protobuf/generated_message_reflection.h
+++ b/src/google/protobuf/generated_message_reflection.h
@@ -670,8 +670,11 @@
                                       Message* sub_message,
                                       const FieldDescriptor* field) const;
 
-  internal::MapFieldBase* MapData(Message* message,
-                                  const FieldDescriptor* field) const override;
+  internal::MapFieldBase* MutableMapData(
+      Message* message, const FieldDescriptor* field) const override;
+
+  const internal::MapFieldBase* GetMapData(
+      const Message& message, const FieldDescriptor* field) const override;
 
   friend inline  // inline so nobody can call this function.
       void
diff --git a/src/google/protobuf/generated_message_table_driven.h b/src/google/protobuf/generated_message_table_driven.h
index eb85ef5..8fee7ab 100644
--- a/src/google/protobuf/generated_message_table_driven.h
+++ b/src/google/protobuf/generated_message_table_driven.h
@@ -52,6 +52,8 @@
 #error "You cannot SWIG proto headers"
 #endif
 
+#include <google/protobuf/port_def.inc>
+
 namespace google {
 namespace protobuf {
 namespace internal {
@@ -79,6 +81,41 @@
 
 static_assert(TYPE_MAP < kRepeatedMask, "Invalid enum");
 
+struct PROTOBUF_EXPORT FieldMetadata {
+  uint32 offset;  // offset of this field in the struct
+  uint32 tag;     // field * 8 + wire_type
+  // byte offset * 8 + bit_offset;
+  // if the high bit is set then this is the byte offset of the oneof_case
+  // for this field.
+  uint32 has_offset;
+  uint32 type;      // the type of this field.
+  const void* ptr;  // auxiliary data
+
+  // From the serializer point of view each fundamental type can occur in
+  // 4 different ways. For simplicity we treat all combinations as a cartesion
+  // product although not all combinations are allowed.
+  enum FieldTypeClass {
+    kPresence,
+    kNoPresence,
+    kRepeated,
+    kPacked,
+    kOneOf,
+    kNumTypeClasses  // must be last enum
+  };
+  // C++ protobuf has 20 fundamental types, were we added Cord and StringPiece
+  // and also distinquish the same types if they have different wire format.
+  enum {
+    kCordType = 19,
+    kStringPieceType = 20,
+    kInlinedType = 21,
+    kNumTypes = 21,
+    kSpecial = kNumTypes * kNumTypeClasses,
+  };
+
+  static int CalculateType(int fundamental_type, FieldTypeClass type_class);
+};
+
+
 // TODO(ckennelly):  Add a static assertion to ensure that these masks do not
 // conflict with wiretypes.
 
@@ -199,8 +236,108 @@
   return WireFormatLite::ReadMessageNoVirtual(input, &parser);
 }
 
+struct SerializationTable {
+  int num_fields;
+  const FieldMetadata* field_table;
+};
+
+PROTOBUF_EXPORT void SerializeInternal(const uint8* base,
+                                       const FieldMetadata* table,
+                                       int32 num_fields,
+                                       io::CodedOutputStream* output);
+
+inline void TableSerialize(const MessageLite& msg,
+                           const SerializationTable* table,
+                           io::CodedOutputStream* output) {
+  const FieldMetadata* field_table = table->field_table;
+  int num_fields = table->num_fields - 1;
+  const uint8* base = reinterpret_cast<const uint8*>(&msg);
+  // TODO(gerbens) This skips the first test if we could use the fast
+  // array serialization path, we should make this
+  // int cached_size =
+  //    *reinterpret_cast<const int32*>(base + field_table->offset);
+  // SerializeWithCachedSize(msg, field_table + 1, num_fields, cached_size, ...)
+  // But we keep conformance with the old way for now.
+  SerializeInternal(base, field_table + 1, num_fields, output);
+}
+
+uint8* SerializeInternalToArray(const uint8* base, const FieldMetadata* table,
+                                int32 num_fields, bool is_deterministic,
+                                uint8* buffer);
+
+inline uint8* TableSerializeToArray(const MessageLite& msg,
+                                    const SerializationTable* table,
+                                    bool is_deterministic, uint8* buffer) {
+  const uint8* base = reinterpret_cast<const uint8*>(&msg);
+  const FieldMetadata* field_table = table->field_table + 1;
+  int num_fields = table->num_fields - 1;
+  return SerializeInternalToArray(base, field_table, num_fields,
+                                  is_deterministic, buffer);
+}
+
+template <typename T>
+struct CompareHelper {
+  bool operator()(const T& a, const T& b) { return a < b; }
+};
+
+template <>
+struct CompareHelper<ArenaStringPtr> {
+  bool operator()(const ArenaStringPtr& a, const ArenaStringPtr& b) {
+    return a.Get() < b.Get();
+  }
+};
+
+struct CompareMapKey {
+  template <typename T>
+  bool operator()(const MapEntryHelper<T>& a, const MapEntryHelper<T>& b) {
+    return Compare(a.key_, b.key_);
+  }
+  template <typename T>
+  bool Compare(const T& a, const T& b) {
+    return CompareHelper<T>()(a, b);
+  }
+};
+
+template <typename MapFieldType, const SerializationTable* table>
+void MapFieldSerializer(const uint8* base, uint32 offset, uint32 tag,
+                        uint32 has_offset, io::CodedOutputStream* output) {
+  typedef MapEntryHelper<typename MapFieldType::EntryTypeTrait> Entry;
+  typedef typename MapFieldType::MapType::const_iterator Iter;
+
+  const MapFieldType& map_field =
+      *reinterpret_cast<const MapFieldType*>(base + offset);
+  const SerializationTable* t =
+      table +
+      has_offset;  // has_offset is overloaded for maps to mean table offset
+  if (!output->IsSerializationDeterministic()) {
+    for (Iter it = map_field.GetMap().begin(); it != map_field.GetMap().end();
+         ++it) {
+      Entry map_entry(*it);
+      output->WriteVarint32(tag);
+      output->WriteVarint32(map_entry._cached_size_);
+      SerializeInternal(reinterpret_cast<const uint8*>(&map_entry),
+                        t->field_table, t->num_fields, output);
+    }
+  } else {
+    std::vector<Entry> v;
+    for (Iter it = map_field.GetMap().begin(); it != map_field.GetMap().end();
+         ++it) {
+      v.push_back(Entry(*it));
+    }
+    std::sort(v.begin(), v.end(), CompareMapKey());
+    for (int i = 0; i < v.size(); i++) {
+      output->WriteVarint32(tag);
+      output->WriteVarint32(v[i]._cached_size_);
+      SerializeInternal(reinterpret_cast<const uint8*>(&v[i]), t->field_table,
+                        t->num_fields, output);
+    }
+  }
+}
+
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
 
+#include <google/protobuf/port_undef.inc>
+
 #endif  // GOOGLE_PROTOBUF_GENERATED_MESSAGE_TABLE_DRIVEN_H__
diff --git a/src/google/protobuf/generated_message_util.cc b/src/google/protobuf/generated_message_util.cc
index 32afb7d..028c8cc 100644
--- a/src/google/protobuf/generated_message_util.cc
+++ b/src/google/protobuf/generated_message_util.cc
@@ -44,6 +44,7 @@
 #include <google/protobuf/io/coded_stream.h>
 #include <google/protobuf/arenastring.h>
 #include <google/protobuf/extension_set.h>
+#include <google/protobuf/generated_message_table_driven.h>
 #include <google/protobuf/message_lite.h>
 #include <google/protobuf/metadata_lite.h>
 #include <google/protobuf/stubs/mutex.h>
@@ -293,8 +294,15 @@
 }
 
 void SerializeMessageNoTable(const MessageLite* msg, ArrayOutput* output) {
-  output->ptr = msg->InternalSerializeWithCachedSizesToArray(
-      output->is_deterministic, output->ptr);
+  if (output->is_deterministic) {
+    io::ArrayOutputStream array_stream(output->ptr, INT_MAX);
+    io::CodedOutputStream o(&array_stream);
+    o.SetSerializationDeterministic(true);
+    msg->SerializeWithCachedSizes(&o);
+    output->ptr += o.ByteCount();
+  } else {
+    output->ptr = msg->InternalSerializeWithCachedSizesToArray(output->ptr);
+  }
 }
 
 // Helper to branch to fast path if possible
@@ -303,14 +311,15 @@
                               int32 cached_size,
                               io::CodedOutputStream* output) {
   const uint8* base = reinterpret_cast<const uint8*>(&msg);
-  // Try the fast path
-  uint8* ptr = output->GetDirectBufferForNBytesAndAdvance(cached_size);
-  if (ptr) {
-    // We use virtual dispatch to enable dedicated generated code for the
-    // fast path.
-    msg.InternalSerializeWithCachedSizesToArray(
-        output->IsSerializationDeterministic(), ptr);
-    return;
+  if (!output->IsSerializationDeterministic()) {
+    // Try the fast path
+    uint8* ptr = output->GetDirectBufferForNBytesAndAdvance(cached_size);
+    if (ptr) {
+      // We use virtual dispatch to enable dedicated generated code for the
+      // fast path.
+      msg.InternalSerializeWithCachedSizesToArray(ptr);
+      return;
+    }
   }
   SerializeInternal(base, field_table, num_fields, output);
 }
@@ -647,7 +656,7 @@
 
       // Special cases
       case FieldMetadata::kSpecial:
-	    func = reinterpret_cast<SpecialSerializer>(
+        func = reinterpret_cast<SpecialSerializer>(
             const_cast<void*>(field_metadata.ptr));
         func (base, field_metadata.offset, field_metadata.tag,
             field_metadata.has_offset, output);
@@ -694,9 +703,9 @@
         io::ArrayOutputStream array_stream(array_output.ptr, INT_MAX);
         io::CodedOutputStream output(&array_stream);
         output.SetSerializationDeterministic(is_deterministic);
-		func =  reinterpret_cast<SpecialSerializer>(
+                func =  reinterpret_cast<SpecialSerializer>(
             const_cast<void*>(field_metadata.ptr));
-		func (base, field_metadata.offset, field_metadata.tag,
+                func (base, field_metadata.offset, field_metadata.tag,
             field_metadata.has_offset, &output);
         array_output.ptr += output.ByteCount();
       } break;
diff --git a/src/google/protobuf/generated_message_util.h b/src/google/protobuf/generated_message_util.h
index ca6cc9c..2e29fd3 100644
--- a/src/google/protobuf/generated_message_util.h
+++ b/src/google/protobuf/generated_message_util.h
@@ -49,7 +49,6 @@
 #include <google/protobuf/parse_context.h>
 #include <google/protobuf/has_bits.h>
 #include <google/protobuf/implicit_weak_message.h>
-#include <google/protobuf/map_entry_lite.h>
 #include <google/protobuf/message_lite.h>
 #include <google/protobuf/stubs/once.h>  // Add direct dep on port for pb.cc
 #include <google/protobuf/port.h>
@@ -108,40 +107,6 @@
   return true;
 }
 
-struct PROTOBUF_EXPORT FieldMetadata {
-  uint32 offset;  // offset of this field in the struct
-  uint32 tag;     // field * 8 + wire_type
-  // byte offset * 8 + bit_offset;
-  // if the high bit is set then this is the byte offset of the oneof_case
-  // for this field.
-  uint32 has_offset;
-  uint32 type;      // the type of this field.
-  const void* ptr;  // auxiliary data
-
-  // From the serializer point of view each fundamental type can occur in
-  // 4 different ways. For simplicity we treat all combinations as a cartesion
-  // product although not all combinations are allowed.
-  enum FieldTypeClass {
-    kPresence,
-    kNoPresence,
-    kRepeated,
-    kPacked,
-    kOneOf,
-    kNumTypeClasses  // must be last enum
-  };
-  // C++ protobuf has 20 fundamental types, were we added Cord and StringPiece
-  // and also distinquish the same types if they have different wire format.
-  enum {
-    kCordType = 19,
-    kStringPieceType = 20,
-    kInlinedType = 21,
-    kNumTypes = 21,
-    kSpecial = kNumTypes * kNumTypeClasses,
-  };
-
-  static int CalculateType(int fundamental_type, FieldTypeClass type_class);
-};
-
 inline bool IsPresent(const void* base, uint32 hasbit) {
   const uint32* has_bits_array = static_cast<const uint32*>(base);
   return (has_bits_array[hasbit / 32] & (1u << (hasbit & 31))) != 0;
@@ -165,104 +130,6 @@
                                                 uint32 has_offset,
                                                 io::CodedOutputStream* output);
 
-struct SerializationTable {
-  int num_fields;
-  const FieldMetadata* field_table;
-};
-
-PROTOBUF_EXPORT void SerializeInternal(const uint8* base,
-                                       const FieldMetadata* table,
-                                       int32 num_fields,
-                                       io::CodedOutputStream* output);
-
-inline void TableSerialize(const MessageLite& msg,
-                           const SerializationTable* table,
-                           io::CodedOutputStream* output) {
-  const FieldMetadata* field_table = table->field_table;
-  int num_fields = table->num_fields - 1;
-  const uint8* base = reinterpret_cast<const uint8*>(&msg);
-  // TODO(gerbens) This skips the first test if we could use the fast
-  // array serialization path, we should make this
-  // int cached_size =
-  //    *reinterpret_cast<const int32*>(base + field_table->offset);
-  // SerializeWithCachedSize(msg, field_table + 1, num_fields, cached_size, ...)
-  // But we keep conformance with the old way for now.
-  SerializeInternal(base, field_table + 1, num_fields, output);
-}
-
-uint8* SerializeInternalToArray(const uint8* base, const FieldMetadata* table,
-                                int32 num_fields, bool is_deterministic,
-                                uint8* buffer);
-
-inline uint8* TableSerializeToArray(const MessageLite& msg,
-                                    const SerializationTable* table,
-                                    bool is_deterministic, uint8* buffer) {
-  const uint8* base = reinterpret_cast<const uint8*>(&msg);
-  const FieldMetadata* field_table = table->field_table + 1;
-  int num_fields = table->num_fields - 1;
-  return SerializeInternalToArray(base, field_table, num_fields,
-                                  is_deterministic, buffer);
-}
-
-template <typename T>
-struct CompareHelper {
-  bool operator()(const T& a, const T& b) { return a < b; }
-};
-
-template <>
-struct CompareHelper<ArenaStringPtr> {
-  bool operator()(const ArenaStringPtr& a, const ArenaStringPtr& b) {
-    return a.Get() < b.Get();
-  }
-};
-
-struct CompareMapKey {
-  template <typename T>
-  bool operator()(const MapEntryHelper<T>& a, const MapEntryHelper<T>& b) {
-    return Compare(a.key_, b.key_);
-  }
-  template <typename T>
-  bool Compare(const T& a, const T& b) {
-    return CompareHelper<T>()(a, b);
-  }
-};
-
-template <typename MapFieldType, const SerializationTable* table>
-void MapFieldSerializer(const uint8* base, uint32 offset, uint32 tag,
-                        uint32 has_offset, io::CodedOutputStream* output) {
-  typedef MapEntryHelper<typename MapFieldType::EntryTypeTrait> Entry;
-  typedef typename MapFieldType::MapType::const_iterator Iter;
-
-  const MapFieldType& map_field =
-      *reinterpret_cast<const MapFieldType*>(base + offset);
-  const SerializationTable* t =
-      table +
-      has_offset;  // has_offset is overloaded for maps to mean table offset
-  if (!output->IsSerializationDeterministic()) {
-    for (Iter it = map_field.GetMap().begin(); it != map_field.GetMap().end();
-         ++it) {
-      Entry map_entry(*it);
-      output->WriteVarint32(tag);
-      output->WriteVarint32(map_entry._cached_size_);
-      SerializeInternal(reinterpret_cast<const uint8*>(&map_entry),
-                        t->field_table, t->num_fields, output);
-    }
-  } else {
-    std::vector<Entry> v;
-    for (Iter it = map_field.GetMap().begin(); it != map_field.GetMap().end();
-         ++it) {
-      v.push_back(Entry(*it));
-    }
-    std::sort(v.begin(), v.end(), CompareMapKey());
-    for (int i = 0; i < v.size(); i++) {
-      output->WriteVarint32(tag);
-      output->WriteVarint32(v[i]._cached_size_);
-      SerializeInternal(reinterpret_cast<const uint8*>(&v[i]), t->field_table,
-                        t->num_fields, output);
-    }
-  }
-}
-
 PROTOBUF_EXPORT MessageLite* DuplicateIfNonNullInternal(MessageLite* message);
 PROTOBUF_EXPORT MessageLite* GetOwnedMessageInternal(Arena* message_arena,
                                                      MessageLite* submessage,
diff --git a/src/google/protobuf/implicit_weak_message.cc b/src/google/protobuf/implicit_weak_message.cc
index b26f441..5cc718f 100644
--- a/src/google/protobuf/implicit_weak_message.cc
+++ b/src/google/protobuf/implicit_weak_message.cc
@@ -34,7 +34,6 @@
 #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
 #include <google/protobuf/stubs/once.h>
 #include <google/protobuf/wire_format_lite.h>
-#include <google/protobuf/wire_format_lite_inl.h>
 
 #include <google/protobuf/port_def.inc>
 
diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h
index a66ace5..9bafafb 100644
--- a/src/google/protobuf/io/coded_stream.h
+++ b/src/google/protobuf/io/coded_stream.h
@@ -139,10 +139,6 @@
 
 #include <google/protobuf/port_def.inc>
 
-#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
-#include "util/coding/varint.h"
-#endif
-
 namespace google {
 namespace protobuf {
 
@@ -168,6 +164,35 @@
   return res;
 }
 
+// TODO(gerbens) Experiment with best implementation.
+// Clang unrolls loop and generating pretty good code on O2, gcc doesn't.
+// Unclear if we want 64 bit parse loop unrolled, inlined or opaque function
+// call. Hence experimentation is needed.
+// Important guarantee is that it doesn't read more than size bytes from p.
+template <int size, typename T>
+const char* VarintParse(const char* p, T* out) {
+  T res = 0;
+  T extra = 0;
+  for (int i = 0; i < size; i++) {
+    T byte = static_cast<uint8>(p[i]);
+    res += byte << (i * 7);
+    int j = i + 1;
+    if (PROTOBUF_PREDICT_TRUE(byte < 128)) {
+        *out = res - extra;
+        return p + j;
+    }
+    extra += 128ull << (i * 7);
+  }
+  return nullptr;
+}
+
+inline const char* Parse32(const char* p, uint32* out) {
+  return VarintParse<5>(p, out);
+}
+inline const char* Parse64(const char* p, uint64* out) {
+  return VarintParse<10>(p, out);
+}
+
 // Class which reads and decodes binary data which is composed of varint-
 // encoded integers and fixed-width pieces.  Wraps a ZeroCopyInputStream.
 // Most users will not need to deal with CodedInputStream.
@@ -175,6 +200,8 @@
 // Most methods of CodedInputStream that return a bool return false if an
 // underlying I/O error occurs or if the data is malformed.  Once such a
 // failure occurs, the CodedInputStream is broken and is no longer useful.
+// After a failure, callers also should assume writes to "out" args may have
+// occurred, though nothing useful can be determined from those writes.
 class PROTOBUF_EXPORT CodedInputStream {
  public:
   // Create a CodedInputStream that reads from the given ZeroCopyInputStream.
@@ -418,6 +445,7 @@
   void SetRecursionLimit(int limit);
   int RecursionBudget() { return recursion_budget_; }
 
+  static int GetDefaultRecursionLimit() { return default_recursion_limit_; }
 
   // Increments the current recursion depth.  Returns true if the depth is
   // under the limit, false if it has gone over.
diff --git a/src/google/protobuf/map_entry_lite.h b/src/google/protobuf/map_entry_lite.h
index 08a02ac..2b36b0b 100644
--- a/src/google/protobuf/map_entry_lite.h
+++ b/src/google/protobuf/map_entry_lite.h
@@ -249,11 +249,9 @@
   }
 
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* output) const override {
-    output = KeyTypeHandler::InternalWriteToArray(kKeyFieldNumber, key(),
-                                                  deterministic, output);
-    output = ValueTypeHandler::InternalWriteToArray(kValueFieldNumber, value(),
-                                                    deterministic, output);
+      ::google::protobuf::uint8* output) const override {
+    output = KeyTypeHandler::WriteToArray(kKeyFieldNumber, key(), output);
+    output = ValueTypeHandler::WriteToArray(kValueFieldNumber, value(), output);
     return output;
   }
 
diff --git a/src/google/protobuf/map_field.h b/src/google/protobuf/map_field.h
index bba5d8a..5e598b8 100644
--- a/src/google/protobuf/map_field.h
+++ b/src/google/protobuf/map_field.h
@@ -742,7 +742,7 @@
  public:
   MapIterator(Message* message, const FieldDescriptor* field) {
     const Reflection* reflection = message->GetReflection();
-    map_ = reflection->MapData(message, field);
+    map_ = reflection->MutableMapData(message, field);
     key_.SetType(field->message_type()->FindFieldByName("key")->cpp_type());
     value_.SetType(field->message_type()->FindFieldByName("value")->cpp_type());
     map_->InitializeIterator(this);
diff --git a/src/google/protobuf/map_test.cc b/src/google/protobuf/map_test.cc
index 41d9c37..06ebf5d 100644
--- a/src/google/protobuf/map_test.cc
+++ b/src/google/protobuf/map_test.cc
@@ -2042,19 +2042,30 @@
       unittest::TestMap::descriptor());
   reflection_tester.SetMapFieldsViaMapReflection(message1.get());
 
+  // message2 is created by same factory.
   std::unique_ptr<Message> message2;
   message2.reset(
       factory.GetPrototype(unittest::TestMap::descriptor())->New());
   reflection_tester.SetMapFieldsViaMapReflection(message2.get());
 
+  // message3 is created by different factory.
+  DynamicMessageFactory factory3;
+  std::unique_ptr<Message> message3;
+  message3.reset(
+      factory3.GetPrototype(unittest::TestMap::descriptor())->New());
+  reflection_tester.SetMapFieldsViaMapReflection(message3.get());
+
   message2->MergeFrom(*message1);
+  message3->MergeFrom(*message1);
 
   // Test MergeFrom does not sync to repeated fields and
   // there is no duplicate keys in text format.
-  string output1, output2;
+  string output1, output2, output3;
   TextFormat::PrintToString(*message1, &output1);
   TextFormat::PrintToString(*message2, &output2);
+  TextFormat::PrintToString(*message3, &output3);
   EXPECT_EQ(output1, output2);
+  EXPECT_EQ(output1, output3);
 }
 
 TEST(GeneratedMapFieldTest, DynamicMessageCopyFrom) {
diff --git a/src/google/protobuf/map_type_handler.h b/src/google/protobuf/map_type_handler.h
index 2db3dc6..a8220b6 100644
--- a/src/google/protobuf/map_type_handler.h
+++ b/src/google/protobuf/map_type_handler.h
@@ -167,9 +167,6 @@
                           MapEntryAccessorType* value);
   static inline void Write(int field, const MapEntryAccessorType& value,
                            io::CodedOutputStream* output);
-  static inline uint8* InternalWriteToArray(int field,
-                                            const MapEntryAccessorType& value,
-                                            bool deterministic, uint8* target);
   static inline uint8* WriteToArray(int field,
                                     const MapEntryAccessorType& value,
                                     uint8* target);
@@ -226,14 +223,9 @@
                             MapEntryAccessorType* value);                     \
     static inline void Write(int field, const MapEntryAccessorType& value,    \
                              io::CodedOutputStream* output);                  \
-    static inline uint8* InternalWriteToArray(                                \
-        int field, const MapEntryAccessorType& value, bool deterministic,     \
-        uint8* target);                                                       \
     static inline uint8* WriteToArray(int field,                              \
                                       const MapEntryAccessorType& value,      \
-                                      uint8* target) {                        \
-      return InternalWriteToArray(field, value, false, target);               \
-    }                                                                         \
+                                      uint8* target);                         \
     static inline const MapEntryAccessorType& GetExternalReference(           \
         const TypeOnMemory& value);                                           \
     static inline void DeleteNoArena(const TypeOnMemory& x);                  \
@@ -374,12 +366,9 @@
 }
 
 template <typename Type>
-inline uint8*
-MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::InternalWriteToArray(
-    int field, const MapEntryAccessorType& value, bool deterministic,
-    uint8* target) {
-  return WireFormatLite::InternalWriteMessageToArray(field, value,
-                                                     deterministic, target);
+inline uint8* MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::WriteToArray(
+    int field, const MapEntryAccessorType& value, uint8* target) {
+  return WireFormatLite::InternalWriteMessageToArray(field, value, target);
 }
 
 #define WRITE_METHOD(FieldType, DeclaredType)                                  \
@@ -391,9 +380,8 @@
   }                                                                            \
   template <typename Type>                                                     \
   inline uint8*                                                                \
-  MapTypeHandler<WireFormatLite::TYPE_##FieldType,                             \
-                 Type>::InternalWriteToArray(                                  \
-      int field, const MapEntryAccessorType& value, bool, uint8* target) {     \
+  MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::WriteToArray(        \
+      int field, const MapEntryAccessorType& value, uint8* target) {           \
     return WireFormatLite::Write##DeclaredType##ToArray(field, value, target); \
   }
 
diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc
index fc307f0..3772594 100644
--- a/src/google/protobuf/message.cc
+++ b/src/google/protobuf/message.cc
@@ -290,7 +290,6 @@
       if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) {
         return {internal::PackedEnumParser, object};
       } else {
-        GOOGLE_CHECK_EQ(field->file()->options().cc_api_version(), 2);
         ctx->extra_parse_data().SetEnumValidatorArg(
             ReflectiveValidator, field->enum_type(),
             reflection->MutableUnknownFields(msg), field->number());
@@ -307,6 +306,7 @@
 
     default:
       GOOGLE_LOG(FATAL) << "Type is not packable " << field->type();
+      return {};  // Make compiler happy
   }
 }
 
@@ -315,19 +315,13 @@
                          internal::ParseContext* ctx) {
   if (WireFormat::WireTypeForFieldType(field->type()) !=
       WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
-    ABSL_ASSERT(field->is_packable());
+    GOOGLE_DCHECK(field->is_packable());
     return GetPackedField(field, msg, reflection, ctx);
   }
   enum { kNone = 0, kVerify, kStrict } utf8_level = kNone;
   internal::ParseFunc string_parsers[] = {internal::StringParser,
                                           internal::StringParserUTF8Verify,
                                           internal::StringParserUTF8};
-  internal::ParseFunc cord_parsers[] = {internal::CordParser,
-                                        internal::CordParserUTF8Verify,
-                                        internal::CordParserUTF8};
-  internal::ParseFunc string_piece_parsers[] = {
-      internal::StringPieceParser, internal::StringPieceParserUTF8Verify,
-      internal::StringPieceParserUTF8};
   switch (field->type()) {
     case FieldDescriptor::TYPE_STRING:
       if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3
@@ -339,7 +333,7 @@
         ctx->extra_parse_data().SetFieldName(field->full_name().c_str());
         utf8_level = kVerify;
       }
-      FALLTHROUGH_INTENDED;
+      PROTOBUF_FALLTHROUGH_INTENDED;
     case FieldDescriptor::TYPE_BYTES: {
       if (field->is_repeated()) {
         int index = reflection->FieldSize(*msg, field);
@@ -350,17 +344,10 @@
           auto object = reflection->MutableRepeatedPtrField<string>(msg, field)
                             ->Mutable(index);
           return {string_parsers[utf8_level], object};
-        } else if (field->options().ctype() == FieldOptions::CORD) {
-          auto object = reflection->MutableRepeatedField<Cord>(msg, field)
+        } else {
+          auto object = reflection->MutableRepeatedPtrField<string>(msg, field)
                             ->Mutable(index);
-          return {cord_parsers[utf8_level], object};
-        } else if (field->options().ctype() == FieldOptions::STRING_PIECE) {
-          auto object =
-              reflection
-                  ->MutableRepeatedPtrField<internal::StringPieceField>(msg,
-                                                                        field)
-                  ->Mutable(index);
-          return {string_piece_parsers[utf8_level], object};
+          return {string_parsers[utf8_level], object};
         }
       } else {
         // Clear value and make sure it's set.
@@ -372,16 +359,10 @@
               reflection->GetStringReference(*msg, field, nullptr));
           return {string_parsers[utf8_level], object};
         } else {
-          void* object =
-              internal::ReflectionAccessor::GetOffset(msg, field, reflection);
-          if (field->containing_oneof()) {
-            object = *static_cast<Cord**>(object);
-          }
-          if (field->options().ctype() == FieldOptions::CORD) {
-            return {cord_parsers[utf8_level], object};
-          } else if (field->options().ctype() == FieldOptions::STRING_PIECE) {
-            return {string_piece_parsers[utf8_level], object};
-          }
+          // HACK around inability to get mutable_string in reflection
+          string* object = &const_cast<string&>(
+              reflection->GetStringReference(*msg, field, nullptr));
+          return {string_parsers[utf8_level], object};
         }
       }
       GOOGLE_LOG(FATAL) << "No other type than string supported";
@@ -399,6 +380,7 @@
     default:
       GOOGLE_LOG(FATAL) << "Wrong type for length delim " << field->type();
   }
+  return {};  // Make compiler happy.
 }
 
 ParseClosure GetGroup(int field_number, const FieldDescriptor* field,
@@ -507,8 +489,8 @@
           reflection_(msg->GetReflection()),
           ctx_(ctx),
           is_item_(is_item) {
-      GOOGLE_CHECK(descriptor_) << typeid(*this).name();
-      GOOGLE_CHECK(reflection_) << descriptor_->name() << " " << typeid(*this).name();
+      GOOGLE_CHECK(descriptor_) << msg->GetTypeName();
+      GOOGLE_CHECK(reflection_) << msg->GetTypeName();
     }
 
     const FieldDescriptor* Field(int num, int wire_type) {
diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h
index 0734df5..02cca53 100644
--- a/src/google/protobuf/message.h
+++ b/src/google/protobuf/message.h
@@ -1049,11 +1049,16 @@
 
   // Help method for MapIterator.
   friend class MapIterator;
-  virtual internal::MapFieldBase* MapData(
+  virtual internal::MapFieldBase* MutableMapData(
       Message* /* message */, const FieldDescriptor* /* field */) const {
     return NULL;
   }
 
+  virtual const internal::MapFieldBase* GetMapData(
+      const Message& /* message */, const FieldDescriptor* /* field */) const {
+    return NULL;
+  }
+
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Reflection);
 };
 
diff --git a/src/google/protobuf/message_lite.cc b/src/google/protobuf/message_lite.cc
index 8edae78..fb1da49 100644
--- a/src/google/protobuf/message_lite.cc
+++ b/src/google/protobuf/message_lite.cc
@@ -45,6 +45,7 @@
 #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
 #include <google/protobuf/arena.h>
 #include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/generated_message_table_driven.h>
 #include <google/protobuf/message_lite.h>
 #include <google/protobuf/repeated_field.h>
 #include <google/protobuf/stubs/strutil.h>
@@ -287,8 +288,9 @@
     }
     range = next();
   }
+  if (!parser.Done()) return false;
   input->SetConsumed();
-  return parser.Done();
+  return true;
 }
 #endif
 
@@ -355,8 +357,27 @@
 // ===================================================================
 
 uint8* MessageLite::SerializeWithCachedSizesToArray(uint8* target) const {
-  return InternalSerializeWithCachedSizesToArray(
-      io::CodedOutputStream::IsDefaultSerializationDeterministic(), target);
+  const internal::SerializationTable* table =
+      static_cast<const internal::SerializationTable*>(InternalGetTable());
+  auto deterministic =
+      io::CodedOutputStream::IsDefaultSerializationDeterministic();
+  if (table) {
+    return internal::TableSerializeToArray(*this, table, deterministic, target);
+  } else {
+    if (deterministic) {
+      // We only optimize this when using optimize_for = SPEED.  In other cases
+      // we just use the CodedOutputStream path.
+      int size = GetCachedSize();
+      io::ArrayOutputStream out(target, size);
+      io::CodedOutputStream coded_out(&out);
+      coded_out.SetSerializationDeterministic(true);
+      SerializeWithCachedSizes(&coded_out);
+      GOOGLE_CHECK(!coded_out.HadError());
+      return target + size;
+    } else {
+      return InternalSerializeWithCachedSizesToArray(target);
+    }
+  }
 }
 
 bool MessageLite::SerializeToCodedStream(io::CodedOutputStream* output) const {
@@ -373,29 +394,29 @@
     return false;
   }
 
-  uint8* buffer = output->GetDirectBufferForNBytesAndAdvance(size);
-  if (buffer != NULL) {
-    uint8* end = InternalSerializeWithCachedSizesToArray(
-        output->IsSerializationDeterministic(), buffer);
-    if (end - buffer != size) {
-      ByteSizeConsistencyError(size, ByteSizeLong(), end - buffer, *this);
+  if (!output->IsSerializationDeterministic()) {
+    uint8* buffer = output->GetDirectBufferForNBytesAndAdvance(size);
+    if (buffer != nullptr) {
+      uint8* end = InternalSerializeWithCachedSizesToArray(buffer);
+      if (end - buffer != size) {
+        ByteSizeConsistencyError(size, ByteSizeLong(), end - buffer, *this);
+      }
+      return true;
     }
-    return true;
-  } else {
-    int original_byte_count = output->ByteCount();
-    SerializeWithCachedSizes(output);
-    if (output->HadError()) {
-      return false;
-    }
-    int final_byte_count = output->ByteCount();
-
-    if (final_byte_count - original_byte_count != size) {
-      ByteSizeConsistencyError(size, ByteSizeLong(),
-                               final_byte_count - original_byte_count, *this);
-    }
-
-    return true;
   }
+  int original_byte_count = output->ByteCount();
+  SerializeWithCachedSizes(output);
+  if (output->HadError()) {
+    return false;
+  }
+  int final_byte_count = output->ByteCount();
+
+  if (final_byte_count - original_byte_count != size) {
+    ByteSizeConsistencyError(size, ByteSizeLong(),
+                             final_byte_count - original_byte_count, *this);
+  }
+
+  return true;
 }
 
 bool MessageLite::SerializeToZeroCopyStream(
@@ -496,7 +517,7 @@
 // generated code for maximum speed. If the proto is optimized for size or
 // is lite, then we need to specialize this to avoid infinite recursion.
 uint8* MessageLite::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, uint8* target) const {
+    uint8* target) const {
   const internal::SerializationTable* table =
       static_cast<const internal::SerializationTable*>(InternalGetTable());
   if (table == NULL) {
@@ -505,12 +526,11 @@
     int size = GetCachedSize();
     io::ArrayOutputStream out(target, size);
     io::CodedOutputStream coded_out(&out);
-    coded_out.SetSerializationDeterministic(deterministic);
     SerializeWithCachedSizes(&coded_out);
     GOOGLE_CHECK(!coded_out.HadError());
     return target + size;
   } else {
-    return internal::TableSerializeToArray(*this, table, deterministic, target);
+    return internal::TableSerializeToArray(*this, table, false, target);
   }
 }
 
diff --git a/src/google/protobuf/message_lite.h b/src/google/protobuf/message_lite.h
index 39c9e8f..1e07141 100644
--- a/src/google/protobuf/message_lite.h
+++ b/src/google/protobuf/message_lite.h
@@ -400,12 +400,9 @@
   // method.)
   virtual int GetCachedSize() const = 0;
 
-  virtual uint8* InternalSerializeWithCachedSizesToArray(bool deterministic,
-                                                         uint8* target) const;
-
 #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
   virtual internal::ParseFunc _ParseFunc() const {
-    GOOGLE_LOG(FATAL) << "Type " << typeid(*this).name()
+    GOOGLE_LOG(FATAL) << "Type " << GetTypeName()
                << " doesn't implement _InternalParse";
     return nullptr;
   }
@@ -451,6 +448,11 @@
   // TODO(gerbens) make this a pure abstract function
   virtual const void* InternalGetTable() const { return NULL; }
 
+  // Fast path when conditions match (ie. non-deterministic)
+ public:
+  virtual uint8* InternalSerializeWithCachedSizesToArray(uint8* target) const;
+
+ private:
   friend class internal::WireFormatLite;
   friend class Message;
   friend class internal::WeakFieldMap;
diff --git a/src/google/protobuf/parse_context.cc b/src/google/protobuf/parse_context.cc
index 3902637..a522966 100644
--- a/src/google/protobuf/parse_context.cc
+++ b/src/google/protobuf/parse_context.cc
@@ -30,18 +30,12 @@
 
 #include <google/protobuf/parse_context.h>
 
-#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
-
 #include <google/protobuf/stubs/stringprintf.h>
 #include <google/protobuf/io/coded_stream.h>
 #include <google/protobuf/message_lite.h>
 #include <google/protobuf/repeated_field.h>
-#include <google/protobuf/string_piece_field_support.h>
 #include <google/protobuf/wire_format_lite.h>
-#include "third_party/absl/strings/str_format.h"
 #include <google/protobuf/stubs/strutil.h>
-#include "util/coding/varint.h"
-#include "util/utf8/public/unilib.h"
 
 #include <google/protobuf/port_def.inc>
 
@@ -50,8 +44,8 @@
 namespace internal {
 
 bool ParseContext::ParseEndsInSlopRegion(const char* begin, int overrun) const {
-  ABSL_ASSERT(overrun >= 0);
-  ABSL_ASSERT(overrun <= kSlopBytes);
+  GOOGLE_DCHECK(overrun >= 0);
+  GOOGLE_DCHECK(overrun <= kSlopBytes);
   auto ptr = begin + overrun;
   auto end = begin + kSlopBytes;
   int n = end - ptr;
@@ -60,7 +54,7 @@
   // bytes (or more if on the stack there are further limits)
   int d = depth_;
   if (limit_ != -1) {
-    ABSL_ASSERT(d < start_depth_);  // Top-level never has a limit.
+    GOOGLE_DCHECK(d < start_depth_);  // Top-level never has a limit.
     // rewind the stack until all limits disappear.
     int limit = limit_;
     if (limit >= n) return false;
@@ -93,7 +87,7 @@
   // any way so we make no attempt to leave the stream at a well specified pos.
   while (ptr < end) {
     uint32 tag;
-    ptr = Varint::Parse32(ptr, &tag);
+    ptr = io::Parse32(ptr, &tag);
     if (ptr == nullptr || ptr > end) return false;
     // ending on 0 tag is allowed and is the major reason for the necessity of
     // this function.
@@ -101,7 +95,7 @@
     switch (tag & 7) {
       case 0: {  // Varint
         uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = io::Parse64(ptr, &val);
         if (ptr == nullptr) return false;
         break;
       }
@@ -111,7 +105,7 @@
       }
       case 2: {  // len delim
         uint32 size;
-        ptr = Varint::Parse32(ptr, &size);
+        ptr = io::Parse32(ptr, &size);
         if (ptr == nullptr) return false;
         ptr += size;
         break;
@@ -145,12 +139,12 @@
                                                        const char* end) {
   auto ptr = begin;
   do {
-    ABSL_ASSERT(ptr < end);
+    GOOGLE_DCHECK(ptr < end);
     const char* limited_end;
     if (limit_ == -1) {
       limited_end = end;
     } else {
-      ABSL_ASSERT(limit_ > 0);
+      GOOGLE_DCHECK(limit_ > 0);
       limited_end = ptr + std::min(static_cast<int32>(end - ptr), limit_);
       limit_ -= limited_end - ptr;
     }
@@ -159,7 +153,7 @@
     // an end-group. If this is the case we continue parsing the range with
     // the parent parser.
     do {
-      ABSL_ASSERT(ptr < limited_end);
+      GOOGLE_DCHECK(ptr < limited_end);
       ptr = parser_(ptr, limited_end, this);
       if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) {
         // Clear last_tag_minus_1_ so that the hard error encountered is not
@@ -170,16 +164,16 @@
       if (!EndedOnTag()) {
         // The parser ended still parsing the initial message. This can only
         // happen because it crossed the end.
-        ABSL_ASSERT(ptr >= limited_end);
+        GOOGLE_DCHECK(ptr >= limited_end);
         break;
       }
       // Child parser terminated on an end-group / 0 tag.
-      ABSL_ASSERT(depth_ <= start_depth_);
+      GOOGLE_DCHECK(depth_ <= start_depth_);
       if (depth_ == start_depth_) {
         // The parse was already at the top-level and there is no parent.
         // This can happen due to encountering 0 or due to this parser being
         // called for parsing a sub-group message in custom parsing code.
-        return {false, ptr - end};
+        return {false, static_cast<int>(ptr - end)};
       }
       auto state = Pop();
       // Verify the ending tag is correct and continue parsing the range with
@@ -192,8 +186,8 @@
       parser_ = state.parser;  // Load parent parser
     } while (ptr < limited_end);
     int overrun = ptr - limited_end;
-    ABSL_ASSERT(overrun >= 0);
-    ABSL_ASSERT(overrun <= kSlopBytes);  // wireformat guarantees this limit
+    GOOGLE_DCHECK(overrun >= 0);
+    GOOGLE_DCHECK(overrun <= kSlopBytes);  // wireformat guarantees this limit
     if (limit_ != -1) {
       limit_ -= overrun;  // Adjust limit relative to new position.
       if (limit_ < 0) return {};  // We overrun the limit
@@ -201,7 +195,7 @@
         // We are at an actual ending of a length delimited field.
         // The top level has no limit (ie. limit_ == -1) so we can assert
         // that the stack is non-empty.
-        ABSL_ASSERT(depth_ < start_depth_);
+        GOOGLE_DCHECK(depth_ < start_depth_);
         // else continue parsing the parent message.
         auto state = Pop();
         parser_ = state.parser;
@@ -212,7 +206,7 @@
       }
     }
   } while (ptr < end);
-  return {true, ptr - end};
+  return {true, static_cast<int>(ptr - end)};
 }
 
 const char* StringParser(const char* begin, const char* end, void* object,
@@ -222,41 +216,6 @@
   return end;
 }
 
-const char* CordParser(const char* begin, const char* end, void* object,
-                       ParseContext* ctx) {
-  auto cord = static_cast<Cord*>(object);
-  cord->Append(StringPiece(begin, end - begin));
-  return end;
-}
-
-void StringPieceField::Append(const char *begin, size_t chunk_size, int limit) {
-  if (size_ == 0) {
-    auto tot = chunk_size + limit;
-    if (tot > scratch_size_) {
-      auto old_scratch_size = scratch_size_;
-      scratch_size_ = tot;
-      // TODO(gerbens) Security against big
-      if (arena_ != NULL) {
-        scratch_ = ::google::protobuf::Arena::CreateArray<char>(arena_, scratch_size_);
-      } else {
-        std::allocator<char>().deallocate(scratch_, old_scratch_size);
-        scratch_ = std::allocator<char>().allocate(scratch_size_);
-      }
-    }
-    data_ = scratch_;
-  }
-  std::memcpy(scratch_ + size_, begin, chunk_size);
-  size_ += chunk_size;
-}
-
-const char* StringPieceParser(const char* begin, const char* end, void* object,
-                              ParseContext* ctx) {
-  auto s = static_cast<StringPieceField*>(object);
-  auto limit = ctx->CurrentLimit();
-  s->Append(begin, end - begin, limit);
-  return end;
-}
-
 // Defined in wire_format_lite.cc
 void PrintUTF8ErrorLog(const char* field_name, const char* operation_str,
                        bool emit_stacktrace);
@@ -269,14 +228,6 @@
   return true;
 }
 
-bool VerifyUTF8Cord(const Cord& value, ParseContext* ctx) {
-  if (!UniLib::CordIsStructurallyValid(value)) {
-    PrintUTF8ErrorLog(ctx->extra_parse_data().FieldName(), "parsing", false);
-    return false;
-  }
-  return true;
-}
-
 const char* StringParserUTF8(const char* begin, const char* end, void* object,
                              ParseContext* ctx) {
   StringParser(begin, end, object, ctx);
@@ -287,26 +238,6 @@
   return end;
 }
 
-const char* CordParserUTF8(const char* begin, const char* end, void* object,
-                           ParseContext* ctx) {
-  CordParser(begin, end, object, ctx);
-  if (ctx->AtLimit()) {
-    auto str = static_cast<Cord*>(object);
-    GOOGLE_PROTOBUF_PARSER_ASSERT(VerifyUTF8Cord(*str, ctx));
-  }
-  return end;
-}
-
-const char* StringPieceParserUTF8(const char* begin, const char* end,
-                                  void* object, ParseContext* ctx) {
-  StringPieceParser(begin, end, object, ctx);
-  if (ctx->AtLimit()) {
-    auto s = static_cast<StringPieceField*>(object);
-    GOOGLE_PROTOBUF_PARSER_ASSERT(VerifyUTF8(s->Get(), ctx));
-  }
-  return end;
-}
-
 const char* StringParserUTF8Verify(const char* begin, const char* end,
                                    void* object, ParseContext* ctx) {
   StringParser(begin, end, object, ctx);
@@ -319,35 +250,12 @@
   return end;
 }
 
-const char* CordParserUTF8Verify(const char* begin, const char* end,
-                                 void* object, ParseContext* ctx) {
-  CordParser(begin, end, object, ctx);
-#ifndef NDEBUG
-  if (ctx->AtLimit()) {
-    auto str = static_cast<Cord*>(object);
-    VerifyUTF8Cord(*str, ctx);
-  }
-#endif
-  return end;
-}
-
-const char* StringPieceParserUTF8Verify(const char* begin, const char* end,
-                                        void* object, ParseContext* ctx) {
-  return StringPieceParser(begin, end, object, ctx);
-#ifndef NDEBUG
-  if (ctx->AtLimit()) {
-    auto s = static_cast<StringPieceField*>(object);
-    VerifyUTF8(s->Get(), ctx);
-  }
-#endif
-  return end;
-}
 
 const char* GreedyStringParser(const char* begin, const char* end, void* object,
                          ParseContext* ctx) {
   auto str = static_cast<string*>(object);
   auto limit = ctx->CurrentLimit();
-  ABSL_ASSERT(limit != -1);  // Always length delimited
+  GOOGLE_DCHECK(limit != -1);  // Always length delimited
   end += std::min<int>(limit, ParseContext::kSlopBytes);
   str->append(begin, end - begin);
   return end;
@@ -356,7 +264,7 @@
 const char* GreedyStringParserUTF8(const char* begin, const char* end, void* object,
                              ParseContext* ctx) {
   auto limit = ctx->CurrentLimit();
-  ABSL_ASSERT(limit != -1);  // Always length delimited
+  GOOGLE_DCHECK(limit != -1);  // Always length delimited
   bool at_end;
   if (limit <= ParseContext::kSlopBytes) {
     end += limit;
@@ -376,7 +284,7 @@
 const char* GreedyStringParserUTF8Verify(const char* begin, const char* end, void* object,
                              ParseContext* ctx) {
   auto limit = ctx->CurrentLimit();
-  ABSL_ASSERT(limit != -1);  // Always length delimited
+  GOOGLE_DCHECK(limit != -1);  // Always length delimited
   bool at_end;
   if (limit <= ParseContext::kSlopBytes) {
     end += limit;
@@ -402,7 +310,7 @@
   auto ptr = begin;
   while (ptr < end) {
     uint64 varint;
-    ptr = Varint::Parse64(ptr, &varint);
+    ptr = io::Parse64(ptr, &varint);
     if (!ptr) return nullptr;
     T val;
     if (sign) {
@@ -467,7 +375,7 @@
   auto ptr = begin;
   while (ptr < end) {
     uint64 varint;
-    ptr = Varint::Parse64(ptr, &varint);
+    ptr = io::Parse64(ptr, &varint);
     if (!ptr) return nullptr;
     int val = varint;
     if (ctx->extra_parse_data().ValidateEnum<string>(val))
@@ -482,7 +390,7 @@
   auto ptr = begin;
   while (ptr < end) {
     uint64 varint;
-    ptr = Varint::Parse64(ptr, &varint);
+    ptr = io::Parse64(ptr, &varint);
     if (!ptr) return nullptr;
     int val = varint;
     if (ctx->extra_parse_data().ValidateEnumArg<string>(val))
@@ -623,5 +531,3 @@
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
-
-#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
diff --git a/src/google/protobuf/parse_context.h b/src/google/protobuf/parse_context.h
index c7d37db..4de3908 100644
--- a/src/google/protobuf/parse_context.h
+++ b/src/google/protobuf/parse_context.h
@@ -31,17 +31,13 @@
 #ifndef GOOGLE_PROTOBUF_PARSE_CONTEXT_H__
 #define GOOGLE_PROTOBUF_PARSE_CONTEXT_H__
 
+#include <cstring>
 #include <string>
 
-#include <google/protobuf/port.h>
-
-#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 #include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/port.h>
 #include <google/protobuf/wire_format_lite.h>
-#include <google/protobuf/stubs/common.h>
-#include "third_party/absl/base/optimization.h"
 #include <google/protobuf/stubs/strutil.h>
-#include "util/coding/varint.h"
 
 #include <google/protobuf/port_def.inc>
 
@@ -55,7 +51,8 @@
 namespace internal {
 
 // Template code below needs to know about the existence of these functions.
-void WriteVarint(uint32 num, uint64 val, std::string* s);
+PROTOBUF_EXPORT void WriteVarint(uint32 num, uint64 val, std::string* s);
+PROTOBUF_EXPORT
 void WriteLengthDelimited(uint32 num, StringPiece val, std::string* s);
 // Inline because it is just forwarding to s->WriteVarint
 inline void WriteVarint(uint32 num, uint64 val, UnknownFieldSet* s);
@@ -141,7 +138,7 @@
   //   All tag/value pairs between in [begin, retval) are parsed and retval
   //   points to start of a tag.
   const char* operator()(const char* ptr, const char* end, ParseContext* ctx) {
-    ABSL_ASSERT(ptr < end);
+    GOOGLE_DCHECK(ptr < end);
     return func(ptr, end, object, ctx);
   }
 };
@@ -157,7 +154,7 @@
 // all the parser code that deals with seams is located in what would otherwise
 // be error paths of a parser that wouldn't need to deal with seams.
 
-class ParseContext {
+class PROTOBUF_EXPORT ParseContext {
  public:
   enum {
     // Tag is atmost 5 bytes, varint is atmost 10 resulting in 15 bytes. We
@@ -243,7 +240,7 @@
         inlined_depth_(std::max(0, rec_limit - kInlinedDepth)) {}
 
   ~ParseContext() {
-    if (inlined_depth_ == -1) delete stack_;
+    if (inlined_depth_ == -1) delete[] stack_;
   }
 
   void StartParse(ParseClosure parser) { parser_ = parser; }
@@ -261,9 +258,10 @@
   //   EndedOnTag() to find if the parse failed due to an error or ended on
   //   terminating tag.
   bool ParseRange(StringPiece chunk, int* overrun_ptr) {
-    ABSL_ASSERT(!chunk.empty());
+    GOOGLE_DCHECK(!chunk.empty());
     int& overrun = *overrun_ptr;
-    if (overrun >= chunk.size()) {
+    GOOGLE_DCHECK(overrun >= 0);
+    if (overrun >= static_cast<int>(chunk.size())) {
       // This case can easily happen in patch buffers and we like to inline
       // this case.
       overrun -= chunk.size();
@@ -317,7 +315,7 @@
     if (!EndedOnTag()) {
       // The group hasn't been terminated by an end-group and thus continues,
       // hence it must have ended because it crossed "end".
-      ABSL_ASSERT(ptr >= end);
+      GOOGLE_DCHECK(ptr >= end);
       return {ptr, true};
     }
     // Verify that the terminating tag matches the start group tag. As an extra
@@ -332,7 +330,7 @@
   }
 
   void EndGroup(uint32 tag) {
-    ABSL_ASSERT(tag == 0 || (tag & 7) == 4);
+    GOOGLE_DCHECK(tag == 0 || (tag & 7) == 4);
     // Because of the above assert last_tag_minus_1 is never set to 0, and the
     // caller can verify the child parser was terminated, by comparing to 0.
     last_tag_minus_1_ = tag - 1;
@@ -355,7 +353,7 @@
     // overflow.
     int64 safe_new_limit = size - static_cast<int64>(end - ptr);
     if (safe_new_limit > INT_MAX) return nullptr;
-    ABSL_ASSERT(safe_new_limit > 0);  // only call this if it's crossing end
+    GOOGLE_DCHECK(safe_new_limit > 0);  // only call this if it's crossing end
     int32 new_limit = static_cast<int32>(safe_new_limit);
     int32 delta;
     if (limit_ != -1) {
@@ -373,6 +371,10 @@
   }
 
   // Helper function for a child group that has crossed the boundary.
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+#endif  // defined(__GNUC__) && !defined(__clang__)
   bool StoreGroup(ParseClosure current_parser, ParseClosure child_parser,
                   int depth, uint32 tag) {
     // The group must still read an end-group tag, so it can't be at a limit.
@@ -386,10 +388,13 @@
       // parse context in this case. We need to make the child parser active.
       parser_ = child_parser;
     }
-    if (ABSL_PREDICT_FALSE(depth < inlined_depth_)) SwitchStack();
+    if (PROTOBUF_PREDICT_FALSE(depth < inlined_depth_)) SwitchStack();
     stack_[depth] = {current_parser, static_cast<int32>(~(tag >> 3))};
     return true;
   }
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#endif  // defined(__GNUC__) && !defined(__clang__)
 
  private:
   // This the "active" or current parser.
@@ -428,9 +433,9 @@
   int inlined_depth_;
 
   bool Push(ParseClosure parser, int32 delta) {
-    ABSL_ASSERT(delta >= -1);  // Make sure it's a valid len-delim
+    GOOGLE_DCHECK(delta >= -1);  // Make sure it's a valid len-delim
     if (PROTOBUF_PREDICT_FALSE(--depth_ < 0)) return false;
-    if (ABSL_PREDICT_FALSE(depth_ < inlined_depth_)) SwitchStack();
+    if (PROTOBUF_PREDICT_FALSE(depth_ < inlined_depth_)) SwitchStack();
     stack_[depth_] = {parser, delta};
     return true;
   }
@@ -537,7 +542,7 @@
   // EndedOnTag() on the underlying ParseContext to find out if the parse ended
   // correctly on a terminating tag.
   bool Parse(StringPiece range) {
-    ABSL_ASSERT(!range.empty());
+    GOOGLE_DCHECK(!range.empty());
     auto size = range.size();
     if (size > kSlopBytes) {
       // The buffer is large enough to be able to parse the (size - kSlopBytes)
@@ -563,7 +568,7 @@
       // We care about leaving the stream at the right place and the stream will
       // indeed terminate, so just parse it.
       auto res = ParseRange({buffer_, kSlopBytes}, size);
-      ABSL_ASSERT(!res);
+      GOOGLE_DCHECK(!res);
       return false;
     }
     return true;
@@ -582,7 +587,7 @@
     // The reason of ensure_non_negative_skip and ParseEndsInSlopRegion is that
     // the following assert holds. Which implies the stream doesn't need to
     // backup.
-    ABSL_ASSERT(!ensure_non_negative_skip || overrun_ >= 0);
+    GOOGLE_DCHECK(!ensure_non_negative_skip || overrun_ >= 0);
     return overrun_;
   }
 
@@ -623,7 +628,7 @@
                                          const char* end, ParseContext* ctx) {
   auto ptr = begin;
   uint32 number = tag >> 3;
-  if (ABSL_PREDICT_FALSE(number == 0)) {
+  if (PROTOBUF_PREDICT_FALSE(number == 0)) {
     GOOGLE_PROTOBUF_ASSERT_RETURN(tag == 0, {});
     // Special case scenario of 0 termination.
     ctx->EndGroup(tag);
@@ -633,7 +638,7 @@
   switch (tag & 7) {
     case WireType::WIRETYPE_VARINT: {
       uint64 value;
-      ptr = Varint::Parse64(ptr, &value);
+      ptr = io::Parse64(ptr, &value);
       GOOGLE_PROTOBUF_ASSERT_RETURN(ptr != nullptr, {});
       field_parser.AddVarint(number, value);
       break;
@@ -646,7 +651,7 @@
     }
     case WireType::WIRETYPE_LENGTH_DELIMITED: {
       uint32 size;
-      ptr = Varint::Parse32(ptr, &size);
+      ptr = io::Parse32(ptr, &size);
       GOOGLE_PROTOBUF_ASSERT_RETURN(ptr != nullptr, {});
       ParseClosure child = field_parser.AddLengthDelimited(number, size);
       if (size > end - ptr) {
@@ -685,7 +690,7 @@
     default:
       GOOGLE_PROTOBUF_ASSERT_RETURN(false, {});
   }
-  ABSL_ASSERT(ptr != nullptr);
+  GOOGLE_DCHECK(ptr != nullptr);
   return {ptr, false};
 }
 
@@ -696,7 +701,7 @@
   auto ptr = begin;
   while (ptr < end) {
     uint32 tag;
-    ptr = Varint::Parse32(ptr, &tag);
+    ptr = io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
     auto res = FieldParser(tag, parent, field_parser, ptr, end, ctx);
     ptr = res.first;
@@ -714,45 +719,61 @@
 // caller needs to set prior to the call.
 
 // The null parser does not do anything, but is useful as a substitute.
+PROTOBUF_EXPORT
 const char* NullParser(const char* begin, const char* end, void* object,
                        ParseContext*);
 
 // Helper for verification of utf8
+PROTOBUF_EXPORT
 bool VerifyUTF8(StringPiece s, ParseContext* ctx);
 // All the string parsers with or without UTF checking and for all CTypes.
+PROTOBUF_EXPORT
 const char* StringParser(const char* begin, const char* end, void* object,
                          ParseContext*);
+PROTOBUF_EXPORT
 const char* CordParser(const char* begin, const char* end, void* object,
                        ParseContext*);
+PROTOBUF_EXPORT
 const char* StringPieceParser(const char* begin, const char* end, void* object,
                               ParseContext*);
+PROTOBUF_EXPORT
 const char* StringParserUTF8(const char* begin, const char* end, void* object,
                              ParseContext*);
+PROTOBUF_EXPORT
 const char* CordParserUTF8(const char* begin, const char* end, void* object,
                            ParseContext*);
+PROTOBUF_EXPORT
 const char* StringPieceParserUTF8(const char* begin, const char* end,
                                   void* object, ParseContext*);
+PROTOBUF_EXPORT
 const char* StringParserUTF8Verify(const char* begin, const char* end,
                                    void* object, ParseContext*);
+PROTOBUF_EXPORT
 const char* CordParserUTF8Verify(const char* begin, const char* end,
                                  void* object, ParseContext*);
+PROTOBUF_EXPORT
 const char* StringPieceParserUTF8Verify(const char* begin, const char* end,
                                         void* object, ParseContext*);
 // Parsers that also eat the slopbytes if possible. Can only be called in a
 // ParseContext where limit_ is set properly.
+PROTOBUF_EXPORT
 const char* GreedyStringParser(const char* begin, const char* end, void* object,
                          ParseContext*);
+PROTOBUF_EXPORT
 const char* GreedyStringParserUTF8(const char* begin, const char* end, void* object,
                              ParseContext*);
+PROTOBUF_EXPORT
 const char* GreedyStringParserUTF8Verify(const char* begin, const char* end,
                                    void* object, ParseContext*);
 
 // This is the only recursive parser.
+PROTOBUF_EXPORT
 const char* UnknownGroupLiteParse(const char* begin, const char* end,
                                   void* object, ParseContext* ctx);
 // This is a helper to for the UnknownGroupLiteParse but is actually also
 // useful in the generated code. It uses overload on string* vs
 // UnknownFieldSet* to make the generated code isomorphic between full and lite.
+PROTOBUF_EXPORT
 std::pair<const char*, bool> UnknownFieldParse(uint32 tag, ParseClosure parent,
                                                const char* begin,
                                                const char* end, std::string* unknown,
@@ -762,44 +783,60 @@
 // corresponding field
 
 // These are packed varints
+PROTOBUF_EXPORT
 const char* PackedInt32Parser(const char* begin, const char* end, void* object,
                               ParseContext* ctx);
+PROTOBUF_EXPORT
 const char* PackedUInt32Parser(const char* begin, const char* end, void* object,
                                ParseContext* ctx);
+PROTOBUF_EXPORT
 const char* PackedInt64Parser(const char* begin, const char* end, void* object,
                               ParseContext* ctx);
+PROTOBUF_EXPORT
 const char* PackedUInt64Parser(const char* begin, const char* end, void* object,
                                ParseContext* ctx);
+PROTOBUF_EXPORT
 const char* PackedSInt32Parser(const char* begin, const char* end, void* object,
                                ParseContext* ctx);
+PROTOBUF_EXPORT
 const char* PackedSInt64Parser(const char* begin, const char* end, void* object,
                                ParseContext* ctx);
+PROTOBUF_EXPORT
 const char* PackedBoolParser(const char* begin, const char* end, void* object,
                              ParseContext* ctx);
 
 // Enums in proto3 do not require verification
+PROTOBUF_EXPORT
 const char* PackedEnumParser(const char* begin, const char* end, void* object,
                              ParseContext* ctx);
 // Enums in proto2 require verification. So an additional verification function
 // needs to be passed into ExtraParseData.
 // If it's a generated verification function we only need the function pointer.
+PROTOBUF_EXPORT
 const char* PackedValidEnumParserLite(const char* begin, const char* end,
                                       void* object, ParseContext* ctx);
 // If it's reflective we need a function that takes an additional argument.
+PROTOBUF_EXPORT
 const char* PackedValidEnumParserLiteArg(const char* begin, const char* end,
                                          void* object, ParseContext* ctx);
 
 // These are the packed fixed field parsers.
+PROTOBUF_EXPORT
 const char* PackedFixed32Parser(const char* begin, const char* end,
                                 void* object, ParseContext* ctx);
+PROTOBUF_EXPORT
 const char* PackedSFixed32Parser(const char* begin, const char* end,
                                  void* object, ParseContext* ctx);
+PROTOBUF_EXPORT
 const char* PackedFixed64Parser(const char* begin, const char* end,
                                 void* object, ParseContext* ctx);
+PROTOBUF_EXPORT
 const char* PackedSFixed64Parser(const char* begin, const char* end,
                                  void* object, ParseContext* ctx);
+PROTOBUF_EXPORT
 const char* PackedFloatParser(const char* begin, const char* end, void* object,
                               ParseContext* ctx);
+PROTOBUF_EXPORT
 const char* PackedDoubleParser(const char* begin, const char* end, void* object,
                                ParseContext* ctx);
 
@@ -808,6 +845,7 @@
 // to a MapField in which we parse the payload upon done (we detect this when
 // this function is called with limit_ == 0), by calling parse_map (also stored
 // in ctx) on the resulting string.
+PROTOBUF_EXPORT
 const char* SlowMapEntryParser(const char* begin, const char* end, void* object,
                                internal::ParseContext* ctx);
 
@@ -817,5 +855,4 @@
 
 #include <google/protobuf/port_undef.inc>
 
-#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 #endif  // GOOGLE_PROTOBUF_PARSE_CONTEXT_H__
diff --git a/src/google/protobuf/port_def.inc b/src/google/protobuf/port_def.inc
index 65d0821..24b3003 100644
--- a/src/google/protobuf/port_def.inc
+++ b/src/google/protobuf/port_def.inc
@@ -48,10 +48,10 @@
 // detect/prohibit anytime it is #included twice without a corresponding
 // #undef.
 
-// These macros are private and should always be #undef'd from headers.
-// If any of these errors fire, you should either properly #include
-// port_undef.h at the end of your header that #includes port.h, or
-// don't #include port.h twice in a .cc file.
+// These macros are private and should always be
+// ::util::RetrieveErrorSpace(*this) headers. If any of these errors fire, you
+// should either properly #include port_undef.h at the end of your header that
+// #includes port.h, or don't #include port.h twice in a .cc file.
 #ifdef PROTOBUF_NAMESPACE
 #error PROTOBUF_NAMESPACE was previously defined
 #endif
diff --git a/src/google/protobuf/reflection_ops.cc b/src/google/protobuf/reflection_ops.cc
index 233ba7d..541fee9 100644
--- a/src/google/protobuf/reflection_ops.cc
+++ b/src/google/protobuf/reflection_ops.cc
@@ -77,6 +77,10 @@
 
   const Reflection* from_reflection = GetReflectionOrDie(from);
   const Reflection* to_reflection = GetReflectionOrDie(*to);
+  bool is_from_generated = (from_reflection->GetMessageFactory() ==
+                            google::protobuf::MessageFactory::generated_factory());
+  bool is_to_generated = (to_reflection->GetMessageFactory() ==
+                          google::protobuf::MessageFactory::generated_factory());
 
   std::vector<const FieldDescriptor*> fields;
   from_reflection->ListFields(from, &fields);
@@ -84,15 +88,17 @@
     const FieldDescriptor* field = fields[i];
 
     if (field->is_repeated()) {
-      if (field->is_map()) {
-        MapFieldBase* from_field =
-            from_reflection->MapData(const_cast<Message*>(&from), field);
+      // Use map reflection if both are in map status and have the
+      // same map type to avoid sync with repeated field.
+      // Note: As from and to messages have the same descriptor, the
+      // map field types are the same if they are both generated
+      // messages or both dynamic messages.
+      if (is_from_generated == is_to_generated && field->is_map()) {
+        const MapFieldBase* from_field =
+            from_reflection->GetMapData(from, field);
         MapFieldBase* to_field =
-            to_reflection->MapData(const_cast<Message*>(to), field);
-        // Use map reflection if both are in map status and have the
-        // same map type to avoid sync with repeated field.
-        if (to_field->IsMapValid() && from_field->IsMapValid()
-            && typeid(*from_field) == typeid(*to_field)) {
+            to_reflection->MutableMapData(to, field);
+        if (to_field->IsMapValid() && from_field->IsMapValid()) {
           to_field->MergeFrom(*from_field);
           continue;
         }
@@ -189,8 +195,8 @@
       if (field->is_map()) {
         const FieldDescriptor* value_field = field->message_type()->field(1);
         if (value_field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
-          MapFieldBase* map_field =
-              reflection->MapData(const_cast<Message*>(&message), field);
+          const MapFieldBase* map_field =
+              reflection->GetMapData(message, field);
           if (map_field->IsMapValid()) {
             MapIterator iter(const_cast<Message*>(&message), field);
             MapIterator end(const_cast<Message*>(&message), field);
@@ -238,6 +244,25 @@
     const FieldDescriptor* field = fields[i];
     if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
       if (field->is_repeated()) {
+        if (field->is_map()) {
+          const FieldDescriptor* value_field = field->message_type()->field(1);
+          if (value_field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+            const MapFieldBase* map_field =
+                reflection->MutableMapData(message, field);
+            if (map_field->IsMapValid()) {
+              MapIterator iter(message, field);
+              MapIterator end(message, field);
+              for (map_field->MapBegin(&iter), map_field->MapEnd(&end);
+                   iter != end; ++iter) {
+                iter.MutableValueRef()->MutableMessageValue()
+                    ->DiscardUnknownFields();
+              }
+              continue;
+            }
+          } else {
+            continue;
+          }
+        }
         int size = reflection->FieldSize(*message, field);
         for (int j = 0; j < size; j++) {
           reflection->MutableRepeatedMessage(message, field, j)
diff --git a/src/google/protobuf/source_context.pb.cc b/src/google/protobuf/source_context.pb.cc
index 5ee61e7..ff0668b 100644
--- a/src/google/protobuf/source_context.pb.cc
+++ b/src/google/protobuf/source_context.pb.cc
@@ -167,13 +167,13 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // string file_name = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.SourceContext.file_name");
         auto str = msg->mutable_file_name();
@@ -190,7 +190,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -204,13 +204,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool SourceContext::MergePartialFromCodedStream(
@@ -283,8 +279,7 @@
 }
 
 ::google::protobuf::uint8* SourceContext::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.SourceContext)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
diff --git a/src/google/protobuf/source_context.pb.h b/src/google/protobuf/source_context.pb.h
index 10c0148..b3d7834 100644
--- a/src/google/protobuf/source_context.pb.h
+++ b/src/google/protobuf/source_context.pb.h
@@ -132,7 +132,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
diff --git a/src/google/protobuf/struct.pb.cc b/src/google/protobuf/struct.pb.cc
index 464436f..317d5dc 100644
--- a/src/google/protobuf/struct.pb.cc
+++ b/src/google/protobuf/struct.pb.cc
@@ -306,14 +306,14 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // map<string, .google.protobuf.Value> fields = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::internal::SlowMapEntryParser;
           auto parse_map = ::google::protobuf::Struct_FieldsEntry_DoNotUse::_ParseMap;
@@ -329,7 +329,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -343,13 +343,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool Struct::MergePartialFromCodedStream(
@@ -470,8 +466,7 @@
 }
 
 ::google::protobuf::uint8* Struct::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Struct)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -491,7 +486,7 @@
       }
     };
 
-    if (deterministic &&
+    if (false &&
         this->fields().size() > 1) {
       ::std::unique_ptr<SortItem[]> items(
           new SortItem[this->fields().size()]);
@@ -506,7 +501,7 @@
       ::std::unique_ptr<Struct_FieldsEntry_DoNotUse> entry;
       for (size_type i = 0; i < n; i++) {
         entry.reset(fields_.NewEntryWrapper(items[static_cast<ptrdiff_t>(i)]->first, items[static_cast<ptrdiff_t>(i)]->second));
-        target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessageNoVirtualToArray(1, *entry, deterministic, target);
+        target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessageNoVirtualToArray(1, *entry, target);
         if (entry->GetArena() != nullptr) {
           entry.release();
         }
@@ -518,7 +513,7 @@
           it = this->fields().begin();
           it != this->fields().end(); ++it) {
         entry.reset(fields_.NewEntryWrapper(it->first, it->second));
-        target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessageNoVirtualToArray(1, *entry, deterministic, target);
+        target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessageNoVirtualToArray(1, *entry, target);
         if (entry->GetArena() != nullptr) {
           entry.release();
         }
@@ -855,14 +850,14 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // .google.protobuf.NullValue null_value = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ::google::protobuf::NullValue value = static_cast<::google::protobuf::NullValue>(val);
         msg->set_null_value(value);
@@ -880,7 +875,7 @@
       // string string_value = 3;
       case 3: {
         if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.Value.string_value");
         auto str = msg->mutable_string_value();
@@ -900,7 +895,7 @@
       case 4: {
         if (static_cast<::google::protobuf::uint8>(tag) != 32) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         bool value = val;
         msg->set_bool_value(value);
@@ -909,7 +904,7 @@
       // .google.protobuf.Struct struct_value = 5;
       case 5: {
         if (static_cast<::google::protobuf::uint8>(tag) != 42) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         parser_till_end = ::google::protobuf::Struct::_InternalParse;
         object = msg->mutable_struct_value();
@@ -924,7 +919,7 @@
       // .google.protobuf.ListValue list_value = 6;
       case 6: {
         if (static_cast<::google::protobuf::uint8>(tag) != 50) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         parser_till_end = ::google::protobuf::ListValue::_InternalParse;
         object = msg->mutable_list_value();
@@ -937,7 +932,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -951,13 +946,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool Value::MergePartialFromCodedStream(
@@ -1122,8 +1113,7 @@
 }
 
 ::google::protobuf::uint8* Value::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Value)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -1159,14 +1149,14 @@
   if (has_struct_value()) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        5, HasBitSetters::struct_value(this), deterministic, target);
+        5, HasBitSetters::struct_value(this), target);
   }
 
   // .google.protobuf.ListValue list_value = 6;
   if (has_list_value()) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        6, HasBitSetters::list_value(this), deterministic, target);
+        6, HasBitSetters::list_value(this), target);
   }
 
   if (_internal_metadata_.have_unknown_fields()) {
@@ -1422,14 +1412,14 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // repeated .google.protobuf.Value values = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::Value::_InternalParse;
           object = msg->add_values();
@@ -1444,7 +1434,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -1458,13 +1448,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool ListValue::MergePartialFromCodedStream(
@@ -1532,8 +1518,7 @@
 }
 
 ::google::protobuf::uint8* ListValue::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ListValue)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -1543,7 +1528,7 @@
       n = static_cast<unsigned int>(this->values_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        1, this->values(static_cast<int>(i)), deterministic, target);
+        1, this->values(static_cast<int>(i)), target);
   }
 
   if (_internal_metadata_.have_unknown_fields()) {
diff --git a/src/google/protobuf/struct.pb.h b/src/google/protobuf/struct.pb.h
index 857d67d..e44bcbd 100644
--- a/src/google/protobuf/struct.pb.h
+++ b/src/google/protobuf/struct.pb.h
@@ -199,7 +199,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -344,7 +344,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -562,7 +562,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc
index a434509..50e2b1c 100644
--- a/src/google/protobuf/text_format.cc
+++ b/src/google/protobuf/text_format.cc
@@ -2049,7 +2049,7 @@
     std::vector<const Message*>* sorted_map_field) {
   bool need_release = false;
   const MapFieldBase& base =
-      *reflection->MapData(const_cast<Message*>(&message), field);
+      *reflection->GetMapData(message, field);
 
   if (base.IsRepeatedFieldValid()) {
     const RepeatedPtrField<Message>& map_field =
diff --git a/src/google/protobuf/timestamp.pb.cc b/src/google/protobuf/timestamp.pb.cc
index 650c18a..bf30404 100644
--- a/src/google/protobuf/timestamp.pb.cc
+++ b/src/google/protobuf/timestamp.pb.cc
@@ -182,14 +182,14 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // int64 seconds = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ::google::protobuf::int64 value = val;
         msg->set_seconds(value);
@@ -199,14 +199,14 @@
       case 2: {
         if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ::google::protobuf::int32 value = val;
         msg->set_nanos(value);
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -220,13 +220,6 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
-  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool Timestamp::MergePartialFromCodedStream(
@@ -310,8 +303,7 @@
 }
 
 ::google::protobuf::uint8* Timestamp::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Timestamp)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
diff --git a/src/google/protobuf/timestamp.pb.h b/src/google/protobuf/timestamp.pb.h
index 8f0fba0..ccb2890 100644
--- a/src/google/protobuf/timestamp.pb.h
+++ b/src/google/protobuf/timestamp.pb.h
@@ -139,7 +139,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
diff --git a/src/google/protobuf/type.pb.cc b/src/google/protobuf/type.pb.cc
index a84e34c..1696bfa 100644
--- a/src/google/protobuf/type.pb.cc
+++ b/src/google/protobuf/type.pb.cc
@@ -509,13 +509,13 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // string name = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.Type.name");
         auto str = msg->mutable_name();
@@ -535,7 +535,7 @@
       case 2: {
         if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::Field::_InternalParse;
           object = msg->add_fields();
@@ -553,7 +553,7 @@
       case 3: {
         if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           ctx->extra_parse_data().SetFieldName("google.protobuf.Type.oneofs");
           auto str = msg->add_oneofs();
@@ -575,7 +575,7 @@
       case 4: {
         if (static_cast<::google::protobuf::uint8>(tag) != 34) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::Option::_InternalParse;
           object = msg->add_options();
@@ -592,7 +592,7 @@
       // .google.protobuf.SourceContext source_context = 5;
       case 5: {
         if (static_cast<::google::protobuf::uint8>(tag) != 42) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         parser_till_end = ::google::protobuf::SourceContext::_InternalParse;
         object = msg->mutable_source_context();
@@ -608,14 +608,14 @@
       case 6: {
         if (static_cast<::google::protobuf::uint8>(tag) != 48) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ::google::protobuf::Syntax value = static_cast<::google::protobuf::Syntax>(val);
         msg->set_syntax(value);
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -629,13 +629,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool Type::MergePartialFromCodedStream(
@@ -811,8 +807,7 @@
 }
 
 ::google::protobuf::uint8* Type::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Type)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -833,7 +828,7 @@
       n = static_cast<unsigned int>(this->fields_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        2, this->fields(static_cast<int>(i)), deterministic, target);
+        2, this->fields(static_cast<int>(i)), target);
   }
 
   // repeated string oneofs = 3;
@@ -851,14 +846,14 @@
       n = static_cast<unsigned int>(this->options_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        4, this->options(static_cast<int>(i)), deterministic, target);
+        4, this->options(static_cast<int>(i)), target);
   }
 
   // .google.protobuf.SourceContext source_context = 5;
   if (this->has_source_context()) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        5, HasBitSetters::source_context(this), deterministic, target);
+        5, HasBitSetters::source_context(this), target);
   }
 
   // .google.protobuf.Syntax syntax = 6;
@@ -1166,14 +1161,14 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // .google.protobuf.Field.Kind kind = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ::google::protobuf::Field_Kind value = static_cast<::google::protobuf::Field_Kind>(val);
         msg->set_kind(value);
@@ -1183,7 +1178,7 @@
       case 2: {
         if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ::google::protobuf::Field_Cardinality value = static_cast<::google::protobuf::Field_Cardinality>(val);
         msg->set_cardinality(value);
@@ -1193,7 +1188,7 @@
       case 3: {
         if (static_cast<::google::protobuf::uint8>(tag) != 24) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ::google::protobuf::int32 value = val;
         msg->set_number(value);
@@ -1202,7 +1197,7 @@
       // string name = 4;
       case 4: {
         if (static_cast<::google::protobuf::uint8>(tag) != 34) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.Field.name");
         auto str = msg->mutable_name();
@@ -1221,7 +1216,7 @@
       // string type_url = 6;
       case 6: {
         if (static_cast<::google::protobuf::uint8>(tag) != 50) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.Field.type_url");
         auto str = msg->mutable_type_url();
@@ -1241,7 +1236,7 @@
       case 7: {
         if (static_cast<::google::protobuf::uint8>(tag) != 56) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ::google::protobuf::int32 value = val;
         msg->set_oneof_index(value);
@@ -1251,7 +1246,7 @@
       case 8: {
         if (static_cast<::google::protobuf::uint8>(tag) != 64) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         bool value = val;
         msg->set_packed(value);
@@ -1261,7 +1256,7 @@
       case 9: {
         if (static_cast<::google::protobuf::uint8>(tag) != 74) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::Option::_InternalParse;
           object = msg->add_options();
@@ -1278,7 +1273,7 @@
       // string json_name = 10;
       case 10: {
         if (static_cast<::google::protobuf::uint8>(tag) != 82) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.Field.json_name");
         auto str = msg->mutable_json_name();
@@ -1297,7 +1292,7 @@
       // string default_value = 11;
       case 11: {
         if (static_cast<::google::protobuf::uint8>(tag) != 90) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.Field.default_value");
         auto str = msg->mutable_default_value();
@@ -1314,7 +1309,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -1328,13 +1323,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool Field::MergePartialFromCodedStream(
@@ -1596,8 +1587,7 @@
 }
 
 ::google::protobuf::uint8* Field::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Field)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -1656,7 +1646,7 @@
       n = static_cast<unsigned int>(this->options_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        9, this->options(static_cast<int>(i)), deterministic, target);
+        9, this->options(static_cast<int>(i)), target);
   }
 
   // string json_name = 10;
@@ -2029,13 +2019,13 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // string name = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.Enum.name");
         auto str = msg->mutable_name();
@@ -2055,7 +2045,7 @@
       case 2: {
         if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::EnumValue::_InternalParse;
           object = msg->add_enumvalue();
@@ -2073,7 +2063,7 @@
       case 3: {
         if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::Option::_InternalParse;
           object = msg->add_options();
@@ -2090,7 +2080,7 @@
       // .google.protobuf.SourceContext source_context = 4;
       case 4: {
         if (static_cast<::google::protobuf::uint8>(tag) != 34) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         parser_till_end = ::google::protobuf::SourceContext::_InternalParse;
         object = msg->mutable_source_context();
@@ -2106,14 +2096,14 @@
       case 5: {
         if (static_cast<::google::protobuf::uint8>(tag) != 40) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ::google::protobuf::Syntax value = static_cast<::google::protobuf::Syntax>(val);
         msg->set_syntax(value);
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -2127,13 +2117,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool Enum::MergePartialFromCodedStream(
@@ -2283,8 +2269,7 @@
 }
 
 ::google::protobuf::uint8* Enum::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Enum)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -2305,7 +2290,7 @@
       n = static_cast<unsigned int>(this->enumvalue_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        2, this->enumvalue(static_cast<int>(i)), deterministic, target);
+        2, this->enumvalue(static_cast<int>(i)), target);
   }
 
   // repeated .google.protobuf.Option options = 3;
@@ -2313,14 +2298,14 @@
       n = static_cast<unsigned int>(this->options_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        3, this->options(static_cast<int>(i)), deterministic, target);
+        3, this->options(static_cast<int>(i)), target);
   }
 
   // .google.protobuf.SourceContext source_context = 4;
   if (this->has_source_context()) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        4, HasBitSetters::source_context(this), deterministic, target);
+        4, HasBitSetters::source_context(this), target);
   }
 
   // .google.protobuf.Syntax syntax = 5;
@@ -2581,13 +2566,13 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // string name = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.EnumValue.name");
         auto str = msg->mutable_name();
@@ -2607,7 +2592,7 @@
       case 2: {
         if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ::google::protobuf::int32 value = val;
         msg->set_number(value);
@@ -2617,7 +2602,7 @@
       case 3: {
         if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
         do {
-          ptr = Varint::Parse32Inline(ptr, &size);
+          ptr = ::google::protobuf::io::Parse32(ptr, &size);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           parser_till_end = ::google::protobuf::Option::_InternalParse;
           object = msg->add_options();
@@ -2632,7 +2617,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -2646,13 +2631,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool EnumValue::MergePartialFromCodedStream(
@@ -2763,8 +2744,7 @@
 }
 
 ::google::protobuf::uint8* EnumValue::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumValue)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -2790,7 +2770,7 @@
       n = static_cast<unsigned int>(this->options_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        3, this->options(static_cast<int>(i)), deterministic, target);
+        3, this->options(static_cast<int>(i)), target);
   }
 
   if (_internal_metadata_.have_unknown_fields()) {
@@ -3052,13 +3032,13 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // string name = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.Option.name");
         auto str = msg->mutable_name();
@@ -3077,7 +3057,7 @@
       // .google.protobuf.Any value = 2;
       case 2: {
         if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         parser_till_end = ::google::protobuf::Any::_InternalParse;
         object = msg->mutable_value();
@@ -3090,7 +3070,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -3104,13 +3084,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool Option::MergePartialFromCodedStream(
@@ -3200,8 +3176,7 @@
 }
 
 ::google::protobuf::uint8* Option::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Option)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -3221,7 +3196,7 @@
   if (this->has_value()) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageToArray(
-        2, HasBitSetters::value(this), deterministic, target);
+        2, HasBitSetters::value(this), target);
   }
 
   if (_internal_metadata_.have_unknown_fields()) {
diff --git a/src/google/protobuf/type.pb.h b/src/google/protobuf/type.pb.h
index 0df5341..fe39afb 100644
--- a/src/google/protobuf/type.pb.h
+++ b/src/google/protobuf/type.pb.h
@@ -240,7 +240,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -452,7 +452,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -805,7 +805,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -994,7 +994,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -1157,7 +1157,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
diff --git a/src/google/protobuf/unknown_field_set.cc b/src/google/protobuf/unknown_field_set.cc
index fe3c825..f0f9ee2 100644
--- a/src/google/protobuf/unknown_field_set.cc
+++ b/src/google/protobuf/unknown_field_set.cc
@@ -54,22 +54,21 @@
 }
 
 void UnknownFieldSet::ClearFallback() {
-  GOOGLE_DCHECK(fields_ != NULL && fields_->size() > 0);
-  int n = fields_->size();
+  GOOGLE_DCHECK(!fields_.empty());
+  int n = fields_.size();
   do {
-    (*fields_)[--n].Delete();
+    (fields_)[--n].Delete();
   } while (n > 0);
-  delete fields_;
-  fields_ = NULL;
+  fields_.clear();
 }
 
 void UnknownFieldSet::InternalMergeFrom(const UnknownFieldSet& other) {
   int other_field_count = other.field_count();
   if (other_field_count > 0) {
-    fields_ = new std::vector<UnknownField>();
+    fields_.reserve(fields_.size() + other_field_count);
     for (int i = 0; i < other_field_count; i++) {
-      fields_->push_back((*other.fields_)[i]);
-      fields_->back().DeepCopy((*other.fields_)[i]);
+      fields_.push_back((other.fields_)[i]);
+      fields_.back().DeepCopy((other.fields_)[i]);
     }
   }
 }
@@ -77,10 +76,10 @@
 void UnknownFieldSet::MergeFrom(const UnknownFieldSet& other) {
   int other_field_count = other.field_count();
   if (other_field_count > 0) {
-    if (fields_ == NULL) fields_ = new std::vector<UnknownField>();
+    fields_.reserve(fields_.size() + other_field_count);
     for (int i = 0; i < other_field_count; i++) {
-      fields_->push_back((*other.fields_)[i]);
-      fields_->back().DeepCopy((*other.fields_)[i]);
+      fields_.push_back((other.fields_)[i]);
+      fields_.back().DeepCopy((other.fields_)[i]);
     }
   }
 }
@@ -88,16 +87,14 @@
 // A specialized MergeFrom for performance when we are merging from an UFS that
 // is temporary and can be destroyed in the process.
 void UnknownFieldSet::MergeFromAndDestroy(UnknownFieldSet* other) {
-  int other_field_count = other->field_count();
-  if (other_field_count > 0) {
-    if (fields_ == NULL) fields_ = new std::vector<UnknownField>();
-    for (int i = 0; i < other_field_count; i++) {
-      fields_->push_back((*other->fields_)[i]);
-      (*other->fields_)[i].Reset();
-    }
+  if (fields_.empty()) {
+    fields_ = std::move(other->fields_);
+  } else {
+    fields_.insert(fields_.end(),
+                   std::make_move_iterator(other->fields_.begin()),
+                   std::make_move_iterator(other->fields_.end()));
   }
-  delete other->fields_;
-  other->fields_ = NULL;
+  other->fields_.clear();
 }
 
 void UnknownFieldSet::MergeToInternalMetdata(
@@ -107,12 +104,12 @@
 }
 
 size_t UnknownFieldSet::SpaceUsedExcludingSelfLong() const {
-  if (fields_ == NULL) return 0;
+  if (fields_.empty()) return 0;
 
-  size_t total_size = sizeof(*fields_) + sizeof(UnknownField) * fields_->size();
+  size_t total_size = sizeof(fields_) + sizeof(UnknownField) * fields_.size();
 
-  for (int i = 0; i < fields_->size(); i++) {
-    const UnknownField& field = (*fields_)[i];
+  for (int i = 0; i < fields_.size(); i++) {
+    const UnknownField& field = (fields_)[i];
     switch (field.type()) {
       case UnknownField::TYPE_LENGTH_DELIMITED:
         total_size += sizeof(*field.data_.length_delimited_.string_value_) +
@@ -138,8 +135,7 @@
   field.number_ = number;
   field.SetType(UnknownField::TYPE_VARINT);
   field.data_.varint_ = value;
-  if (fields_ == NULL) fields_ = new std::vector<UnknownField>();
-  fields_->push_back(field);
+  fields_.push_back(field);
 }
 
 void UnknownFieldSet::AddFixed32(int number, uint32 value) {
@@ -147,8 +143,7 @@
   field.number_ = number;
   field.SetType(UnknownField::TYPE_FIXED32);
   field.data_.fixed32_ = value;
-  if (fields_ == NULL) fields_ = new std::vector<UnknownField>();
-  fields_->push_back(field);
+  fields_.push_back(field);
 }
 
 void UnknownFieldSet::AddFixed64(int number, uint64 value) {
@@ -156,8 +151,7 @@
   field.number_ = number;
   field.SetType(UnknownField::TYPE_FIXED64);
   field.data_.fixed64_ = value;
-  if (fields_ == NULL) fields_ = new std::vector<UnknownField>();
-  fields_->push_back(field);
+  fields_.push_back(field);
 }
 
 string* UnknownFieldSet::AddLengthDelimited(int number) {
@@ -165,8 +159,7 @@
   field.number_ = number;
   field.SetType(UnknownField::TYPE_LENGTH_DELIMITED);
   field.data_.length_delimited_.string_value_ = new string;
-  if (fields_ == NULL) fields_ = new std::vector<UnknownField>();
-  fields_->push_back(field);
+  fields_.push_back(field);
   return field.data_.length_delimited_.string_value_;
 }
 
@@ -176,57 +169,44 @@
   field.number_ = number;
   field.SetType(UnknownField::TYPE_GROUP);
   field.data_.group_ = new UnknownFieldSet;
-  if (fields_ == NULL) fields_ = new std::vector<UnknownField>();
-  fields_->push_back(field);
+  fields_.push_back(field);
   return field.data_.group_;
 }
 
 void UnknownFieldSet::AddField(const UnknownField& field) {
-  if (fields_ == NULL) fields_ = new std::vector<UnknownField>();
-  fields_->push_back(field);
-  fields_->back().DeepCopy(field);
+  fields_.push_back(field);
+  fields_.back().DeepCopy(field);
 }
 
 void UnknownFieldSet::DeleteSubrange(int start, int num) {
   // Delete the specified fields.
   for (int i = 0; i < num; ++i) {
-    (*fields_)[i + start].Delete();
+    (fields_)[i + start].Delete();
   }
   // Slide down the remaining fields.
-  for (int i = start + num; i < fields_->size(); ++i) {
-    (*fields_)[i - num] = (*fields_)[i];
+  for (int i = start + num; i < fields_.size(); ++i) {
+    (fields_)[i - num] = (fields_)[i];
   }
   // Pop off the # of deleted fields.
   for (int i = 0; i < num; ++i) {
-    fields_->pop_back();
-  }
-  if (fields_ && fields_->size() == 0) {
-    // maintain invariant: never hold fields_ if empty.
-    delete fields_;
-    fields_ = NULL;
+    fields_.pop_back();
   }
 }
 
 void UnknownFieldSet::DeleteByNumber(int number) {
-  if (fields_ == NULL) return;
   int left = 0;  // The number of fields left after deletion.
-  for (int i = 0; i < fields_->size(); ++i) {
-    UnknownField* field = &(*fields_)[i];
+  for (int i = 0; i < fields_.size(); ++i) {
+    UnknownField* field = &(fields_)[i];
     if (field->number() == number) {
       field->Delete();
     } else {
       if (i != left) {
-        (*fields_)[left] = (*fields_)[i];
+        (fields_)[left] = (fields_)[i];
       }
       ++left;
     }
   }
-  fields_->resize(left);
-  if (left == 0) {
-    // maintain invariant: never hold fields_ if empty.
-    delete fields_;
-    fields_ = NULL;
-  }
+  fields_.resize(left);
 }
 
 bool UnknownFieldSet::MergeFromCodedStream(io::CodedInputStream* input) {
@@ -269,22 +249,6 @@
   }
 }
 
-// Reset all owned ptrs, a special function for performance, to avoid double
-// owning the ptrs, when we merge from a temporary UnknownFieldSet objects.
-void UnknownField::Reset() {
-  switch (type()) {
-    case UnknownField::TYPE_LENGTH_DELIMITED:
-      data_.length_delimited_.string_value_ = NULL;
-      break;
-    case UnknownField::TYPE_GROUP: {
-      data_.group_ = NULL;
-      break;
-    }
-    default:
-      break;
-  }
-}
-
 void UnknownField::DeepCopy(const UnknownField& other) {
   switch (type()) {
     case UnknownField::TYPE_LENGTH_DELIMITED:
@@ -328,7 +292,7 @@
   auto ptr = begin;
   while (ptr < end) {
     uint64 varint;
-    ptr = Varint::Parse64(ptr, &varint);
+    ptr = io::Parse64(ptr, &varint);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     int val = varint;
     if (ctx->extra_parse_data().ValidateEnum<UnknownFieldSet>(val))
@@ -343,7 +307,7 @@
   auto ptr = begin;
   while (ptr < end) {
     uint64 varint;
-    ptr = Varint::Parse64(ptr, &varint);
+    ptr = io::Parse64(ptr, &varint);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     int val = varint;
     if (ctx->extra_parse_data().ValidateEnumArg<UnknownFieldSet>(val))
diff --git a/src/google/protobuf/unknown_field_set.h b/src/google/protobuf/unknown_field_set.h
index 0193b27..d8335cd 100644
--- a/src/google/protobuf/unknown_field_set.h
+++ b/src/google/protobuf/unknown_field_set.h
@@ -176,17 +176,11 @@
   // For InternalMergeFrom
   friend class UnknownField;
   // Merges from other UnknownFieldSet. This method assumes, that this object
-  // is newly created and has fields_ == NULL;
+  // is newly created and has no fields.
   void InternalMergeFrom(const UnknownFieldSet& other);
   void ClearFallback();
 
-  // fields_ is either NULL, or a pointer to a vector that is *non-empty*. We
-  // never hold the empty vector because we want the 'do we have any unknown
-  // fields' check to be fast, and avoid a cache miss: the UFS instance gets
-  // embedded in the message object, so 'fields_ != NULL' tests a member
-  // variable hot in the cache, without the need to go touch a vector somewhere
-  // else in memory.
-  std::vector<UnknownField>* fields_;
+  std::vector<UnknownField> fields_;
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UnknownFieldSet);
 };
 
@@ -200,13 +194,16 @@
   unknown->AddLengthDelimited(num)->assign(val.data(), val.size());
 }
 
+PROTOBUF_EXPORT
 const char* PackedValidEnumParser(const char* begin, const char* end,
                                   void* object, ParseContext* ctx);
+PROTOBUF_EXPORT
 const char* PackedValidEnumParserArg(const char* begin, const char* end,
                                      void* object, ParseContext* ctx);
-
+PROTOBUF_EXPORT
 const char* UnknownGroupParse(const char* begin, const char* end, void* object,
                               ParseContext* ctx);
+PROTOBUF_EXPORT
 std::pair<const char*, bool> UnknownFieldParse(uint64 tag, ParseClosure parent,
                                                const char* begin,
                                                const char* end,
@@ -262,10 +259,6 @@
   // If this UnknownField contains a pointer, delete it.
   void Delete();
 
-  // Reset all the underlying pointers to NULL. A special function to be only
-  // used while merging from a temporary UFS.
-  void Reset();
-
   // Make a deep copy of any pointers in this UnknownField.
   void DeepCopy(const UnknownField& other);
 
@@ -291,36 +284,34 @@
 // ===================================================================
 // inline implementations
 
-inline UnknownFieldSet::UnknownFieldSet() : fields_(NULL) {}
+inline UnknownFieldSet::UnknownFieldSet() {}
 
 inline UnknownFieldSet::~UnknownFieldSet() { Clear(); }
 
 inline void UnknownFieldSet::ClearAndFreeMemory() { Clear(); }
 
 inline void UnknownFieldSet::Clear() {
-  if (fields_ != NULL) {
+  if (!fields_.empty()) {
     ClearFallback();
   }
 }
 
 inline bool UnknownFieldSet::empty() const {
-  // Invariant: fields_ is never empty if present.
-  return !fields_;
+  return fields_.empty();
 }
 
 inline void UnknownFieldSet::Swap(UnknownFieldSet* x) {
-  std::swap(fields_, x->fields_);
+  fields_.swap(x->fields_);
 }
 
 inline int UnknownFieldSet::field_count() const {
-  return fields_ ? static_cast<int>(fields_->size()) : 0;
+  return static_cast<int>(fields_.size());
 }
 inline const UnknownField& UnknownFieldSet::field(int index) const {
-  GOOGLE_DCHECK(fields_ != NULL);
-  return (*fields_)[static_cast<size_t>(index)];
+  return (fields_)[static_cast<size_t>(index)];
 }
 inline UnknownField* UnknownFieldSet::mutable_field(int index) {
-  return &(*fields_)[static_cast<size_t>(index)];
+  return &(fields_)[static_cast<size_t>(index)];
 }
 
 inline void UnknownFieldSet::AddLengthDelimited(
diff --git a/src/google/protobuf/util/internal/datapiece.cc b/src/google/protobuf/util/internal/datapiece.cc
index 30060fe..40827cb 100644
--- a/src/google/protobuf/util/internal/datapiece.cc
+++ b/src/google/protobuf/util/internal/datapiece.cc
@@ -274,6 +274,7 @@
 
 StatusOr<int> DataPiece::ToEnum(const google::protobuf::Enum* enum_type,
                                 bool use_lower_camel_for_enums,
+                                bool case_insensitive_enum_parsing,
                                 bool ignore_unknown_enum_values,
                                 bool* is_unknown_enum_value) const {
   if (type_ == TYPE_NULL) return google::protobuf::NULL_VALUE;
@@ -295,11 +296,16 @@
     }
 
     // Next try a normalized name.
-    for (string::iterator it = enum_name.begin(); it != enum_name.end(); ++it) {
-      *it = *it == '-' ? '_' : ascii_toupper(*it);
+    bool should_normalize_enum =
+        case_insensitive_enum_parsing || use_lower_camel_for_enums;
+    if (should_normalize_enum) {
+      for (string::iterator it = enum_name.begin(); it != enum_name.end();
+           ++it) {
+        *it = *it == '-' ? '_' : ascii_toupper(*it);
+      }
+      value = FindEnumValueByNameOrNull(enum_type, enum_name);
+      if (value != nullptr) return value->number();
     }
-    value = FindEnumValueByNameOrNull(enum_type, enum_name);
-    if (value != nullptr) return value->number();
 
     // If use_lower_camel_for_enums is true try with enum name without
     // underscore. This will also accept camel case names as the enum_name has
diff --git a/src/google/protobuf/util/internal/datapiece.h b/src/google/protobuf/util/internal/datapiece.h
index 0551ff5..f2628b8 100644
--- a/src/google/protobuf/util/internal/datapiece.h
+++ b/src/google/protobuf/util/internal/datapiece.h
@@ -169,7 +169,10 @@
   // If none of these succeeds, returns a conversion error status.
   util::StatusOr<int> ToEnum(const google::protobuf::Enum* enum_type,
                                bool use_lower_camel_for_enums) const {
-    return ToEnum(enum_type, use_lower_camel_for_enums, false, nullptr);
+    return ToEnum(enum_type, use_lower_camel_for_enums,
+                  /* ignore_unknown_enum_values */ false,
+                  /* case_insensitive_enum_parsing */ true,
+                  /* is_unknown_enum_value */ nullptr);
   }
 
  private:
@@ -186,6 +189,7 @@
   // unknown enum values.
   util::StatusOr<int> ToEnum(const google::protobuf::Enum* enum_type,
                                bool use_lower_camel_for_enums,
+                               bool case_insensitive_enum_parsing,
                                bool ignore_unknown_enum_values,
                                bool* is_unknown_enum_value) const;
 
diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.h b/src/google/protobuf/util/internal/default_value_objectwriter.h
index 89636dc..7a8863c 100644
--- a/src/google/protobuf/util/internal/default_value_objectwriter.h
+++ b/src/google/protobuf/util/internal/default_value_objectwriter.h
@@ -119,7 +119,7 @@
   DefaultValueObjectWriter* RenderBytes(StringPiece name,
                                         StringPiece value) override;
 
-  DefaultValueObjectWriter* RenderNull(StringPiece name) override;
+  virtual DefaultValueObjectWriter* RenderNull(StringPiece name);
 
   // Register the callback for scrubbing of fields. Owership of
   // field_scrub_callback pointer is also transferred to this class
diff --git a/src/google/protobuf/util/internal/json_objectwriter.h b/src/google/protobuf/util/internal/json_objectwriter.h
index 2e19c9b..ebfc7fb 100644
--- a/src/google/protobuf/util/internal/json_objectwriter.h
+++ b/src/google/protobuf/util/internal/json_objectwriter.h
@@ -95,20 +95,21 @@
   virtual ~JsonObjectWriter();
 
   // ObjectWriter methods.
-  JsonObjectWriter* StartObject(StringPiece name) override;
-  JsonObjectWriter* EndObject() override;
-  JsonObjectWriter* StartList(StringPiece name) override;
-  JsonObjectWriter* EndList() override;
-  JsonObjectWriter* RenderBool(StringPiece name, bool value) override;
-  JsonObjectWriter* RenderInt32(StringPiece name, int32 value) override;
-  JsonObjectWriter* RenderUint32(StringPiece name, uint32 value) override;
-  JsonObjectWriter* RenderInt64(StringPiece name, int64 value) override;
-  JsonObjectWriter* RenderUint64(StringPiece name, uint64 value) override;
-  JsonObjectWriter* RenderDouble(StringPiece name, double value) override;
-  JsonObjectWriter* RenderFloat(StringPiece name, float value) override;
-  JsonObjectWriter* RenderString(StringPiece name, StringPiece value) override;
-  JsonObjectWriter* RenderBytes(StringPiece name, StringPiece value) override;
-  JsonObjectWriter* RenderNull(StringPiece name) override;
+  virtual JsonObjectWriter* StartObject(StringPiece name);
+  virtual JsonObjectWriter* EndObject();
+  virtual JsonObjectWriter* StartList(StringPiece name);
+  virtual JsonObjectWriter* EndList();
+  virtual JsonObjectWriter* RenderBool(StringPiece name, bool value);
+  virtual JsonObjectWriter* RenderInt32(StringPiece name, int32 value);
+  virtual JsonObjectWriter* RenderUint32(StringPiece name, uint32 value);
+  virtual JsonObjectWriter* RenderInt64(StringPiece name, int64 value);
+  virtual JsonObjectWriter* RenderUint64(StringPiece name, uint64 value);
+  virtual JsonObjectWriter* RenderDouble(StringPiece name, double value);
+  virtual JsonObjectWriter* RenderFloat(StringPiece name, float value);
+  virtual JsonObjectWriter* RenderString(StringPiece name,
+                                         StringPiece value);
+  virtual JsonObjectWriter* RenderBytes(StringPiece name, StringPiece value);
+  virtual JsonObjectWriter* RenderNull(StringPiece name);
   virtual JsonObjectWriter* RenderNullAsEmpty(StringPiece name);
 
   void set_use_websafe_base64_for_bytes(bool value) {
diff --git a/src/google/protobuf/util/internal/json_stream_parser_test.cc b/src/google/protobuf/util/internal/json_stream_parser_test.cc
index 764c9f7..83a0c2d 100644
--- a/src/google/protobuf/util/internal/json_stream_parser_test.cc
+++ b/src/google/protobuf/util/internal/json_stream_parser_test.cc
@@ -140,7 +140,7 @@
                    bool allow_empty_null = false) {
     util::Status result =
         RunTest(json, split, coerce_utf8, allow_empty_null);
-    EXPECT_EQ(util::error::INVALID_ARGUMENT, result.error_code());
+    EXPECT_EQ(util::error::INVALID_ARGUMENT, result.code());
     StringPiece error_message(result.error_message());
     EXPECT_EQ(error_prefix, error_message.substr(0, error_prefix.size()));
   }
diff --git a/src/google/protobuf/util/internal/proto_writer.cc b/src/google/protobuf/util/internal/proto_writer.cc
index 391c32e..ec9ef19 100644
--- a/src/google/protobuf/util/internal/proto_writer.cc
+++ b/src/google/protobuf/util/internal/proto_writer.cc
@@ -69,6 +69,7 @@
       ignore_unknown_fields_(false),
       ignore_unknown_enum_values_(false),
       use_lower_camel_for_enums_(false),
+      case_insensitive_enum_parsing_(true),
       element_(nullptr),
       size_insert_(),
       output_(output),
@@ -89,6 +90,7 @@
       ignore_unknown_fields_(false),
       ignore_unknown_enum_values_(false),
       use_lower_camel_for_enums_(false),
+      case_insensitive_enum_parsing_(true),
       element_(nullptr),
       size_insert_(),
       output_(output),
@@ -589,9 +591,11 @@
                               const google::protobuf::Enum* enum_type,
                               CodedOutputStream* stream,
                               bool use_lower_camel_for_enums,
+                              bool case_insensitive_enum_parsing,
                               bool ignore_unknown_values) {
   bool is_unknown_enum_value = false;
   StatusOr<int> e = data.ToEnum(enum_type, use_lower_camel_for_enums,
+                                case_insensitive_enum_parsing,
                                 ignore_unknown_values, &is_unknown_enum_value);
   if (e.ok() && !is_unknown_enum_value) {
     WireFormatLite::WriteEnum(field_number, e.ValueOrDie(), stream);
@@ -689,10 +693,10 @@
       break;
     }
     case google::protobuf::Field_Kind_TYPE_ENUM: {
-      status = WriteEnum(field.number(), data,
-                         typeinfo_->GetEnumByTypeUrl(field.type_url()),
-                         stream_.get(), use_lower_camel_for_enums_,
-                         ignore_unknown_enum_values_);
+      status = WriteEnum(
+          field.number(), data, typeinfo_->GetEnumByTypeUrl(field.type_url()),
+          stream_.get(), use_lower_camel_for_enums_,
+          case_insensitive_enum_parsing_, ignore_unknown_enum_values_);
       break;
     }
     default:  // TYPE_GROUP or TYPE_MESSAGE
diff --git a/src/google/protobuf/util/internal/proto_writer.h b/src/google/protobuf/util/internal/proto_writer.h
index 1a8df98..b67d76e 100644
--- a/src/google/protobuf/util/internal/proto_writer.h
+++ b/src/google/protobuf/util/internal/proto_writer.h
@@ -162,6 +162,10 @@
     use_lower_camel_for_enums_ = use_lower_camel_for_enums;
   }
 
+  void set_case_insensitive_enum_parsing(bool case_insensitive_enum_parsing) {
+    case_insensitive_enum_parsing_ = case_insensitive_enum_parsing;
+  }
+
  protected:
   class PROTOBUF_EXPORT ProtoElement : public BaseElement,
                                        public LocationTrackerInterface {
@@ -315,6 +319,7 @@
                                   const google::protobuf::Enum* enum_type,
                                   io::CodedOutputStream* stream,
                                   bool use_lower_camel_for_enums,
+                                  bool case_insensitive_enum_parsing,
                                   bool ignore_unknown_values);
 
   // Variables for describing the structure of the input tree:
@@ -338,6 +343,9 @@
   // field name.
   bool use_lower_camel_for_enums_;
 
+  // If true, check if enum name in UPPER_CASE matches the field name.
+  bool case_insensitive_enum_parsing_;
+
   // Variable for internal state processing:
   // element_    : the current element.
   // size_insert_: sizes of nested messages.
diff --git a/src/google/protobuf/util/internal/protostream_objectsource.cc b/src/google/protobuf/util/internal/protostream_objectsource.cc
index 55e8e4b..a11d983 100644
--- a/src/google/protobuf/util/internal/protostream_objectsource.cc
+++ b/src/google/protobuf/util/internal/protostream_objectsource.cc
@@ -783,13 +783,14 @@
 
     bool use_type_renderer = type_renderer != nullptr;
 
+    RETURN_IF_ERROR(IncrementRecursionDepth(type->name(), field_name));
     if (use_type_renderer) {
       RETURN_IF_ERROR((*type_renderer)(this, *type, field_name, ow));
     } else {
-      RETURN_IF_ERROR(IncrementRecursionDepth(type->name(), field_name));
       RETURN_IF_ERROR(WriteMessage(*type, field_name, 0, true, ow));
-      --recursion_depth_;
     }
+    --recursion_depth_;
+
     if (!stream_->ConsumedEntireMessage()) {
       return Status(util::error::INVALID_ARGUMENT,
                     "Nested protocol message not parsed in its entirety.");
diff --git a/src/google/protobuf/util/internal/protostream_objectsource.h b/src/google/protobuf/util/internal/protostream_objectsource.h
index 5ff8327..124a36a 100644
--- a/src/google/protobuf/util/internal/protostream_objectsource.h
+++ b/src/google/protobuf/util/internal/protostream_objectsource.h
@@ -155,9 +155,9 @@
       const google::protobuf::Type& type, uint32 tag) const;
 
   // Renders a field value to the ObjectWriter.
-  util::Status RenderField(const google::protobuf::Field* field,
-                             StringPiece field_name,
-                             ObjectWriter* ow) const;
+  virtual util::Status RenderField(const google::protobuf::Field* field,
+                                     StringPiece field_name,
+                                     ObjectWriter* ow) const;
 
   // Reads field value according to Field spec in 'field' and returns the read
   // value as string. This only works for primitive datatypes (no message
diff --git a/src/google/protobuf/util/internal/protostream_objectsource_test.cc b/src/google/protobuf/util/internal/protostream_objectsource_test.cc
index 5e2f86f..8a8b0c4 100644
--- a/src/google/protobuf/util/internal/protostream_objectsource_test.cc
+++ b/src/google/protobuf/util/internal/protostream_objectsource_test.cc
@@ -596,7 +596,7 @@
   }
 
   Status status = ExecuteTest(cyclic, Cyclic::descriptor());
-  EXPECT_EQ(util::error::INVALID_ARGUMENT, status.error_code());
+  EXPECT_EQ(util::error::INVALID_ARGUMENT, status.code());
 }
 
 class ProtostreamObjectSourceMapsTest : public ProtostreamObjectSourceTest {
@@ -941,7 +941,7 @@
   ow_.StartObject("");
 
   Status status = ExecuteTest(out, AnyOut::descriptor());
-  EXPECT_EQ(util::error::INTERNAL, status.error_code());
+  EXPECT_EQ(util::error::INTERNAL, status.code());
 }
 
 TEST_P(ProtostreamObjectSourceAnysTest, UnknownTypeServiceError) {
@@ -957,7 +957,7 @@
   ow_.StartObject("");
 
   Status status = ExecuteTest(out, AnyOut::descriptor());
-  EXPECT_EQ(util::error::INTERNAL, status.error_code());
+  EXPECT_EQ(util::error::INTERNAL, status.code());
 }
 
 TEST_P(ProtostreamObjectSourceAnysTest, UnknownTypeError) {
@@ -973,7 +973,7 @@
   ow_.StartObject("");
 
   Status status = ExecuteTest(out, AnyOut::descriptor());
-  EXPECT_EQ(util::error::INTERNAL, status.error_code());
+  EXPECT_EQ(util::error::INTERNAL, status.code());
 }
 
 class ProtostreamObjectSourceStructTest : public ProtostreamObjectSourceTest {
@@ -1106,7 +1106,7 @@
   ow_.StartObject("");
 
   Status status = ExecuteTest(out, TimestampDuration::descriptor());
-  EXPECT_EQ(util::error::INTERNAL, status.error_code());
+  EXPECT_EQ(util::error::INTERNAL, status.code());
 }
 
 TEST_P(ProtostreamObjectSourceTimestampTest, InvalidTimestampAboveMaxTest) {
@@ -1117,7 +1117,7 @@
   ow_.StartObject("");
 
   Status status = ExecuteTest(out, TimestampDuration::descriptor());
-  EXPECT_EQ(util::error::INTERNAL, status.error_code());
+  EXPECT_EQ(util::error::INTERNAL, status.code());
 }
 
 TEST_P(ProtostreamObjectSourceTimestampTest, InvalidDurationBelowMinTest) {
@@ -1128,7 +1128,7 @@
   ow_.StartObject("");
 
   Status status = ExecuteTest(out, TimestampDuration::descriptor());
-  EXPECT_EQ(util::error::INTERNAL, status.error_code());
+  EXPECT_EQ(util::error::INTERNAL, status.code());
 }
 
 TEST_P(ProtostreamObjectSourceTimestampTest, InvalidDurationAboveMaxTest) {
@@ -1139,7 +1139,7 @@
   ow_.StartObject("");
 
   Status status = ExecuteTest(out, TimestampDuration::descriptor());
-  EXPECT_EQ(util::error::INTERNAL, status.error_code());
+  EXPECT_EQ(util::error::INTERNAL, status.code());
 }
 
 TEST_P(ProtostreamObjectSourceTimestampTest, TimestampDurationDefaultValue) {
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.cc b/src/google/protobuf/util/internal/protostream_objectwriter.cc
index f2f0f3f..9f0e208 100644
--- a/src/google/protobuf/util/internal/protostream_objectwriter.cc
+++ b/src/google/protobuf/util/internal/protostream_objectwriter.cc
@@ -73,6 +73,7 @@
   set_ignore_unknown_fields(options_.ignore_unknown_fields);
   set_ignore_unknown_enum_values(options_.ignore_unknown_enum_values);
   set_use_lower_camel_for_enums(options_.use_lower_camel_for_enums);
+  set_case_insensitive_enum_parsing(options_.case_insensitive_enum_parsing);
 }
 
 ProtoStreamObjectWriter::ProtoStreamObjectWriter(
@@ -85,6 +86,7 @@
       options_(options) {
   set_ignore_unknown_fields(options_.ignore_unknown_fields);
   set_use_lower_camel_for_enums(options.use_lower_camel_for_enums);
+  set_case_insensitive_enum_parsing(options_.case_insensitive_enum_parsing);
 }
 
 ProtoStreamObjectWriter::ProtoStreamObjectWriter(
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.h b/src/google/protobuf/util/internal/protostream_objectwriter.h
index bdb70c7..8c1af58 100644
--- a/src/google/protobuf/util/internal/protostream_objectwriter.h
+++ b/src/google/protobuf/util/internal/protostream_objectwriter.h
@@ -104,6 +104,9 @@
     // the field name.
     bool use_lower_camel_for_enums;
 
+    // If true, check if enum name in UPPER_CASE matches the field name.
+    bool case_insensitive_enum_parsing;
+
     // If true, skips rendering the map entry if map value is null unless the
     // value type is google.protobuf.NullType.
     bool ignore_null_value_map_entry;
@@ -113,6 +116,8 @@
           ignore_unknown_fields(false),
           ignore_unknown_enum_values(false),
           use_lower_camel_for_enums(false),
+          // TODO(haon): Change this to false by default.
+          case_insensitive_enum_parsing(true),
           ignore_null_value_map_entry(false) {}
 
     // Default instance of Options with all options set to defaults.
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter_test.cc b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc
index c464696..da24dd5 100644
--- a/src/google/protobuf/util/internal/protostream_objectwriter_test.cc
+++ b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc
@@ -301,6 +301,65 @@
   CheckOutput(book);
 }
 
+TEST_P(ProtoStreamObjectWriterTest, EnumValuesWithDifferentCaseIsRejected) {
+  Book book;
+  book.set_title("Some Book");
+  Author* robert = book.mutable_author();
+  robert->set_name("robert");
+
+  options_.case_insensitive_enum_parsing = false;
+  ResetProtoWriter();
+
+  ow_->StartObject("")
+      ->RenderString("title", "Some Book")
+      ->RenderString("type", "action_and_adventure")
+      ->StartObject("author")
+      ->RenderString("name", "robert")
+      ->EndObject()
+      ->EndObject();
+  CheckOutput(book);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, EnumValuesWithSameCaseIsAccepted) {
+  Book book;
+  book.set_title("Some Book");
+  book.set_type(google::protobuf::testing::Book_Type_ACTION_AND_ADVENTURE);
+  Author* robert = book.mutable_author();
+  robert->set_name("robert");
+
+  options_.case_insensitive_enum_parsing = false;
+  ResetProtoWriter();
+
+  ow_->StartObject("")
+      ->RenderString("title", "Some Book")
+      ->RenderString("type", "ACTION_AND_ADVENTURE")
+      ->StartObject("author")
+      ->RenderString("name", "robert")
+      ->EndObject()
+      ->EndObject();
+  CheckOutput(book);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, EnumValuesWithDifferentCaseIsAccepted) {
+  Book book;
+  book.set_title("Some Book");
+  book.set_type(google::protobuf::testing::Book_Type_ACTION_AND_ADVENTURE);
+  Author* robert = book.mutable_author();
+  robert->set_name("robert");
+
+  options_.case_insensitive_enum_parsing = true;
+  ResetProtoWriter();
+
+  ow_->StartObject("")
+      ->RenderString("title", "Some Book")
+      ->RenderString("type", "action_AND_adventure")
+      ->StartObject("author")
+      ->RenderString("name", "robert")
+      ->EndObject()
+      ->EndObject();
+  CheckOutput(book);
+}
+
 TEST_P(ProtoStreamObjectWriterTest, EnumValuesWithoutUnderscoreAreAccepted) {
   Book book;
   book.set_title("Some Book");
@@ -342,6 +401,28 @@
 }
 
 TEST_P(ProtoStreamObjectWriterTest,
+       EnumValuesInCamelCaseRemoveDashAndUnderscoreAreAccepted) {
+  Book book;
+  book.set_title("Some Book");
+  book.set_type(google::protobuf::testing::Book_Type_ACTION_AND_ADVENTURE);
+  Author* robert = book.mutable_author();
+  robert->set_name("robert");
+
+  options_.use_lower_camel_for_enums = true;
+  options_.case_insensitive_enum_parsing = false;
+  ResetProtoWriter();
+
+  ow_->StartObject("")
+      ->RenderString("title", "Some Book")
+      ->RenderString("type", "action-And_Adventure")
+      ->StartObject("author")
+      ->RenderString("name", "robert")
+      ->EndObject()
+      ->EndObject();
+  CheckOutput(book);
+}
+
+TEST_P(ProtoStreamObjectWriterTest,
        EnumValuesInCamelCaseWithNameNotUppercaseAreAccepted) {
   Book book;
   book.set_title("Some Book");
diff --git a/src/google/protobuf/util/json_util.cc b/src/google/protobuf/util/json_util.cc
index 8c0b4eb..1fcee63 100644
--- a/src/google/protobuf/util/json_util.cc
+++ b/src/google/protobuf/util/json_util.cc
@@ -129,9 +129,9 @@
 
   util::Status GetStatus() { return status_; }
 
-  void InvalidName(const converter::LocationTrackerInterface& loc,
-                   StringPiece unknown_name,
-                   StringPiece message) override {
+  virtual void InvalidName(const converter::LocationTrackerInterface& loc,
+                           StringPiece unknown_name,
+                           StringPiece message) {
     string loc_string = GetLocString(loc);
     if (!loc_string.empty()) {
       loc_string.append(" ");
@@ -141,17 +141,17 @@
                        StrCat(loc_string, unknown_name, ": ", message));
   }
 
-  void InvalidValue(const converter::LocationTrackerInterface& loc,
-                    StringPiece type_name,
-                    StringPiece value) override {
+  virtual void InvalidValue(const converter::LocationTrackerInterface& loc,
+                            StringPiece type_name,
+                            StringPiece value) {
     status_ = util::Status(
         util::error::INVALID_ARGUMENT,
         StrCat(GetLocString(loc), ": invalid value ", string(value),
                      " for type ", string(type_name)));
   }
 
-  void MissingField(const converter::LocationTrackerInterface& loc,
-                    StringPiece missing_name) override {
+  virtual void MissingField(const converter::LocationTrackerInterface& loc,
+                            StringPiece missing_name) {
     status_ = util::Status(util::error::INVALID_ARGUMENT,
                              StrCat(GetLocString(loc), ": missing field ",
                                           string(missing_name)));
@@ -186,6 +186,8 @@
   proto_writer_options.ignore_unknown_fields = options.ignore_unknown_fields;
   proto_writer_options.ignore_unknown_enum_values =
       options.ignore_unknown_fields;
+  proto_writer_options.case_insensitive_enum_parsing =
+      options.case_insensitive_enum_parsing;
   converter::ProtoStreamObjectWriter proto_writer(resolver, type, &sink,
                                                   &listener,
                                                   proto_writer_options);
diff --git a/src/google/protobuf/util/json_util.h b/src/google/protobuf/util/json_util.h
index 015ca58..2e40615 100644
--- a/src/google/protobuf/util/json_util.h
+++ b/src/google/protobuf/util/json_util.h
@@ -52,7 +52,17 @@
   // Whether to ignore unknown JSON fields during parsing
   bool ignore_unknown_fields;
 
-  JsonParseOptions() : ignore_unknown_fields(false) {}
+  // If true, when a lowercase enum value fails to parse, try convert it to
+  // UPPER_CASE and see if it matches a valid enum.
+  // WARNING: This option exists only to preserve legacy behavior. Avoid using
+  // this option. If your enum needs to support different casing, consider using
+  // allow_alias instead.
+  bool case_insensitive_enum_parsing;
+
+  JsonParseOptions()
+      : ignore_unknown_fields(false),
+        // TODO(haon): Change this to false by default.
+        case_insensitive_enum_parsing(true) {}
 };
 
 struct JsonPrintOptions {
diff --git a/src/google/protobuf/util/json_util_test.cc b/src/google/protobuf/util/json_util_test.cc
index 23da45b..0f5b396 100644
--- a/src/google/protobuf/util/json_util_test.cc
+++ b/src/google/protobuf/util/json_util_test.cc
@@ -454,6 +454,44 @@
   }
 }
 
+TEST_F(JsonUtilTest, TestParsingEnumIgnoreCase) {
+  TestMessage m;
+  {
+    JsonParseOptions options;
+    string input =
+        "{\n"
+        "  \"enum_value\":\"bar\"\n"
+        "}";
+    m.set_enum_value(proto3::FOO);
+    EXPECT_TRUE(FromJson(input, &m, options));
+    // Default behavior is case-insensitive.
+    // TODO(haon): Change the default behavior to case-sensitive.
+    ASSERT_EQ(proto3::BAR, m.enum_value());
+  }
+  {
+    JsonParseOptions options;
+    options.case_insensitive_enum_parsing = false;
+    string input =
+        "{\n"
+        "  \"enum_value\":\"bar\"\n"
+        "}";
+    m.set_enum_value(proto3::FOO);
+    EXPECT_FALSE(FromJson(input, &m, options));
+    ASSERT_EQ(proto3::FOO, m.enum_value());  // Keep previous value
+  }
+  {
+    JsonParseOptions options;
+    options.case_insensitive_enum_parsing = true;
+    string input =
+        "{\n"
+        "  \"enum_value\":\"bar\"\n"
+        "}";
+    m.set_enum_value(proto3::FOO);
+    EXPECT_TRUE(FromJson(input, &m, options));
+    ASSERT_EQ(proto3::BAR, m.enum_value());
+  }
+}
+
 typedef std::pair<char*, int> Segment;
 // A ZeroCopyOutputStream that writes to multiple buffers.
 class SegmentedZeroCopyOutputStream : public io::ZeroCopyOutputStream {
@@ -594,7 +632,7 @@
   delete resolver;
 
   EXPECT_FALSE(result_status.ok());
-  EXPECT_EQ(result_status.error_code(),
+  EXPECT_EQ(result_status.code(),
             util::error::INVALID_ARGUMENT);
 }
 
diff --git a/src/google/protobuf/util/message_differencer.cc b/src/google/protobuf/util/message_differencer.cc
index 3e00d07..d1183c0 100644
--- a/src/google/protobuf/util/message_differencer.cc
+++ b/src/google/protobuf/util/message_differencer.cc
@@ -1603,10 +1603,10 @@
       success = success && (match_count == count1);
     } else {
       int start_offset = 0;
+      const bool is_treated_as_smart_set = IsTreatedAsSmartSet(repeated_field);
       // If the two repeated fields are treated as sets, optimize for the case
       // where both start with same items stored in the same order.
-      if (IsTreatedAsSet(repeated_field) ||
-          IsTreatedAsSmartSet(repeated_field) ||
+      if (IsTreatedAsSet(repeated_field) || is_treated_as_smart_set ||
           IsTreatedAsSmartList(repeated_field)) {
         start_offset = std::min(count1, count2);
         for (int i = 0; i < count1 && i < count2; i++) {
@@ -1623,16 +1623,16 @@
       for (int i = start_offset; i < count1; ++i) {
         // Indicates any matched elements for this repeated field.
         bool match = false;
+        int matched_j = -1;
 
         for (int j = start_offset; j < count2; j++) {
           if (match_list2->at(j) != -1) {
-            if (!IsTreatedAsSmartSet(repeated_field) ||
-                num_diffs_list1[i] == 0) {
+            if (!is_treated_as_smart_set || num_diffs_list1[i] == 0) {
               continue;
             }
           }
 
-          if (IsTreatedAsSmartSet(repeated_field)) {
+          if (is_treated_as_smart_set) {
             num_diffs_reporter.Reset();
             match = IsMatch(repeated_field, key_comparator,
                             &message1, &message2, parent_fields,
@@ -1643,7 +1643,7 @@
                             nullptr, i, j);
           }
 
-          if (IsTreatedAsSmartSet(repeated_field)) {
+          if (is_treated_as_smart_set) {
             if (match) {
               num_diffs_list1[i] = 0;
             } else if (repeated_field->cpp_type() ==
@@ -1658,14 +1658,24 @@
           }
 
           if (match) {
-            match_list1->at(i) = j;
-            match_list2->at(j) = i;
-            if (!IsTreatedAsSmartSet(repeated_field)
-                || num_diffs_list1[i] == 0) {
+            matched_j = j;
+            if (!is_treated_as_smart_set || num_diffs_list1[i] == 0) {
               break;
             }
           }
         }
+
+        match = (matched_j != -1);
+        if (match) {
+          if (is_treated_as_smart_set &&
+              match_list2->at(matched_j) != -1) {
+            // This is to revert the previously matched index in list2.
+            match_list1->at(match_list2->at(matched_j)) = -1;
+            match = false;
+          }
+          match_list1->at(i) = matched_j;
+          match_list2->at(matched_j) = i;
+        }
         if (!match && reporter == NULL) return false;
         success = success && match;
       }
diff --git a/src/google/protobuf/util/message_differencer.h b/src/google/protobuf/util/message_differencer.h
index 96d0f0c..f6d7bf1 100644
--- a/src/google/protobuf/util/message_differencer.h
+++ b/src/google/protobuf/util/message_differencer.h
@@ -115,8 +115,9 @@
   // Determines whether the supplied messages are equal. Equality is defined as
   // all fields within the two messages being set to the same value. Primitive
   // fields and strings are compared by value while embedded messages/groups
-  // are compared as if via a recursive call. Use IgnoreField() and Compare()
-  // if some fields should be ignored in the comparison.
+  // are compared as if via a recursive call. Use Compare() with IgnoreField()
+  // if some fields should be ignored in the comparison. Use Compare() with
+  // TreatAsSet() if there are repeated fields where ordering does not matter.
   //
   // This method REQUIRES that the two messages have the same
   // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
diff --git a/src/google/protobuf/util/message_differencer_unittest.cc b/src/google/protobuf/util/message_differencer_unittest.cc
index 24c05c6..9ff9d24 100644
--- a/src/google/protobuf/util/message_differencer_unittest.cc
+++ b/src/google/protobuf/util/message_differencer_unittest.cc
@@ -1155,6 +1155,67 @@
             "modified: rm[2].b -> rm[0].b: 3 -> 0\n", diff_report);
 }
 
+TEST(MessageDifferencerTest, RepeatedFieldSmartSet_MultipleMatches) {
+  // Create the testing protos
+  protobuf_unittest::TestDiffMessage msg1;
+  protobuf_unittest::TestDiffMessage msg2;
+  protobuf_unittest::TestField elem1_1, elem2_1, elem3_1;
+  protobuf_unittest::TestField elem2_2, elem3_2;
+
+  // Only one field is different for each pair of elememts
+  elem1_1.set_a(1);
+  elem1_1.set_b(1);
+  elem1_1.set_c(1);
+  elem2_1.set_a(2);  elem2_2.set_a(2);
+  elem2_1.set_b(2);  elem2_2.set_b(0);
+  elem2_1.set_c(2);  elem2_2.set_c(2);
+  elem3_1.set_a(3);  elem3_2.set_a(3);
+  elem3_1.set_b(3);  elem3_2.set_b(0);
+  elem3_1.set_c(3);  elem3_2.set_c(3);
+
+
+
+  // In this testcase, elem1_1 will match with elem2_2 first and then get
+  // reverted because elem2_1 matches with elem2_2 later.
+  *msg1.add_rm() = elem1_1;
+  *msg1.add_rm() = elem2_1;
+  *msg1.add_rm() = elem3_1;
+  *msg2.add_rm() = elem2_2;
+  *msg2.add_rm() = elem3_2;
+
+  string diff_report;
+  util::MessageDifferencer differencer;
+  differencer.ReportDifferencesToString(&diff_report);
+  differencer.set_repeated_field_comparison(
+      util::MessageDifferencer::AS_SMART_SET);
+  EXPECT_FALSE(differencer.Compare(msg1, msg2));
+  EXPECT_EQ("modified: rm[1].b -> rm[0].b: 2 -> 0\n"
+            "modified: rm[2].b -> rm[1].b: 3 -> 0\n"
+            "deleted: rm[0]: { c: 1 a: 1 b: 1 }\n", diff_report);
+}
+
+TEST(MessageDifferencerTest, RepeatedFieldSmartSet_MultipleMatchesNoReporter) {
+  protobuf_unittest::TestDiffMessage msg1;
+  protobuf_unittest::TestDiffMessage msg2;
+  protobuf_unittest::TestField elem1, elem2, elem3, elem4;
+  elem1.set_a(1);
+  elem2.set_a(2);
+  elem3.set_a(3);
+  elem4.set_a(4);
+
+  *msg1.add_rm() = elem1;
+  *msg1.add_rm() = elem2;
+  *msg1.add_rm() = elem3;
+  *msg2.add_rm() = elem2;
+  *msg2.add_rm() = elem3;
+  *msg2.add_rm() = elem4;
+
+  util::MessageDifferencer differencer;
+  differencer.set_repeated_field_comparison(
+      util::MessageDifferencer::AS_SMART_SET);
+  EXPECT_FALSE(differencer.Compare(msg1, msg2));
+}
+
 TEST(MessageDifferencerTest, RepeatedFieldSmartSet_NonMessageTypeTest) {
   // Create the testing protos
   protobuf_unittest::TestDiffMessage msg1;
diff --git a/src/google/protobuf/wire_format.cc b/src/google/protobuf/wire_format.cc
index 0342a10..1ddc1d5 100644
--- a/src/google/protobuf/wire_format.cc
+++ b/src/google/protobuf/wire_format.cc
@@ -907,8 +907,8 @@
   // internal state and existing references that came from map reflection remain
   // valid for both reading and writing.
   if (field->is_map()) {
-    MapFieldBase* map_field =
-        message_reflection->MapData(const_cast<Message*>(&message), field);
+    const MapFieldBase* map_field =
+        message_reflection->GetMapData(message, field);
     if (map_field->IsMapValid()) {
       if (output->IsSerializationDeterministic()) {
         std::vector<MapKey> sorted_key_list =
@@ -1243,8 +1243,8 @@
   size_t data_size = 0;
 
   if (field->is_map()) {
-    MapFieldBase* map_field =
-        message_reflection->MapData(const_cast<Message*>(&message), field);
+    const MapFieldBase* map_field =
+        message_reflection->GetMapData(message, field);
     if (map_field->IsMapValid()) {
       MapIterator iter(const_cast<Message*>(&message), field);
       MapIterator end(const_cast<Message*>(&message), field);
diff --git a/src/google/protobuf/wire_format_lite.cc b/src/google/protobuf/wire_format_lite.cc
index a393f36..14ee5a3 100644
--- a/src/google/protobuf/wire_format_lite.cc
+++ b/src/google/protobuf/wire_format_lite.cc
@@ -550,19 +550,25 @@
   value.SerializeWithCachedSizes(output);
 }
 
+void WireFormatLite::WriteSubMessageMaybeToArray(
+    int size, const MessageLite& value, io::CodedOutputStream* output) {
+  if (!output->IsSerializationDeterministic()) {
+    uint8* target = output->GetDirectBufferForNBytesAndAdvance(size);
+    if (target != nullptr) {
+      uint8* end = value.InternalSerializeWithCachedSizesToArray(target);
+      GOOGLE_DCHECK_EQ(end - target, size);
+      return;
+    }
+  }
+  value.SerializeWithCachedSizes(output);
+}
+
 void WireFormatLite::WriteGroupMaybeToArray(int field_number,
                                             const MessageLite& value,
                                             io::CodedOutputStream* output) {
   WriteTag(field_number, WIRETYPE_START_GROUP, output);
   const int size = value.GetCachedSize();
-  uint8* target = output->GetDirectBufferForNBytesAndAdvance(size);
-  if (target != NULL) {
-    uint8* end = value.InternalSerializeWithCachedSizesToArray(
-        output->IsSerializationDeterministic(), target);
-    GOOGLE_DCHECK_EQ(end - target, size);
-  } else {
-    value.SerializeWithCachedSizes(output);
-  }
+  WriteSubMessageMaybeToArray(size, value, output);
   WriteTag(field_number, WIRETYPE_END_GROUP, output);
 }
 
@@ -572,14 +578,7 @@
   WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
   const int size = value.GetCachedSize();
   output->WriteVarint32(size);
-  uint8* target = output->GetDirectBufferForNBytesAndAdvance(size);
-  if (target != NULL) {
-    uint8* end = value.InternalSerializeWithCachedSizesToArray(
-        output->IsSerializationDeterministic(), target);
-    GOOGLE_DCHECK_EQ(end - target, size);
-  } else {
-    value.SerializeWithCachedSizes(output);
-  }
+  WriteSubMessageMaybeToArray(size, value, output);
 }
 
 PROTOBUF_ALWAYS_INLINE static bool ReadBytesToString(
diff --git a/src/google/protobuf/wire_format_lite.h b/src/google/protobuf/wire_format_lite.h
index f576875..ed1410e 100644
--- a/src/google/protobuf/wire_format_lite.h
+++ b/src/google/protobuf/wire_format_lite.h
@@ -622,12 +622,10 @@
   template <typename MessageType>
   INL static uint8* InternalWriteGroupToArray(int field_number,
                                               const MessageType& value,
-                                              bool deterministic,
                                               uint8* target);
   template <typename MessageType>
   INL static uint8* InternalWriteMessageToArray(int field_number,
                                                 const MessageType& value,
-                                                bool deterministic,
                                                 uint8* target);
 
   // Like above, but de-virtualize the call to SerializeWithCachedSizes().  The
@@ -636,23 +634,21 @@
   template <typename MessageType>
   INL static uint8* InternalWriteGroupNoVirtualToArray(int field_number,
                                                        const MessageType& value,
-                                                       bool deterministic,
                                                        uint8* target);
   template <typename MessageType>
   INL static uint8* InternalWriteMessageNoVirtualToArray(
-      int field_number, const MessageType& value, bool deterministic,
-      uint8* target);
+      int field_number, const MessageType& value, uint8* target);
 
   // For backward-compatibility, the last four methods also have versions
   // that are non-deterministic always.
   INL static uint8* WriteGroupToArray(int field_number,
                                       const MessageLite& value, uint8* target) {
-    return InternalWriteGroupToArray(field_number, value, false, target);
+    return InternalWriteGroupToArray(field_number, value, target);
   }
   INL static uint8* WriteMessageToArray(int field_number,
                                         const MessageLite& value,
                                         uint8* target) {
-    return InternalWriteMessageToArray(field_number, value, false, target);
+    return InternalWriteMessageToArray(field_number, value, target);
   }
   template <typename MessageType>
   INL static uint8* WriteGroupNoVirtualToArray(int field_number,
@@ -736,6 +732,8 @@
 
   static const CppType kFieldTypeToCppTypeMap[];
   static const WireFormatLite::WireType kWireTypeForFieldType[];
+  static void WriteSubMessageMaybeToArray(int size, const MessageLite& value,
+                                          io::CodedOutputStream* output);
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(WireFormatLite);
 };
diff --git a/src/google/protobuf/wire_format_lite_inl.h b/src/google/protobuf/wire_format_lite_inl.h
index 44c4b5c..266b1e1 100644
--- a/src/google/protobuf/wire_format_lite_inl.h
+++ b/src/google/protobuf/wire_format_lite_inl.h
@@ -889,46 +889,44 @@
 }
 
 
-template<typename MessageType>
+template <typename MessageType>
 inline uint8* WireFormatLite::InternalWriteGroupToArray(
-    int field_number, const MessageType& value, bool deterministic,
-    uint8* target) {
+    int field_number, const MessageType& value, uint8* target) {
   target = WriteTagToArray(field_number, WIRETYPE_START_GROUP, target);
-  target = value.InternalSerializeWithCachedSizesToArray(deterministic, target);
+  target = value.InternalSerializeWithCachedSizesToArray(target);
   return WriteTagToArray(field_number, WIRETYPE_END_GROUP, target);
 }
-template<typename MessageType>
+template <typename MessageType>
 inline uint8* WireFormatLite::InternalWriteMessageToArray(
-    int field_number, const MessageType& value, bool deterministic,
-    uint8* target) {
+    int field_number, const MessageType& value, uint8* target) {
   target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target);
   target = io::CodedOutputStream::WriteVarint32ToArray(
     static_cast<uint32>(value.GetCachedSize()), target);
-  return value.InternalSerializeWithCachedSizesToArray(deterministic, target);
+  return value.InternalSerializeWithCachedSizesToArray(target);
 }
 
 // See comment on ReadGroupNoVirtual to understand the need for this template
 // parameter name.
-template<typename MessageType_WorkAroundCppLookupDefect>
+template <typename MessageType_WorkAroundCppLookupDefect>
 inline uint8* WireFormatLite::InternalWriteGroupNoVirtualToArray(
     int field_number, const MessageType_WorkAroundCppLookupDefect& value,
-    bool deterministic, uint8* target) {
+    uint8* target) {
   target = WriteTagToArray(field_number, WIRETYPE_START_GROUP, target);
   target = value.MessageType_WorkAroundCppLookupDefect::
-      InternalSerializeWithCachedSizesToArray(deterministic, target);
+               InternalSerializeWithCachedSizesToArray(target);
   return WriteTagToArray(field_number, WIRETYPE_END_GROUP, target);
 }
-template<typename MessageType_WorkAroundCppLookupDefect>
+template <typename MessageType_WorkAroundCppLookupDefect>
 inline uint8* WireFormatLite::InternalWriteMessageNoVirtualToArray(
     int field_number, const MessageType_WorkAroundCppLookupDefect& value,
-    bool deterministic, uint8* target) {
+    uint8* target) {
   target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target);
   target = io::CodedOutputStream::WriteVarint32ToArray(
         static_cast<uint32>(
             value.MessageType_WorkAroundCppLookupDefect::GetCachedSize()),
         target);
   return value.MessageType_WorkAroundCppLookupDefect::
-      InternalSerializeWithCachedSizesToArray(deterministic, target);
+      InternalSerializeWithCachedSizesToArray(target);
 }
 
 // ===================================================================
diff --git a/src/google/protobuf/wrappers.pb.cc b/src/google/protobuf/wrappers.pb.cc
index fcfbc93..0d6e413 100644
--- a/src/google/protobuf/wrappers.pb.cc
+++ b/src/google/protobuf/wrappers.pb.cc
@@ -396,7 +396,7 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // double value = 1;
@@ -409,7 +409,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -423,13 +423,6 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
-  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool DoubleValue::MergePartialFromCodedStream(
@@ -495,8 +488,7 @@
 }
 
 ::google::protobuf::uint8* DoubleValue::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.DoubleValue)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -693,7 +685,7 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // float value = 1;
@@ -706,7 +698,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -720,13 +712,6 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
-  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool FloatValue::MergePartialFromCodedStream(
@@ -792,8 +777,7 @@
 }
 
 ::google::protobuf::uint8* FloatValue::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FloatValue)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -990,21 +974,21 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // int64 value = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ::google::protobuf::int64 value = val;
         msg->set_value(value);
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -1018,13 +1002,6 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
-  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool Int64Value::MergePartialFromCodedStream(
@@ -1090,8 +1067,7 @@
 }
 
 ::google::protobuf::uint8* Int64Value::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Int64Value)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -1290,21 +1266,21 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // uint64 value = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ::google::protobuf::uint64 value = val;
         msg->set_value(value);
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -1318,13 +1294,6 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
-  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool UInt64Value::MergePartialFromCodedStream(
@@ -1390,8 +1359,7 @@
 }
 
 ::google::protobuf::uint8* UInt64Value::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.UInt64Value)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -1590,21 +1558,21 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // int32 value = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ::google::protobuf::int32 value = val;
         msg->set_value(value);
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -1618,13 +1586,6 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
-  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool Int32Value::MergePartialFromCodedStream(
@@ -1690,8 +1651,7 @@
 }
 
 ::google::protobuf::uint8* Int32Value::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Int32Value)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -1890,21 +1850,21 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // uint32 value = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ::google::protobuf::uint32 value = val;
         msg->set_value(value);
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -1918,13 +1878,6 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
-  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool UInt32Value::MergePartialFromCodedStream(
@@ -1990,8 +1943,7 @@
 }
 
 ::google::protobuf::uint8* UInt32Value::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.UInt32Value)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -2190,21 +2142,21 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // bool value = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
         ::google::protobuf::uint64 val;
-        ptr = Varint::Parse64(ptr, &val);
+        ptr = ::google::protobuf::io::Parse64(ptr, &val);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         bool value = val;
         msg->set_value(value);
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -2218,13 +2170,6 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
-  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool BoolValue::MergePartialFromCodedStream(
@@ -2290,8 +2235,7 @@
 }
 
 ::google::protobuf::uint8* BoolValue::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.BoolValue)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -2495,13 +2439,13 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // string value = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.StringValue.value");
         auto str = msg->mutable_value();
@@ -2518,7 +2462,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -2532,13 +2476,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool StringValue::MergePartialFromCodedStream(
@@ -2611,8 +2551,7 @@
 }
 
 ::google::protobuf::uint8* StringValue::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.StringValue)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -2825,13 +2764,13 @@
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ptr = Varint::Parse32Inline(ptr, &tag);
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
       // bytes value = 1;
       case 1: {
         if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
-        ptr = Varint::Parse32Inline(ptr, &size);
+        ptr = ::google::protobuf::io::Parse32(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         auto str = msg->mutable_value();
         if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
@@ -2847,7 +2786,7 @@
         break;
       }
       default: {
-      handle_unusual: (void)&&handle_unusual;
+      handle_unusual:
         if ((tag & 7) == 4 || tag == 0) {
           ctx->EndGroup(tag);
           return ptr;
@@ -2861,13 +2800,9 @@
     }  // switch
   }  // while
   return ptr;
-len_delim_till_end: (void)&&len_delim_till_end;
+len_delim_till_end:
   return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
-                                 {parser_till_end, object}, size);
-group_continues: (void)&&group_continues;
-  GOOGLE_DCHECK(ptr >= end);
-  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
-  return ptr;
+                               {parser_till_end, object}, size);
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
 bool BytesValue::MergePartialFromCodedStream(
@@ -2932,8 +2867,7 @@
 }
 
 ::google::protobuf::uint8* BytesValue::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  (void)deterministic; // Unused
+    ::google::protobuf::uint8* target) const {
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.BytesValue)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
diff --git a/src/google/protobuf/wrappers.pb.h b/src/google/protobuf/wrappers.pb.h
index 19c248d..48559c2 100644
--- a/src/google/protobuf/wrappers.pb.h
+++ b/src/google/protobuf/wrappers.pb.h
@@ -171,7 +171,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -297,7 +297,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -423,7 +423,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -549,7 +549,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -675,7 +675,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -801,7 +801,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -927,7 +927,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -1053,7 +1053,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
@@ -1196,7 +1196,7 @@
   void SerializeWithCachedSizes(
       ::google::protobuf::io::CodedOutputStream* output) const final;
   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const final;
+      ::google::protobuf::uint8* target) const final;
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private: