Submit recent changes from internal branch. See CHANGES.txt for more details.
diff --git a/CHANGES.txt b/CHANGES.txt
index 11b332e..6d1932b 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,3 +1,66 @@
+2010-11-01 version 2.4.0:
+
+  General
+  * The RPC (cc|java|py)_generic_services default value is now false instead of
+    true.
+  * Custom options can have aggregate types. For example,
+      message MyOption {
+        optional string comment = 1;
+        optional string author = 2;
+      }
+      extend google.protobuf.FieldOptions {
+        optional MyOption myoption = 12345;
+      }
+    This option can now be set as follows:
+      message SomeType {
+        optional int32 field = 1 [(myoption) = { comment:'x' author:'y' }];
+      }
+
+  C++
+  * Various speed and code size optimizations.
+  * Added a release_foo() method on string and message fields.
+  * Fixed gzip_output_stream sub-stream handling.
+
+  Java
+  * Builders now maintain sub-builders for sub-messages. Use getFooBuilder() to
+    get the builder for the sub-message "foo". This allows you to repeatedly
+    modify deeply-nested sub-messages without rebuilding them.
+  * Builder.build() no longer invalidates the Builder for generated messages
+    (You may continue to modify it and then build another message).
+  * Code generator will generate efficient equals() and hashCode()
+    implementations if new option java_generate_equals_and_hash is enabled.
+    (Otherwise, reflection-based implementations are used.)
+  * Generated messages now implement Serializable.
+  * Fields with [deprecated=true] will be marked with @Deprecated in Java.
+  * Added lazy conversion of UTF-8 encoded strings to String objects to improve
+    performance.
+  * Various optimizations.
+  * Enum value can be accessed directly, instead of calling getNumber() on the
+    enum member.
+  * For each enum value, an integer constant is also generated with the suffix
+    _VALUE.
+
+  Python
+  * Added an experimental  C++ implementation for Python messages via a Python
+    extension. Implementation type is controlled by an environment variable
+    PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION (valid values: "cpp" and "python")
+    The default value is currently "python" but will be changed to "cpp" in
+    future release.
+  * Improved performance on message instantiation significantly.
+    Most of the work on message instantiation is done just once per message
+    class, instead of once per message instance.
+  * Improved performance on text message parsing.
+  * Allow add() to forward keyword arguments to the concrete class.
+      E.g. instead of
+        item = repeated_field.add()
+        item.foo = bar
+        item.baz = quux
+      You can do:
+        repeated_field.add(foo=bar, baz=quux)
+  * Added a sort() interface to the BaseContainer.
+  * Added an extend() method to repeated composite fields.
+  * Added UTF8 debug string support.
+
 2010-01-08 version 2.3.0:
 
   General
diff --git a/Makefile.am b/Makefile.am
index b65daee..9b960fc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -83,33 +83,57 @@
   java/src/main/java/com/google/protobuf/GeneratedMessageLite.java           \
   java/src/main/java/com/google/protobuf/Internal.java                       \
   java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java \
+  java/src/main/java/com/google/protobuf/LazyStringArrayList.java            \
+  java/src/main/java/com/google/protobuf/LazyStringList.java                 \
   java/src/main/java/com/google/protobuf/Message.java                        \
   java/src/main/java/com/google/protobuf/MessageLite.java                    \
+  java/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java           \
+  java/src/main/java/com/google/protobuf/MessageOrBuilder.java               \
   java/src/main/java/com/google/protobuf/ProtocolMessageEnum.java            \
+  java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java           \
   java/src/main/java/com/google/protobuf/RpcCallback.java                    \
   java/src/main/java/com/google/protobuf/RpcChannel.java                     \
   java/src/main/java/com/google/protobuf/RpcController.java                  \
   java/src/main/java/com/google/protobuf/RpcUtil.java                        \
   java/src/main/java/com/google/protobuf/Service.java                        \
   java/src/main/java/com/google/protobuf/ServiceException.java               \
+  java/src/main/java/com/google/protobuf/SingleFieldBuilder.java             \
+  java/src/main/java/com/google/protobuf/SmallSortedMap.java                 \
   java/src/main/java/com/google/protobuf/TextFormat.java                     \
   java/src/main/java/com/google/protobuf/UninitializedMessageException.java  \
   java/src/main/java/com/google/protobuf/UnknownFieldSet.java                \
+  java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java     \
   java/src/main/java/com/google/protobuf/WireFormat.java                     \
   java/src/test/java/com/google/protobuf/AbstractMessageTest.java            \
   java/src/test/java/com/google/protobuf/CodedInputStreamTest.java           \
   java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java          \
+  java/src/test/java/com/google/protobuf/DeprecatedFieldTest.java            \
   java/src/test/java/com/google/protobuf/DescriptorsTest.java                \
   java/src/test/java/com/google/protobuf/DynamicMessageTest.java             \
+  java/src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java       \
   java/src/test/java/com/google/protobuf/GeneratedMessageTest.java           \
+  java/src/test/java/com/google/protobuf/LazyStringArrayListTest.java        \
+  java/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java         \
   java/src/test/java/com/google/protobuf/LiteTest.java                       \
   java/src/test/java/com/google/protobuf/MessageTest.java                    \
+  java/src/test/java/com/google/protobuf/NestedBuildersTest.java             \
+  java/src/test/java/com/google/protobuf/RepeatedFieldBuilderTest.java       \
   java/src/test/java/com/google/protobuf/ServiceTest.java                    \
+  java/src/test/java/com/google/protobuf/SingleFieldBuilderTest.java         \
+  java/src/test/java/com/google/protobuf/SmallSortedMapTest.java             \
+  java/src/test/java/com/google/protobuf/TestBadIdentifiers.java             \
   java/src/test/java/com/google/protobuf/TestUtil.java                       \
   java/src/test/java/com/google/protobuf/TextFormatTest.java                 \
   java/src/test/java/com/google/protobuf/UnknownFieldSetTest.java            \
+  java/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java \
   java/src/test/java/com/google/protobuf/WireFormatTest.java                 \
   java/src/test/java/com/google/protobuf/multiple_files_test.proto           \
+  java/src/test/java/com/google/protobuf/nested_builders_test.proto          \
+  java/src/test/java/com/google/protobuf/nested_extension.proto              \
+  java/src/test/java/com/google/protobuf/nested_extension_lite.proto         \
+  java/src/test/java/com/google/protobuf/non_nested_extension.proto          \
+  java/src/test/java/com/google/protobuf/non_nested_extension_lite.proto     \
+  java/src/test/java/com/google/protobuf/test_bad_identifiers.proto          \
   java/pom.xml                                                               \
   java/README.txt                                                            \
   python/google/protobuf/internal/generator_test.py                          \
@@ -121,6 +145,9 @@
   python/google/protobuf/internal/message_test.py                            \
   python/google/protobuf/internal/more_extensions.proto                      \
   python/google/protobuf/internal/more_messages.proto                        \
+  python/google/protobuf/internal/python_message.py                          \
+  python/google/protobuf/internal/cpp_message.py                             \
+  python/google/protobuf/internal/api_implementation.py                      \
   python/google/protobuf/internal/reflection_test.py                         \
   python/google/protobuf/internal/service_reflection_test.py                 \
   python/google/protobuf/internal/test_util.py                               \
@@ -129,6 +156,11 @@
   python/google/protobuf/internal/wire_format.py                             \
   python/google/protobuf/internal/wire_format_test.py                        \
   python/google/protobuf/internal/__init__.py                                \
+  python/google/protobuf/pyext/python-proto2.cc                              \
+  python/google/protobuf/pyext/python_descriptor.cc                          \
+  python/google/protobuf/pyext/python_descriptor.h                           \
+  python/google/protobuf/pyext/python_protobuf.cc                            \
+  python/google/protobuf/pyext/python_protobuf.h                             \
   python/google/protobuf/descriptor.py                                       \
   python/google/protobuf/message.py                                          \
   python/google/protobuf/reflection.py                                       \
diff --git a/java/pom.xml b/java/pom.xml
index 94f1d7f..cdf85de 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -105,6 +105,12 @@
                   <arg value="../src/google/protobuf/unittest_mset.proto" />
                   <arg
                     value="src/test/java/com/google/protobuf/multiple_files_test.proto" />
+                  <arg value="src/test/java/com/google/protobuf/nested_builders_test.proto" />
+                  <arg value="src/test/java/com/google/protobuf/nested_extension.proto" />
+                  <arg value="src/test/java/com/google/protobuf/nested_extension_lite.proto" />
+                  <arg value="src/test/java/com/google/protobuf/non_nested_extension.proto" />
+                  <arg value="src/test/java/com/google/protobuf/non_nested_extension_lite.proto" />
+                  <arg value="src/test/java/com/google/protobuf/test_bad_identifiers.proto" />
                   <arg
                     value="../src/google/protobuf/unittest_optimize_for.proto" />
                   <arg
diff --git a/java/src/main/java/com/google/protobuf/AbstractMessage.java b/java/src/main/java/com/google/protobuf/AbstractMessage.java
index fb416bd..b9d8301 100644
--- a/java/src/main/java/com/google/protobuf/AbstractMessage.java
+++ b/java/src/main/java/com/google/protobuf/AbstractMessage.java
@@ -32,9 +32,10 @@
 
 import com.google.protobuf.Descriptors.Descriptor;
 import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.Internal.EnumLite;
 
-import java.io.InputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -167,11 +168,66 @@
   public int hashCode() {
     int hash = 41;
     hash = (19 * hash) + getDescriptorForType().hashCode();
-    hash = (53 * hash) + getAllFields().hashCode();
+    hash = hashFields(hash, getAllFields());
     hash = (29 * hash) + getUnknownFields().hashCode();
     return hash;
   }
 
+  /** Get a hash code for given fields and values, using the given seed. */
+  @SuppressWarnings("unchecked")
+  protected int hashFields(int hash, Map<FieldDescriptor, Object> map) {
+    for (Map.Entry<FieldDescriptor, Object> entry : map.entrySet()) {
+      FieldDescriptor field = entry.getKey();
+      Object value = entry.getValue();
+      hash = (37 * hash) + field.getNumber();
+      if (field.getType() != FieldDescriptor.Type.ENUM){
+        hash = (53 * hash) + value.hashCode();
+      } else if (field.isRepeated()) {
+        List<? extends EnumLite> list = (List<? extends EnumLite>) value;
+        hash = (53 * hash) + hashEnumList(list);
+      } else {
+        hash = (53 * hash) + hashEnum((EnumLite) value);
+      }
+    }
+    return hash;
+  }
+
+  /**
+   * Helper method for implementing {@link Message#hashCode()}.
+   * @see Boolean#hashCode()
+   */
+  protected static int hashLong(long n) {
+    return (int) (n ^ (n >>> 32));
+  }
+
+  /**
+   * Helper method for implementing {@link Message#hashCode()}.
+   * @see Boolean#hashCode()
+   */
+  protected static int hashBoolean(boolean b) {
+    return b ? 1231 : 1237;
+  }
+
+  /**
+   * Helper method for implementing {@link Message#hashCode()}.
+   * <p>
+   * This is needed because {@link java.lang.Enum#hashCode()} is final, but we
+   * need to use the field number as the hash code to ensure compatibility
+   * between statically and dynamically generated enum objects.
+   */
+  protected static int hashEnum(EnumLite e) {
+    return e.getNumber();
+  }
+
+  /** Helper method for implementing {@link Message#hashCode()}. */
+  protected static int hashEnumList(List<? extends EnumLite> list) {
+    int hash = 1;
+    for (EnumLite e : list) {
+      hash = 31 * hash + hashEnum(e);
+    }
+    return hash;
+  }
+
   // =================================================================
 
   /**
diff --git a/java/src/main/java/com/google/protobuf/ByteString.java b/java/src/main/java/com/google/protobuf/ByteString.java
index 5fade03..9135635 100644
--- a/java/src/main/java/com/google/protobuf/ByteString.java
+++ b/java/src/main/java/com/google/protobuf/ByteString.java
@@ -194,6 +194,18 @@
   }
 
   /**
+   * Copies bytes into a ByteBuffer.
+   *
+   * @param target ByteBuffer to copy into.
+   * @throws ReadOnlyBufferException if the {@code target} is read-only
+   * @throws BufferOverflowException if the {@code target}'s remaining()
+   *         space is not large enough to hold the data.
+   */
+  public void copyTo(ByteBuffer target) {
+    target.put(bytes, 0, bytes.length);
+  }
+
+  /**
    * Copies bytes to a {@code byte[]}.
    */
   public byte[] toByteArray() {
diff --git a/java/src/main/java/com/google/protobuf/CodedInputStream.java b/java/src/main/java/com/google/protobuf/CodedInputStream.java
index ad43f96..b3e0855 100644
--- a/java/src/main/java/com/google/protobuf/CodedInputStream.java
+++ b/java/src/main/java/com/google/protobuf/CodedInputStream.java
@@ -67,7 +67,25 @@
    */
   public static CodedInputStream newInstance(final byte[] buf, final int off,
                                              final int len) {
-    return new CodedInputStream(buf, off, len);
+    CodedInputStream result = new CodedInputStream(buf, off, len);
+    try {
+      // Some uses of CodedInputStream can be more efficient if they know
+      // exactly how many bytes are available.  By pushing the end point of the
+      // buffer as a limit, we allow them to get this information via
+      // getBytesUntilLimit().  Pushing a limit that we know is at the end of
+      // the stream can never hurt, since we can never past that point anyway.
+      result.pushLimit(len);
+    } catch (InvalidProtocolBufferException ex) {
+      // The only reason pushLimit() might throw an exception here is if len
+      // is negative. Normally pushLimit()'s parameter comes directly off the
+      // wire, so it's important to catch exceptions in case of corrupt or
+      // malicious data. However, in this case, we expect that len is not a
+      // user-supplied value, so we can assume that it being negative indicates
+      // a programming error. Therefore, throwing an unchecked exception is
+      // appropriate.
+      throw new IllegalArgumentException(ex);
+    }
+    return result;
   }
 
   // -----------------------------------------------------------------
@@ -263,7 +281,9 @@
   /** Read a {@code bytes} field value from the stream. */
   public ByteString readBytes() throws IOException {
     final int size = readRawVarint32();
-    if (size <= (bufferSize - bufferPos) && size > 0) {
+    if (size == 0) {
+      return ByteString.EMPTY;
+    } else if (size <= (bufferSize - bufferPos) && size > 0) {
       // Fast path:  We already have the bytes in a contiguous buffer, so
       //   just copy directly from it.
       final ByteString result = ByteString.copyFrom(buffer, bufferPos, size);
@@ -368,8 +388,8 @@
    * has already read one byte.  This allows the caller to determine if EOF
    * has been reached before attempting to read.
    */
-  static int readRawVarint32(final int firstByte,
-                             final InputStream input) throws IOException {
+  public static int readRawVarint32(
+      final int firstByte, final InputStream input) throws IOException {
     if ((firstByte & 0x80) == 0) {
       return firstByte;
     }
@@ -847,19 +867,19 @@
     } else {
       // Skipping more bytes than are in the buffer.  First skip what we have.
       int pos = bufferSize - bufferPos;
-      totalBytesRetired += pos;
-      bufferPos = 0;
-      bufferSize = 0;
+      bufferPos = bufferSize;
 
-      // Then skip directly from the InputStream for the rest.
-      while (pos < size) {
-        final int n = (input == null) ? -1 : (int) input.skip(size - pos);
-        if (n <= 0) {
-          throw InvalidProtocolBufferException.truncatedMessage();
-        }
-        pos += n;
-        totalBytesRetired += n;
+      // Keep refilling the buffer until we get to the point we wanted to skip
+      // to.  This has the side effect of ensuring the limits are updated
+      // correctly.
+      refillBuffer(true);
+      while (size - pos > bufferSize) {
+        pos += bufferSize;
+        bufferPos = bufferSize;
+        refillBuffer(true);
       }
+
+      bufferPos = size - pos; 
     }
   }
 }
diff --git a/java/src/main/java/com/google/protobuf/CodedOutputStream.java b/java/src/main/java/com/google/protobuf/CodedOutputStream.java
index 58dd150..51a932a 100644
--- a/java/src/main/java/com/google/protobuf/CodedOutputStream.java
+++ b/java/src/main/java/com/google/protobuf/CodedOutputStream.java
@@ -33,6 +33,7 @@
 import java.io.OutputStream;
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
+import java.io.InputStream;
 
 /**
  * Encodes and writes protocol message fields.
@@ -381,9 +382,8 @@
 
   /** Write a {@code bytes} field to the stream. */
   public void writeBytesNoTag(final ByteString value) throws IOException {
-    final byte[] bytes = value.toByteArray();
-    writeRawVarint32(bytes.length);
-    writeRawBytes(bytes);
+    writeRawVarint32(value.size());
+    writeRawBytes(value);
   }
 
   /** Write a {@code uint32} field to the stream. */
@@ -870,6 +870,11 @@
     writeRawByte((byte) value);
   }
 
+  /** Write a byte string. */
+  public void writeRawBytes(final ByteString value) throws IOException {
+    writeRawBytes(value, 0, value.size());
+  }
+
   /** Write an array of bytes. */
   public void writeRawBytes(final byte[] value) throws IOException {
     writeRawBytes(value, 0, value.length);
@@ -906,6 +911,53 @@
     }
   }
 
+  /** Write part of a byte string. */
+  public void writeRawBytes(final ByteString value, int offset, int length)
+                            throws IOException {
+    if (limit - position >= length) {
+      // We have room in the current buffer.
+      value.copyTo(buffer, offset, position, length);
+      position += length;
+    } else {
+      // Write extends past current buffer.  Fill the rest of this buffer and
+      // flush.
+      final int bytesWritten = limit - position;
+      value.copyTo(buffer, offset, position, bytesWritten);
+      offset += bytesWritten;
+      length -= bytesWritten;
+      position = limit;
+      refreshBuffer();
+
+      // Now deal with the rest.
+      // Since we have an output stream, this is our buffer
+      // and buffer offset == 0
+      if (length <= limit) {
+        // Fits in new buffer.
+        value.copyTo(buffer, offset, 0, length);
+        position = length;
+      } else {
+        // Write is very big, but we can't do it all at once without allocating
+        // an a copy of the byte array since ByteString does not give us access
+        // to the underlying bytes. Use the InputStream interface on the
+        // ByteString and our buffer to copy between the two.
+        InputStream inputStreamFrom = value.newInput();
+        if (offset != inputStreamFrom.skip(offset)) {
+          throw new IllegalStateException("Skip failed? Should never happen.");
+        }
+        // Use the buffer as the temporary buffer to avoid allocating memory.
+        while (length > 0) {
+          int bytesToRead = Math.min(length, limit);
+          int bytesRead = inputStreamFrom.read(buffer, 0, bytesToRead);
+          if (bytesRead != bytesToRead) {
+            throw new IllegalStateException("Read failed? Should never happen");
+          }
+          output.write(buffer, 0, bytesRead);
+          length -= bytesRead;
+        }
+      }
+    }
+  }
+
   /** Encode and write a tag. */
   public void writeTag(final int fieldNumber, final int wireType)
                        throws IOException {
diff --git a/java/src/main/java/com/google/protobuf/Descriptors.java b/java/src/main/java/com/google/protobuf/Descriptors.java
index c5e9a04..2ee8459 100644
--- a/java/src/main/java/com/google/protobuf/Descriptors.java
+++ b/java/src/main/java/com/google/protobuf/Descriptors.java
@@ -46,6 +46,11 @@
  * its fields and other information about a type.  You can get a message
  * type's descriptor by calling {@code MessageType.getDescriptor()}, or
  * (given a message object of the type) {@code message.getDescriptorForType()}.
+ * Furthermore, each message is associated with a {@link FileDescriptor} for
+ * a relevant {@code .proto} file. You can obtain it by calling
+ * {@code Descriptor.getFile()}. A {@link FileDescriptor} contains descriptors
+ * for all the messages defined in that file, and file descriptors for all the
+ * imported {@code .proto} files.
  *
  * Descriptors are built from DescriptorProtos, as defined in
  * {@code google/protobuf/descriptor.proto}.
@@ -55,6 +60,9 @@
 public final class Descriptors {
   /**
    * Describes a {@code .proto} file, including everything defined within.
+   * That includes, in particular, descriptors for all the messages and
+   * file descriptors for all other imported {@code .proto} files
+   * (dependencies).
    */
   public static final class FileDescriptor {
     /** Convert the descriptor to its protocol message representation. */
diff --git a/java/src/main/java/com/google/protobuf/FieldSet.java b/java/src/main/java/com/google/protobuf/FieldSet.java
index bc1bb79..a85dbaa 100644
--- a/java/src/main/java/com/google/protobuf/FieldSet.java
+++ b/java/src/main/java/com/google/protobuf/FieldSet.java
@@ -33,7 +33,6 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
-import java.util.TreeMap;
 import java.util.List;
 import java.util.Map;
 import java.io.IOException;
@@ -67,16 +66,12 @@
         MessageLite.Builder to, MessageLite from);
   }
 
-  private Map<FieldDescriptorType, Object> fields;
+  private final SmallSortedMap<FieldDescriptorType, Object> fields;
+  private boolean isImmutable;
 
   /** Construct a new FieldSet. */
   private FieldSet() {
-    // Use a TreeMap because fields need to be in canonical order when
-    // serializing.
-    // TODO(kenton):  Maybe use some sort of sparse array instead?  It would
-    //   even make sense to store the first 16 or so tags in a flat array
-    //   to make DynamicMessage faster.
-    fields = new TreeMap<FieldDescriptorType, Object>();
+    this.fields = SmallSortedMap.newFieldMap(16);
   }
 
   /**
@@ -84,7 +79,8 @@
    * DEFAULT_INSTANCE.
    */
   private FieldSet(final boolean dummy) {
-    this.fields = Collections.emptyMap();
+    this.fields = SmallSortedMap.newFieldMap(0);
+    makeImmutable();
   }
 
   /** Construct a new FieldSet. */
@@ -105,14 +101,45 @@
   /** Make this FieldSet immutable from this point forward. */
   @SuppressWarnings("unchecked")
   public void makeImmutable() {
-    for (final Map.Entry<FieldDescriptorType, Object> entry:
-         fields.entrySet()) {
-      if (entry.getKey().isRepeated()) {
-        final List value = (List)entry.getValue();
-        fields.put(entry.getKey(), Collections.unmodifiableList(value));
-      }
+    if (isImmutable) {
+      return;
     }
-    fields = Collections.unmodifiableMap(fields);
+    fields.makeImmutable();
+    isImmutable = true;
+  }
+
+  /**
+   * Retuns whether the FieldSet is immutable. This is true if it is the
+   * {@link #emptySet} or if {@link #makeImmutable} were called.
+   *
+   * @return whether the FieldSet is immutable.
+   */
+  public boolean isImmutable() {
+    return isImmutable;
+  }
+
+  /**
+   * Clones the FieldSet. The returned FieldSet will be mutable even if the
+   * original FieldSet was immutable.
+   *
+   * @return the newly cloned FieldSet
+   */
+  @Override
+  public FieldSet<FieldDescriptorType> clone() {
+    // We can't just call fields.clone because List objects in the map
+    // should not be shared.
+    FieldSet<FieldDescriptorType> clone = FieldSet.newFieldSet();
+    for (int i = 0; i < fields.getNumArrayEntries(); i++) {
+      Map.Entry<FieldDescriptorType, Object> entry = fields.getArrayEntryAt(i);
+      FieldDescriptorType descriptor = entry.getKey();
+      clone.setField(descriptor, entry.getValue());
+    }
+    for (Map.Entry<FieldDescriptorType, Object> entry :
+             fields.getOverflowEntries()) {
+      FieldDescriptorType descriptor = entry.getKey();
+      clone.setField(descriptor, entry.getValue());
+    }
+    return clone;
   }
 
   // =================================================================
@@ -126,12 +153,13 @@
    * Get a simple map containing all the fields.
    */
   public Map<FieldDescriptorType, Object> getAllFields() {
-    return Collections.unmodifiableMap(fields);
+    return fields.isImmutable() ? fields : Collections.unmodifiableMap(fields);
   }
 
   /**
-   * Get an iterator to the field map.  This iterator should not be leaked
-   * out of the protobuf library as it is not protected from mutation.
+   * Get an iterator to the field map. This iterator should not be leaked out
+   * of the protobuf library as it is not protected from mutation when
+   * fields is not immutable.
    */
   public Iterator<Map.Entry<FieldDescriptorType, Object>> iterator() {
     return fields.entrySet().iterator();
@@ -336,27 +364,39 @@
    * aren't actually present in the set, it is up to the caller to check
    * that all required fields are present.
    */
-  @SuppressWarnings("unchecked")
   public boolean isInitialized() {
-    for (final Map.Entry<FieldDescriptorType, Object> entry:
-         fields.entrySet()) {
-      final FieldDescriptorType descriptor = entry.getKey();
-      if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) {
-        if (descriptor.isRepeated()) {
-          for (final MessageLite element:
-               (List<MessageLite>) entry.getValue()) {
-            if (!element.isInitialized()) {
-              return false;
-            }
-          }
-        } else {
-          if (!((MessageLite) entry.getValue()).isInitialized()) {
+    for (int i = 0; i < fields.getNumArrayEntries(); i++) {
+      if (!isInitialized(fields.getArrayEntryAt(i))) {
+        return false;
+      }
+    }
+    for (final Map.Entry<FieldDescriptorType, Object> entry :
+             fields.getOverflowEntries()) {
+      if (!isInitialized(entry)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  @SuppressWarnings("unchecked")
+  private boolean isInitialized(
+      final Map.Entry<FieldDescriptorType, Object> entry) {
+    final FieldDescriptorType descriptor = entry.getKey();
+    if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) {
+      if (descriptor.isRepeated()) {
+        for (final MessageLite element:
+                 (List<MessageLite>) entry.getValue()) {
+          if (!element.isInitialized()) {
             return false;
           }
         }
+      } else {
+        if (!((MessageLite) entry.getValue()).isInitialized()) {
+          return false;
+        }
       }
     }
-
     return true;
   }
 
@@ -378,39 +418,48 @@
   /**
    * Like {@link #mergeFrom(Message)}, but merges from another {@link FieldSet}.
    */
-  @SuppressWarnings("unchecked")
   public void mergeFrom(final FieldSet<FieldDescriptorType> other) {
-    for (final Map.Entry<FieldDescriptorType, Object> entry:
-         other.fields.entrySet()) {
-      final FieldDescriptorType descriptor = entry.getKey();
-      final Object otherValue = entry.getValue();
+    for (int i = 0; i < other.fields.getNumArrayEntries(); i++) {
+      mergeFromField(other.fields.getArrayEntryAt(i));
+    }
+    for (final Map.Entry<FieldDescriptorType, Object> entry :
+             other.fields.getOverflowEntries()) {
+      mergeFromField(entry);
+    }
+  }
 
-      if (descriptor.isRepeated()) {
-        Object value = fields.get(descriptor);
-        if (value == null) {
-          // Our list is empty, but we still need to make a defensive copy of
-          // the other list since we don't know if the other FieldSet is still
-          // mutable.
-          fields.put(descriptor, new ArrayList((List) otherValue));
-        } else {
-          // Concatenate the lists.
-          ((List) value).addAll((List) otherValue);
-        }
-      } else if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) {
-        Object value = fields.get(descriptor);
-        if (value == null) {
-          fields.put(descriptor, otherValue);
-        } else {
-          // Merge the messages.
-          fields.put(descriptor,
-              descriptor.internalMergeFrom(
-                ((MessageLite) value).toBuilder(), (MessageLite) otherValue)
-              .build());
-        }
+  @SuppressWarnings("unchecked")
+  private void mergeFromField(
+      final Map.Entry<FieldDescriptorType, Object> entry) {
+    final FieldDescriptorType descriptor = entry.getKey();
+    final Object otherValue = entry.getValue();
 
+    if (descriptor.isRepeated()) {
+      Object value = fields.get(descriptor);
+      if (value == null) {
+        // Our list is empty, but we still need to make a defensive copy of
+        // the other list since we don't know if the other FieldSet is still
+        // mutable.
+        fields.put(descriptor, new ArrayList((List) otherValue));
       } else {
-        fields.put(descriptor, otherValue);
+        // Concatenate the lists.
+        ((List) value).addAll((List) otherValue);
       }
+    } else if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) {
+      Object value = fields.get(descriptor);
+      if (value == null) {
+        fields.put(descriptor, otherValue);
+      } else {
+        // Merge the messages.
+        fields.put(
+            descriptor,
+            descriptor.internalMergeFrom(
+                ((MessageLite) value).toBuilder(), (MessageLite) otherValue)
+            .build());
+      }
+
+    } else {
+      fields.put(descriptor, otherValue);
     }
   }
 
@@ -468,8 +517,13 @@
   /** See {@link Message#writeTo(CodedOutputStream)}. */
   public void writeTo(final CodedOutputStream output)
                       throws IOException {
-    for (final Map.Entry<FieldDescriptorType, Object> entry:
-         fields.entrySet()) {
+    for (int i = 0; i < fields.getNumArrayEntries(); i++) {
+      final Map.Entry<FieldDescriptorType, Object> entry =
+          fields.getArrayEntryAt(i);
+      writeField(entry.getKey(), entry.getValue(), output);
+    }
+    for (final Map.Entry<FieldDescriptorType, Object> entry :
+         fields.getOverflowEntries()) {
       writeField(entry.getKey(), entry.getValue(), output);
     }
   }
@@ -479,16 +533,25 @@
    */
   public void writeMessageSetTo(final CodedOutputStream output)
                                 throws IOException {
-    for (final Map.Entry<FieldDescriptorType, Object> entry:
-         fields.entrySet()) {
-      final FieldDescriptorType descriptor = entry.getKey();
-      if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE &&
-          !descriptor.isRepeated() && !descriptor.isPacked()) {
-        output.writeMessageSetExtension(entry.getKey().getNumber(),
-                                        (MessageLite) entry.getValue());
-      } else {
-        writeField(descriptor, entry.getValue(), output);
-      }
+    for (int i = 0; i < fields.getNumArrayEntries(); i++) {
+      writeMessageSetTo(fields.getArrayEntryAt(i), output);
+    }
+    for (final Map.Entry<FieldDescriptorType, Object> entry :
+             fields.getOverflowEntries()) {
+      writeMessageSetTo(entry, output);
+    }
+  }
+
+  private void writeMessageSetTo(
+      final Map.Entry<FieldDescriptorType, Object> entry,
+      final CodedOutputStream output) throws IOException {
+    final FieldDescriptorType descriptor = entry.getKey();
+    if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE &&
+        !descriptor.isRepeated() && !descriptor.isPacked()) {
+      output.writeMessageSetExtension(entry.getKey().getNumber(),
+                                      (MessageLite) entry.getValue());
+    } else {
+      writeField(descriptor, entry.getValue(), output);
     }
   }
 
@@ -593,8 +656,13 @@
    */
   public int getSerializedSize() {
     int size = 0;
-    for (final Map.Entry<FieldDescriptorType, Object> entry:
-         fields.entrySet()) {
+    for (int i = 0; i < fields.getNumArrayEntries(); i++) {
+      final Map.Entry<FieldDescriptorType, Object> entry =
+          fields.getArrayEntryAt(i);
+      size += computeFieldSize(entry.getKey(), entry.getValue());
+    }
+    for (final Map.Entry<FieldDescriptorType, Object> entry :
+         fields.getOverflowEntries()) {
       size += computeFieldSize(entry.getKey(), entry.getValue());
     }
     return size;
@@ -605,20 +673,28 @@
    */
   public int getMessageSetSerializedSize() {
     int size = 0;
-    for (final Map.Entry<FieldDescriptorType, Object> entry:
-         fields.entrySet()) {
-      final FieldDescriptorType descriptor = entry.getKey();
-      if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE &&
-          !descriptor.isRepeated() && !descriptor.isPacked()) {
-        size += CodedOutputStream.computeMessageSetExtensionSize(
-                  entry.getKey().getNumber(), (MessageLite) entry.getValue());
-      } else {
-        size += computeFieldSize(descriptor, entry.getValue());
-      }
+    for (int i = 0; i < fields.getNumArrayEntries(); i++) {
+      size += getMessageSetSerializedSize(fields.getArrayEntryAt(i));
+    }
+    for (final Map.Entry<FieldDescriptorType, Object> entry :
+             fields.getOverflowEntries()) {
+      size += getMessageSetSerializedSize(entry);
     }
     return size;
   }
 
+  private int getMessageSetSerializedSize(
+      final Map.Entry<FieldDescriptorType, Object> entry) {
+    final FieldDescriptorType descriptor = entry.getKey();
+    if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE &&
+        !descriptor.isRepeated() && !descriptor.isPacked()) {
+      return CodedOutputStream.computeMessageSetExtensionSize(
+          entry.getKey().getNumber(), (MessageLite) entry.getValue());
+    } else {
+      return computeFieldSize(descriptor, entry.getValue());
+    }
+  }
+
   /**
    * Compute the number of bytes that would be needed to encode a
    * single tag/value pair of arbitrary type.
diff --git a/java/src/main/java/com/google/protobuf/GeneratedMessage.java b/java/src/main/java/com/google/protobuf/GeneratedMessage.java
index 42ccbfd..fc2e530 100644
--- a/java/src/main/java/com/google/protobuf/GeneratedMessage.java
+++ b/java/src/main/java/com/google/protobuf/GeneratedMessage.java
@@ -35,8 +35,10 @@
 import com.google.protobuf.Descriptors.FieldDescriptor;
 
 import java.io.IOException;
-import java.lang.reflect.Method;
+import java.io.ObjectStreamException;
+import java.io.Serializable;
 import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
@@ -52,10 +54,35 @@
  *
  * @author kenton@google.com Kenton Varda
  */
-public abstract class GeneratedMessage extends AbstractMessage {
-  protected GeneratedMessage() {}
+public abstract class GeneratedMessage extends AbstractMessage
+    implements Serializable {
 
-  private UnknownFieldSet unknownFields = UnknownFieldSet.getDefaultInstance();
+  private final UnknownFieldSet unknownFields;
+
+  /**
+   * For testing. Allows a test to disable the optimization that avoids using
+   * field builders for nested messages until they are requested. By disabling
+   * this optimization, existing tests can be reused to test the field builders.
+   */
+  protected static boolean alwaysUseFieldBuilders = false;
+
+  protected GeneratedMessage() {
+    this.unknownFields = UnknownFieldSet.getDefaultInstance();
+  }
+
+  protected GeneratedMessage(Builder<?> builder) {
+    this.unknownFields = builder.getUnknownFields();
+  }
+
+ /**
+  * For testing. Allows a test to disable the optimization that avoids using
+  * field builders for nested messages until they are requested. By disabling
+  * this optimization, existing tests can be reused to test the field builders.
+  * See {@link RepeatedFieldBuilder} and {@link SingleFieldBuilder}.
+  */
+  static void enableAlwaysUseFieldBuildersForTesting() {
+    alwaysUseFieldBuilders = true;
+  }
 
   /**
    * Get the FieldAccessorTable for this type.  We can't have the message
@@ -64,6 +91,7 @@
    */
   protected abstract FieldAccessorTable internalGetFieldAccessorTable();
 
+  //@Override (Java 1.6 override semantics, but we must support 1.5)
   public Descriptor getDescriptorForType() {
     return internalGetFieldAccessorTable().descriptor;
   }
@@ -118,36 +146,115 @@
     return true;
   }
 
+  //@Override (Java 1.6 override semantics, but we must support 1.5)
   public Map<FieldDescriptor, Object> getAllFields() {
     return Collections.unmodifiableMap(getAllFieldsMutable());
   }
 
+  //@Override (Java 1.6 override semantics, but we must support 1.5)
   public boolean hasField(final FieldDescriptor field) {
     return internalGetFieldAccessorTable().getField(field).has(this);
   }
 
+  //@Override (Java 1.6 override semantics, but we must support 1.5)
   public Object getField(final FieldDescriptor field) {
     return internalGetFieldAccessorTable().getField(field).get(this);
   }
 
+  //@Override (Java 1.6 override semantics, but we must support 1.5)
   public int getRepeatedFieldCount(final FieldDescriptor field) {
     return internalGetFieldAccessorTable().getField(field)
       .getRepeatedCount(this);
   }
 
+  //@Override (Java 1.6 override semantics, but we must support 1.5)
   public Object getRepeatedField(final FieldDescriptor field, final int index) {
     return internalGetFieldAccessorTable().getField(field)
       .getRepeated(this, index);
   }
 
+  //@Override (Java 1.6 override semantics, but we must support 1.5)
   public final UnknownFieldSet getUnknownFields() {
     return unknownFields;
   }
 
+  protected abstract Message.Builder newBuilderForType(BuilderParent parent);
+
+  /**
+   * Interface for the parent of a Builder that allows the builder to
+   * communicate invalidations back to the parent for use when using nested
+   * builders.
+   */
+  protected interface BuilderParent {
+
+    /**
+     * A builder becomes dirty whenever a field is modified -- including fields
+     * in nested builders -- and becomes clean when build() is called.  Thus,
+     * when a builder becomes dirty, all its parents become dirty as well, and
+     * when it becomes clean, all its children become clean.  The dirtiness
+     * state is used to invalidate certain cached values.
+     * <br>
+     * To this end, a builder calls markAsDirty() on its parent whenever it
+     * transitions from clean to dirty.  The parent must propagate this call to
+     * its own parent, unless it was already dirty, in which case the
+     * grandparent must necessarily already be dirty as well.  The parent can
+     * only transition back to "clean" after calling build() on all children.
+     */
+    void markDirty();
+  }
+
   @SuppressWarnings("unchecked")
   public abstract static class Builder <BuilderType extends Builder>
       extends AbstractMessage.Builder<BuilderType> {
-    protected Builder() {}
+
+    private BuilderParent builderParent;
+
+    private BuilderParentImpl meAsParent;
+
+    // Indicates that we've built a message and so we are now obligated
+    // to dispatch dirty invalidations. See GeneratedMessage.BuilderListener.
+    private boolean isClean;
+
+    private UnknownFieldSet unknownFields =
+        UnknownFieldSet.getDefaultInstance();
+
+    protected Builder() {
+      this(null);
+    }
+
+    protected Builder(BuilderParent builderParent) {
+      this.builderParent = builderParent;
+    }
+
+    void dispose() {
+      builderParent = null;
+    }
+
+    /**
+     * Called by the subclass when a message is built.
+     */
+    protected void onBuilt() {
+      if (builderParent != null) {
+        markClean();
+      }
+    }
+
+    /**
+     * Called by the subclass or a builder to notify us that a message was
+     * built and may be cached and therefore invalidations are needed.
+     */
+    protected void markClean() {
+      this.isClean = true;
+    }
+
+    /**
+     * Gets whether invalidations are needed
+     *
+     * @return whether invalidations are needed
+     */
+    protected boolean isClean() {
+      return isClean;
+    }
 
     // This is implemented here only to work around an apparent bug in the
     // Java compiler and/or build system.  See bug #1898463.  The mere presence
@@ -159,26 +266,50 @@
     }
 
     /**
-     * Get the message being built.  We don't just pass this to the
-     * constructor because it becomes null when build() is called.
+     * Called by the initialization and clear code paths to allow subclasses to
+     * reset any of their builtin fields back to the initial values.
      */
-    protected abstract GeneratedMessage internalGetResult();
+    public BuilderType clear() {
+      unknownFields = UnknownFieldSet.getDefaultInstance();
+      onChanged();
+      return (BuilderType) this;
+    }
 
     /**
      * Get the FieldAccessorTable for this type.  We can't have the message
      * class pass this in to the constructor because of bootstrapping trouble
      * with DescriptorProtos.
      */
-    private FieldAccessorTable internalGetFieldAccessorTable() {
-      return internalGetResult().internalGetFieldAccessorTable();
-    }
+    protected abstract FieldAccessorTable internalGetFieldAccessorTable();
 
+    //@Override (Java 1.6 override semantics, but we must support 1.5)
     public Descriptor getDescriptorForType() {
       return internalGetFieldAccessorTable().descriptor;
     }
 
+    //@Override (Java 1.6 override semantics, but we must support 1.5)
     public Map<FieldDescriptor, Object> getAllFields() {
-      return internalGetResult().getAllFields();
+      return Collections.unmodifiableMap(getAllFieldsMutable());
+    }
+
+    /** Internal helper which returns a mutable map. */
+    private Map<FieldDescriptor, Object> getAllFieldsMutable() {
+      final TreeMap<FieldDescriptor, Object> result =
+        new TreeMap<FieldDescriptor, Object>();
+      final Descriptor descriptor = internalGetFieldAccessorTable().descriptor;
+      for (final FieldDescriptor field : descriptor.getFields()) {
+        if (field.isRepeated()) {
+          final List value = (List) getField(field);
+          if (!value.isEmpty()) {
+            result.put(field, value);
+          }
+        } else {
+          if (hasField(field)) {
+            result.put(field, getField(field));
+          }
+        }
+      }
+      return result;
     }
 
     public Message.Builder newBuilderForField(
@@ -186,18 +317,20 @@
       return internalGetFieldAccessorTable().getField(field).newBuilder();
     }
 
+    //@Override (Java 1.6 override semantics, but we must support 1.5)
     public boolean hasField(final FieldDescriptor field) {
-      return internalGetResult().hasField(field);
+      return internalGetFieldAccessorTable().getField(field).has(this);
     }
 
+    //@Override (Java 1.6 override semantics, but we must support 1.5)
     public Object getField(final FieldDescriptor field) {
+      Object object = internalGetFieldAccessorTable().getField(field).get(this);
       if (field.isRepeated()) {
         // The underlying list object is still modifiable at this point.
         // Make sure not to expose the modifiable list to the caller.
-        return Collections.unmodifiableList(
-          (List) internalGetResult().getField(field));
+        return Collections.unmodifiableList((List) object);
       } else {
-        return internalGetResult().getField(field);
+        return object;
       }
     }
 
@@ -207,18 +340,23 @@
       return (BuilderType) this;
     }
 
+    //@Override (Java 1.6 override semantics, but we must support 1.5)
     public BuilderType clearField(final FieldDescriptor field) {
       internalGetFieldAccessorTable().getField(field).clear(this);
       return (BuilderType) this;
     }
 
+    //@Override (Java 1.6 override semantics, but we must support 1.5)
     public int getRepeatedFieldCount(final FieldDescriptor field) {
-      return internalGetResult().getRepeatedFieldCount(field);
+      return internalGetFieldAccessorTable().getField(field)
+          .getRepeatedCount(this);
     }
 
+    //@Override (Java 1.6 override semantics, but we must support 1.5)
     public Object getRepeatedField(final FieldDescriptor field,
                                    final int index) {
-      return internalGetResult().getRepeatedField(field, index);
+      return internalGetFieldAccessorTable().getField(field)
+          .getRepeated(this, index);
     }
 
     public BuilderType setRepeatedField(final FieldDescriptor field,
@@ -234,29 +372,57 @@
       return (BuilderType) this;
     }
 
-    public final UnknownFieldSet getUnknownFields() {
-      return internalGetResult().unknownFields;
-    }
-
     public final BuilderType setUnknownFields(
         final UnknownFieldSet unknownFields) {
-      internalGetResult().unknownFields = unknownFields;
+      this.unknownFields = unknownFields;
+      onChanged();
       return (BuilderType) this;
     }
 
     @Override
     public final BuilderType mergeUnknownFields(
         final UnknownFieldSet unknownFields) {
-      final GeneratedMessage result = internalGetResult();
-      result.unknownFields =
-        UnknownFieldSet.newBuilder(result.unknownFields)
+      this.unknownFields =
+        UnknownFieldSet.newBuilder(this.unknownFields)
                        .mergeFrom(unknownFields)
                        .build();
+      onChanged();
       return (BuilderType) this;
     }
 
+    //@Override (Java 1.6 override semantics, but we must support 1.5)
     public boolean isInitialized() {
-      return internalGetResult().isInitialized();
+      for (final FieldDescriptor field : getDescriptorForType().getFields()) {
+        // Check that all required fields are present.
+        if (field.isRequired()) {
+          if (!hasField(field)) {
+            return false;
+          }
+        }
+        // Check that embedded messages are initialized.
+        if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+          if (field.isRepeated()) {
+            @SuppressWarnings("unchecked") final
+            List<Message> messageList = (List<Message>) getField(field);
+            for (final Message element : messageList) {
+              if (!element.isInitialized()) {
+                return false;
+              }
+            }
+          } else {
+            if (hasField(field) &&
+                !((Message) getField(field)).isInitialized()) {
+              return false;
+            }
+          }
+        }
+      }
+      return true;
+    }
+
+    @Override
+    public final UnknownFieldSet getUnknownFields() {
+      return unknownFields;
     }
 
     /**
@@ -270,11 +436,68 @@
         final int tag) throws IOException {
       return unknownFields.mergeFieldFrom(tag, input);
     }
+
+    /**
+     * Implementation of {@link BuilderParent} for giving to our children. This
+     * small inner class makes it so we don't publicly expose the BuilderParent
+     * methods.
+     */
+    private class BuilderParentImpl implements BuilderParent {
+
+      @Override
+      public void markDirty() {
+        onChanged();
+      }
+    }
+
+    /**
+     * Gets the {@link BuilderParent} for giving to our children.
+     * @return The builder parent for our children.
+     */
+    protected BuilderParent getParentForChildren() {
+      if (meAsParent == null) {
+        meAsParent = new BuilderParentImpl();
+      }
+      return meAsParent;
+    }
+
+    /**
+     * Called when a the builder or one of its nested children has changed
+     * and any parent should be notified of its invalidation.
+     */
+    protected final void onChanged() {
+      if (isClean && builderParent != null) {
+        builderParent.markDirty();
+
+        // Don't keep dispatching invalidations until build is called again.
+        isClean = false;
+      }
+    }
   }
 
   // =================================================================
   // Extensions-related stuff
 
+  public interface ExtendableMessageOrBuilder<
+      MessageType extends ExtendableMessage> extends MessageOrBuilder {
+
+    /** Check if a singular extension is present. */
+    <Type> boolean hasExtension(
+        GeneratedExtension<MessageType, Type> extension);
+
+    /** Get the number of elements in a repeated extension. */
+    <Type> int getExtensionCount(
+        GeneratedExtension<MessageType, List<Type>> extension);
+
+    /** Get the value of an extension. */
+    <Type> Type getExtension(GeneratedExtension<MessageType, Type> extension);
+
+    /** Get one element of a repeated extension. */
+    <Type> Type getExtension(
+        GeneratedExtension<MessageType, List<Type>> extension,
+        int index);
+  }
+
   /**
    * Generated message classes for message types that contain extension ranges
    * subclass this.
@@ -312,9 +535,20 @@
    */
   public abstract static class ExtendableMessage<
         MessageType extends ExtendableMessage>
-      extends GeneratedMessage {
-    protected ExtendableMessage() {}
-    private final FieldSet<FieldDescriptor> extensions = FieldSet.newFieldSet();
+      extends GeneratedMessage
+      implements ExtendableMessageOrBuilder<MessageType> {
+
+    private final FieldSet<FieldDescriptor> extensions;
+
+    protected ExtendableMessage() {
+      this.extensions = FieldSet.newFieldSet();
+    }
+
+    protected ExtendableMessage(
+        ExtendableBuilder<MessageType, ?> builder) {
+      super(builder);
+      this.extensions = builder.buildExtensions();
+    }
 
     private void verifyExtensionContainingType(
         final GeneratedExtension<MessageType, ?> extension) {
@@ -330,13 +564,15 @@
     }
 
     /** Check if a singular extension is present. */
-    public final boolean hasExtension(
-        final GeneratedExtension<MessageType, ?> extension) {
+    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    public final <Type> boolean hasExtension(
+        final GeneratedExtension<MessageType, Type> extension) {
       verifyExtensionContainingType(extension);
       return extensions.hasField(extension.getDescriptor());
     }
 
     /** Get the number of elements in a repeated extension. */
+    //@Override (Java 1.6 override semantics, but we must support 1.5)
     public final <Type> int getExtensionCount(
         final GeneratedExtension<MessageType, List<Type>> extension) {
       verifyExtensionContainingType(extension);
@@ -345,6 +581,7 @@
     }
 
     /** Get the value of an extension. */
+    //@Override (Java 1.6 override semantics, but we must support 1.5)
     @SuppressWarnings("unchecked")
     public final <Type> Type getExtension(
         final GeneratedExtension<MessageType, Type> extension) {
@@ -367,6 +604,7 @@
     }
 
     /** Get one element of a repeated extension. */
+    //@Override (Java 1.6 override semantics, but we must support 1.5)
     @SuppressWarnings("unchecked")
     public final <Type> Type getExtension(
         final GeneratedExtension<MessageType, List<Type>> extension,
@@ -448,10 +686,14 @@
     // ---------------------------------------------------------------
     // Reflection
 
+    protected Map<FieldDescriptor, Object> getExtensionFields() {
+      return extensions.getAllFields();
+    }
+
     @Override
     public Map<FieldDescriptor, Object> getAllFields() {
       final Map<FieldDescriptor, Object> result = super.getAllFieldsMutable();
-      result.putAll(extensions.getAllFields());
+      result.putAll(getExtensionFields());
       return Collections.unmodifiableMap(result);
     }
 
@@ -556,9 +798,24 @@
   public abstract static class ExtendableBuilder<
         MessageType extends ExtendableMessage,
         BuilderType extends ExtendableBuilder>
-      extends Builder<BuilderType> {
+      extends Builder<BuilderType>
+      implements ExtendableMessageOrBuilder<MessageType> {
+
+    private FieldSet<FieldDescriptor> extensions = FieldSet.emptySet();
+
     protected ExtendableBuilder() {}
 
+    protected ExtendableBuilder(
+        BuilderParent parent) {
+      super(parent);
+    }
+
+    @Override
+    public BuilderType clear() {
+      extensions = FieldSet.emptySet();
+      return super.clear();
+    }
+
     // This is implemented here only to work around an apparent bug in the
     // Java compiler and/or build system.  See bug #1898463.  The mere presence
     // of this dummy clone() implementation makes it go away.
@@ -568,43 +825,84 @@
           "This is supposed to be overridden by subclasses.");
     }
 
-    @Override
-    protected abstract ExtendableMessage<MessageType> internalGetResult();
+    private void ensureExtensionsIsMutable() {
+      if (extensions.isImmutable()) {
+        extensions = extensions.clone();
+      }
+    }
+
+    private void verifyExtensionContainingType(
+        final GeneratedExtension<MessageType, ?> extension) {
+      if (extension.getDescriptor().getContainingType() !=
+          getDescriptorForType()) {
+        // This can only happen if someone uses unchecked operations.
+        throw new IllegalArgumentException(
+          "Extension is for type \"" +
+          extension.getDescriptor().getContainingType().getFullName() +
+          "\" which does not match message type \"" +
+          getDescriptorForType().getFullName() + "\".");
+      }
+    }
 
     /** Check if a singular extension is present. */
-    public final boolean hasExtension(
-        final GeneratedExtension<MessageType, ?> extension) {
-      return internalGetResult().hasExtension(extension);
+    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    public final <Type> boolean hasExtension(
+        final GeneratedExtension<MessageType, Type> extension) {
+      verifyExtensionContainingType(extension);
+      return extensions.hasField(extension.getDescriptor());
     }
 
     /** Get the number of elements in a repeated extension. */
+    //@Override (Java 1.6 override semantics, but we must support 1.5)
     public final <Type> int getExtensionCount(
         final GeneratedExtension<MessageType, List<Type>> extension) {
-      return internalGetResult().getExtensionCount(extension);
+      verifyExtensionContainingType(extension);
+      final FieldDescriptor descriptor = extension.getDescriptor();
+      return extensions.getRepeatedFieldCount(descriptor);
     }
 
     /** Get the value of an extension. */
+    //@Override (Java 1.6 override semantics, but we must support 1.5)
     public final <Type> Type getExtension(
         final GeneratedExtension<MessageType, Type> extension) {
-      return internalGetResult().getExtension(extension);
+      verifyExtensionContainingType(extension);
+      FieldDescriptor descriptor = extension.getDescriptor();
+      final Object value = extensions.getField(descriptor);
+      if (value == null) {
+        if (descriptor.isRepeated()) {
+          return (Type) Collections.emptyList();
+        } else if (descriptor.getJavaType() ==
+                   FieldDescriptor.JavaType.MESSAGE) {
+          return (Type) extension.getMessageDefaultInstance();
+        } else {
+          return (Type) extension.fromReflectionType(
+              descriptor.getDefaultValue());
+        }
+      } else {
+        return (Type) extension.fromReflectionType(value);
+      }
     }
 
     /** Get one element of a repeated extension. */
+    //@Override (Java 1.6 override semantics, but we must support 1.5)
     public final <Type> Type getExtension(
         final GeneratedExtension<MessageType, List<Type>> extension,
         final int index) {
-      return internalGetResult().getExtension(extension, index);
+      verifyExtensionContainingType(extension);
+      FieldDescriptor descriptor = extension.getDescriptor();
+      return (Type) extension.singularFromReflectionType(
+          extensions.getRepeatedField(descriptor, index));
     }
 
     /** Set the value of an extension. */
     public final <Type> BuilderType setExtension(
         final GeneratedExtension<MessageType, Type> extension,
         final Type value) {
-      final ExtendableMessage<MessageType> message = internalGetResult();
-      message.verifyExtensionContainingType(extension);
+      verifyExtensionContainingType(extension);
+      ensureExtensionsIsMutable();
       final FieldDescriptor descriptor = extension.getDescriptor();
-      message.extensions.setField(descriptor,
-                                  extension.toReflectionType(value));
+      extensions.setField(descriptor, extension.toReflectionType(value));
+      onChanged();
       return (BuilderType) this;
     }
 
@@ -612,12 +910,13 @@
     public final <Type> BuilderType setExtension(
         final GeneratedExtension<MessageType, List<Type>> extension,
         final int index, final Type value) {
-      final ExtendableMessage<MessageType> message = internalGetResult();
-      message.verifyExtensionContainingType(extension);
+      verifyExtensionContainingType(extension);
+      ensureExtensionsIsMutable();
       final FieldDescriptor descriptor = extension.getDescriptor();
-      message.extensions.setRepeatedField(
+      extensions.setRepeatedField(
         descriptor, index,
         extension.singularToReflectionType(value));
+      onChanged();
       return (BuilderType) this;
     }
 
@@ -625,23 +924,44 @@
     public final <Type> BuilderType addExtension(
         final GeneratedExtension<MessageType, List<Type>> extension,
         final Type value) {
-      final ExtendableMessage<MessageType> message = internalGetResult();
-      message.verifyExtensionContainingType(extension);
+      verifyExtensionContainingType(extension);
+      ensureExtensionsIsMutable();
       final FieldDescriptor descriptor = extension.getDescriptor();
-      message.extensions.addRepeatedField(
+      extensions.addRepeatedField(
           descriptor, extension.singularToReflectionType(value));
+      onChanged();
       return (BuilderType) this;
     }
 
     /** Clear an extension. */
     public final <Type> BuilderType clearExtension(
         final GeneratedExtension<MessageType, ?> extension) {
-      final ExtendableMessage<MessageType> message = internalGetResult();
-      message.verifyExtensionContainingType(extension);
-      message.extensions.clearField(extension.getDescriptor());
+      verifyExtensionContainingType(extension);
+      ensureExtensionsIsMutable();
+      extensions.clearField(extension.getDescriptor());
+      onChanged();
       return (BuilderType) this;
     }
 
+    /** Called by subclasses to check if all extensions are initialized. */
+    protected boolean extensionsAreInitialized() {
+      return extensions.isInitialized();
+    }
+
+    /**
+     * Called by the build code path to create a copy of the extensions for
+     * building the message.
+     */
+    private FieldSet<FieldDescriptor> buildExtensions() {
+      extensions.makeImmutable();
+      return extensions;
+    }
+
+    @Override
+    public boolean isInitialized() {
+      return super.isInitialized() && extensionsAreInitialized();
+    }
+
     /**
      * Called by subclasses to parse an unknown field or an extension.
      * @return {@code true} unless the tag is an end-group tag.
@@ -659,16 +979,73 @@
     // ---------------------------------------------------------------
     // Reflection
 
-    // We don't have to override the get*() methods here because they already
-    // just forward to the underlying message.
+    @Override
+    public Map<FieldDescriptor, Object> getAllFields() {
+      final Map<FieldDescriptor, Object> result = super.getAllFieldsMutable();
+      result.putAll(extensions.getAllFields());
+      return Collections.unmodifiableMap(result);
+    }
+
+    @Override
+    public Object getField(final FieldDescriptor field) {
+      if (field.isExtension()) {
+        verifyContainingType(field);
+        final Object value = extensions.getField(field);
+        if (value == null) {
+          if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+            // Lacking an ExtensionRegistry, we have no way to determine the
+            // extension's real type, so we return a DynamicMessage.
+            return DynamicMessage.getDefaultInstance(field.getMessageType());
+          } else {
+            return field.getDefaultValue();
+          }
+        } else {
+          return value;
+        }
+      } else {
+        return super.getField(field);
+      }
+    }
+
+    @Override
+    public int getRepeatedFieldCount(final FieldDescriptor field) {
+      if (field.isExtension()) {
+        verifyContainingType(field);
+        return extensions.getRepeatedFieldCount(field);
+      } else {
+        return super.getRepeatedFieldCount(field);
+      }
+    }
+
+    @Override
+    public Object getRepeatedField(final FieldDescriptor field,
+                                   final int index) {
+      if (field.isExtension()) {
+        verifyContainingType(field);
+        return extensions.getRepeatedField(field, index);
+      } else {
+        return super.getRepeatedField(field, index);
+      }
+    }
+
+    @Override
+    public boolean hasField(final FieldDescriptor field) {
+      if (field.isExtension()) {
+        verifyContainingType(field);
+        return extensions.hasField(field);
+      } else {
+        return super.hasField(field);
+      }
+    }
 
     @Override
     public BuilderType setField(final FieldDescriptor field,
                                 final Object value) {
       if (field.isExtension()) {
-        final ExtendableMessage<MessageType> message = internalGetResult();
-        message.verifyContainingType(field);
-        message.extensions.setField(field, value);
+        verifyContainingType(field);
+        ensureExtensionsIsMutable();
+        extensions.setField(field, value);
+        onChanged();
         return (BuilderType) this;
       } else {
         return super.setField(field, value);
@@ -678,9 +1055,10 @@
     @Override
     public BuilderType clearField(final FieldDescriptor field) {
       if (field.isExtension()) {
-        final ExtendableMessage<MessageType> message = internalGetResult();
-        message.verifyContainingType(field);
-        message.extensions.clearField(field);
+        verifyContainingType(field);
+        ensureExtensionsIsMutable();
+        extensions.clearField(field);
+        onChanged();
         return (BuilderType) this;
       } else {
         return super.clearField(field);
@@ -691,9 +1069,10 @@
     public BuilderType setRepeatedField(final FieldDescriptor field,
                                         final int index, final Object value) {
       if (field.isExtension()) {
-        final ExtendableMessage<MessageType> message = internalGetResult();
-        message.verifyContainingType(field);
-        message.extensions.setRepeatedField(field, index, value);
+        verifyContainingType(field);
+        ensureExtensionsIsMutable();
+        extensions.setRepeatedField(field, index, value);
+        onChanged();
         return (BuilderType) this;
       } else {
         return super.setRepeatedField(field, index, value);
@@ -704,9 +1083,10 @@
     public BuilderType addRepeatedField(final FieldDescriptor field,
                                         final Object value) {
       if (field.isExtension()) {
-        final ExtendableMessage<MessageType> message = internalGetResult();
-        message.verifyContainingType(field);
-        message.extensions.addRepeatedField(field, value);
+        verifyContainingType(field);
+        ensureExtensionsIsMutable();
+        extensions.addRepeatedField(field, value);
+        onChanged();
         return (BuilderType) this;
       } else {
         return super.addRepeatedField(field, value);
@@ -714,17 +1094,63 @@
     }
 
     protected final void mergeExtensionFields(final ExtendableMessage other) {
-      internalGetResult().extensions.mergeFrom(other.extensions);
+      ensureExtensionsIsMutable();
+      extensions.mergeFrom(other.extensions);
+      onChanged();
+    }
+
+    private void verifyContainingType(final FieldDescriptor field) {
+      if (field.getContainingType() != getDescriptorForType()) {
+        throw new IllegalArgumentException(
+          "FieldDescriptor does not match message type.");
+      }
     }
   }
 
   // -----------------------------------------------------------------
 
+  /**
+   * Gets the descriptor for an extension. The implementation depends on whether
+   * the extension is scoped in the top level of a file or scoped in a Message.
+   */
+  private static interface ExtensionDescriptorRetriever {
+    FieldDescriptor getDescriptor();
+  }
+
   /** For use by generated code only. */
   public static <ContainingType extends Message, Type>
       GeneratedExtension<ContainingType, Type>
-      newGeneratedExtension() {
-    return new GeneratedExtension<ContainingType, Type>();
+      newMessageScopedGeneratedExtension(final Message scope,
+                                         final int descriptorIndex,
+                                         final Class singularType,
+                                         final Message defaultInstance) {
+    // For extensions scoped within a Message, we use the Message to resolve
+    // the outer class's descriptor, from which the extension descriptor is
+    // obtained.
+    return new GeneratedExtension<ContainingType, Type>(
+        new ExtensionDescriptorRetriever() {
+          @Override
+          public FieldDescriptor getDescriptor() {
+            return scope.getDescriptorForType().getExtensions()
+                .get(descriptorIndex);
+          }
+        },
+        singularType,
+        defaultInstance);
+  }
+
+  /** For use by generated code only. */
+  public static <ContainingType extends Message, Type>
+     GeneratedExtension<ContainingType, Type>
+     newFileScopedGeneratedExtension(final Class singularType,
+                                     final Message defaultInstance) {
+    // For extensions scoped within a file, we rely on the outer class's
+    // static initializer to call internalInit() on the extension when the
+    // descriptor is available.
+    return new GeneratedExtension<ContainingType, Type>(
+        null,  // ExtensionDescriptorRetriever is initialized in internalInit();
+        singularType,
+        defaultInstance);
   }
 
   /**
@@ -757,64 +1183,67 @@
     // TODO(kenton):  Find ways to avoid using Java reflection within this
     //   class.  Also try to avoid suppressing unchecked warnings.
 
-    // We can't always initialize a GeneratedExtension when we first construct
-    // it due to initialization order difficulties (namely, the descriptor may
-    // not have been constructed yet, since it is often constructed by the
-    // initializer of a separate module).  So, we construct an uninitialized
-    // GeneratedExtension once, then call internalInit() on it later.  Generated
-    // code will always call internalInit() on all extensions as part of the
-    // static initialization code, and internalInit() throws an exception if
-    // called more than once, so this method is useless to users.
-    private GeneratedExtension() {}
-
-    /** For use by generated code only. */
-    public void internalInit(final FieldDescriptor descriptor,
-                             final Class<?> type) {
-      if (this.descriptor != null) {
-        throw new IllegalStateException("Already initialized.");
-      }
-
-      if (!descriptor.isExtension()) {
+    // We can't always initialize the descriptor of a GeneratedExtension when
+    // we first construct it due to initialization order difficulties (namely,
+    // the descriptor may not have been constructed yet, since it is often
+    // constructed by the initializer of a separate module).
+    //
+    // In the case of nested extensions, we initialize the
+    // ExtensionDescriptorRetriever with an instance that uses the scoping
+    // Message's default instance to retrieve the extension's descriptor.
+    //
+    // In the case of non-nested extensions, we initialize the
+    // ExtensionDescriptorRetriever to null and rely on the outer class's static
+    // initializer to call internalInit() after the descriptor has been parsed.
+    private GeneratedExtension(ExtensionDescriptorRetriever descriptorRetriever,
+                               Class singularType,
+                               Message messageDefaultInstance) {
+      if (Message.class.isAssignableFrom(singularType) &&
+          !singularType.isInstance(messageDefaultInstance)) {
         throw new IllegalArgumentException(
-          "GeneratedExtension given a regular (non-extension) field.");
+            "Bad messageDefaultInstance for " + singularType.getName());
       }
+      this.descriptorRetriever = descriptorRetriever;
+      this.singularType = singularType;
+      this.messageDefaultInstance = messageDefaultInstance;
 
-      this.descriptor = descriptor;
-      this.type = type;
-
-      switch (descriptor.getJavaType()) {
-        case MESSAGE:
-          enumValueOf = null;
-          enumGetValueDescriptor = null;
-          messageDefaultInstance =
-            (Message) invokeOrDie(getMethodOrDie(type, "getDefaultInstance"),
-                                  null);
-          if (messageDefaultInstance == null) {
-            throw new IllegalStateException(
-                type.getName() + ".getDefaultInstance() returned null.");
-          }
-          break;
-        case ENUM:
-          enumValueOf = getMethodOrDie(type, "valueOf",
-                                       EnumValueDescriptor.class);
-          enumGetValueDescriptor = getMethodOrDie(type, "getValueDescriptor");
-          messageDefaultInstance = null;
-          break;
-        default:
-          enumValueOf = null;
-          enumGetValueDescriptor = null;
-          messageDefaultInstance = null;
-          break;
+      if (ProtocolMessageEnum.class.isAssignableFrom(singularType)) {
+        this.enumValueOf = getMethodOrDie(singularType, "valueOf",
+                                          EnumValueDescriptor.class);
+        this.enumGetValueDescriptor =
+            getMethodOrDie(singularType, "getValueDescriptor");
+      } else {
+        this.enumValueOf = null;
+        this.enumGetValueDescriptor = null;
       }
     }
 
-    private FieldDescriptor descriptor;
-    private Class<?> type;
-    private Method enumValueOf;
-    private Method enumGetValueDescriptor;
-    private Message messageDefaultInstance;
+    /** For use by generated code only. */
+    public void internalInit(final FieldDescriptor descriptor) {
+      if (descriptorRetriever != null) {
+        throw new IllegalStateException("Already initialized.");
+      }
+      descriptorRetriever = new ExtensionDescriptorRetriever() {
+          @Override
+          public FieldDescriptor getDescriptor() {
+            return descriptor;
+          }
+        };
+    }
 
-    public FieldDescriptor getDescriptor() { return descriptor; }
+    private ExtensionDescriptorRetriever descriptorRetriever;
+    private final Class singularType;
+    private final Message messageDefaultInstance;
+    private final Method enumValueOf;
+    private final Method enumGetValueDescriptor;
+
+    public FieldDescriptor getDescriptor() {
+      if (descriptorRetriever == null) {
+        throw new IllegalStateException(
+            "getDescriptor() called before internalInit()");
+      }
+      return descriptorRetriever.getDescriptor();
+    }
 
     /**
      * If the extension is an embedded message or group, returns the default
@@ -832,6 +1261,7 @@
      */
     @SuppressWarnings("unchecked")
     private Object fromReflectionType(final Object value) {
+      FieldDescriptor descriptor = getDescriptor();
       if (descriptor.isRepeated()) {
         if (descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE ||
             descriptor.getJavaType() == FieldDescriptor.JavaType.ENUM) {
@@ -854,9 +1284,10 @@
      * type, this converts a single element.
      */
     private Object singularFromReflectionType(final Object value) {
+      FieldDescriptor descriptor = getDescriptor();
       switch (descriptor.getJavaType()) {
         case MESSAGE:
-          if (type.isInstance(value)) {
+          if (singularType.isInstance(value)) {
             return value;
           } else {
             // It seems the copy of the embedded message stored inside the
@@ -883,6 +1314,7 @@
      */
     @SuppressWarnings("unchecked")
     private Object toReflectionType(final Object value) {
+      FieldDescriptor descriptor = getDescriptor();
       if (descriptor.isRepeated()) {
         if (descriptor.getJavaType() == FieldDescriptor.JavaType.ENUM) {
           // Must convert the whole list.
@@ -904,6 +1336,7 @@
      * type, this converts a single element.
      */
     private Object singularToReflectionType(final Object value) {
+      FieldDescriptor descriptor = getDescriptor();
       switch (descriptor.getJavaType()) {
         case ENUM:
           return invokeOrDie(enumGetValueDescriptor, value);
@@ -1025,13 +1458,17 @@
      */
     private interface FieldAccessor {
       Object get(GeneratedMessage message);
+      Object get(GeneratedMessage.Builder builder);
       void set(Builder builder, Object value);
       Object getRepeated(GeneratedMessage message, int index);
+      Object getRepeated(GeneratedMessage.Builder builder, int index);
       void setRepeated(Builder builder,
                        int index, Object value);
       void addRepeated(Builder builder, Object value);
       boolean has(GeneratedMessage message);
+      boolean has(GeneratedMessage.Builder builder);
       int getRepeatedCount(GeneratedMessage message);
+      int getRepeatedCount(GeneratedMessage.Builder builder);
       void clear(Builder builder);
       Message.Builder newBuilder();
     }
@@ -1044,10 +1481,13 @@
           final Class<? extends GeneratedMessage> messageClass,
           final Class<? extends Builder> builderClass) {
         getMethod = getMethodOrDie(messageClass, "get" + camelCaseName);
+        getMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName);
         type = getMethod.getReturnType();
         setMethod = getMethodOrDie(builderClass, "set" + camelCaseName, type);
         hasMethod =
-          getMethodOrDie(messageClass, "has" + camelCaseName);
+            getMethodOrDie(messageClass, "has" + camelCaseName);
+        hasMethodBuilder =
+            getMethodOrDie(builderClass, "has" + camelCaseName);
         clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName);
       }
 
@@ -1056,13 +1496,18 @@
       //   checks.
       protected final Class<?> type;
       protected final Method getMethod;
+      protected final Method getMethodBuilder;
       protected final Method setMethod;
       protected final Method hasMethod;
+      protected final Method hasMethodBuilder;
       protected final Method clearMethod;
 
       public Object get(final GeneratedMessage message) {
         return invokeOrDie(getMethod, message);
       }
+      public Object get(GeneratedMessage.Builder builder) {
+        return invokeOrDie(getMethodBuilder, builder);
+      }
       public void set(final Builder builder, final Object value) {
         invokeOrDie(setMethod, builder, value);
       }
@@ -1071,6 +1516,10 @@
         throw new UnsupportedOperationException(
           "getRepeatedField() called on a singular field.");
       }
+      public Object getRepeated(GeneratedMessage.Builder builder, int index) {
+        throw new UnsupportedOperationException(
+          "getRepeatedField() called on a singular field.");
+      }
       public void setRepeated(final Builder builder,
                               final int index, final Object value) {
         throw new UnsupportedOperationException(
@@ -1083,10 +1532,17 @@
       public boolean has(final GeneratedMessage message) {
         return (Boolean) invokeOrDie(hasMethod, message);
       }
+      public boolean has(GeneratedMessage.Builder builder) {
+        return (Boolean) invokeOrDie(hasMethodBuilder, builder);
+      }
       public int getRepeatedCount(final GeneratedMessage message) {
         throw new UnsupportedOperationException(
           "getRepeatedFieldSize() called on a singular field.");
       }
+      public int getRepeatedCount(GeneratedMessage.Builder builder) {
+        throw new UnsupportedOperationException(
+          "getRepeatedFieldSize() called on a singular field.");
+      }
       public void clear(final Builder builder) {
         invokeOrDie(clearMethod, builder);
       }
@@ -1097,38 +1553,51 @@
     }
 
     private static class RepeatedFieldAccessor implements FieldAccessor {
+      protected final Class type;
+      protected final Method getMethod;
+      protected final Method getMethodBuilder;
+      protected final Method getRepeatedMethod;
+      protected final Method getRepeatedMethodBuilder;
+      protected final Method setRepeatedMethod;
+      protected final Method addRepeatedMethod;
+      protected final Method getCountMethod;
+      protected final Method getCountMethodBuilder;
+      protected final Method clearMethod;
+
       RepeatedFieldAccessor(
           final FieldDescriptor descriptor, final String camelCaseName,
           final Class<? extends GeneratedMessage> messageClass,
           final Class<? extends Builder> builderClass) {
         getMethod = getMethodOrDie(messageClass,
                                    "get" + camelCaseName + "List");
+        getMethodBuilder = getMethodOrDie(builderClass,
+                                   "get" + camelCaseName + "List");
+
 
         getRepeatedMethod =
-          getMethodOrDie(messageClass, "get" + camelCaseName, Integer.TYPE);
+            getMethodOrDie(messageClass, "get" + camelCaseName, Integer.TYPE);
+        getRepeatedMethodBuilder =
+            getMethodOrDie(builderClass, "get" + camelCaseName, Integer.TYPE);
         type = getRepeatedMethod.getReturnType();
         setRepeatedMethod =
-          getMethodOrDie(builderClass, "set" + camelCaseName,
-                         Integer.TYPE, type);
+            getMethodOrDie(builderClass, "set" + camelCaseName,
+                           Integer.TYPE, type);
         addRepeatedMethod =
-          getMethodOrDie(builderClass, "add" + camelCaseName, type);
+            getMethodOrDie(builderClass, "add" + camelCaseName, type);
         getCountMethod =
-          getMethodOrDie(messageClass, "get" + camelCaseName + "Count");
+            getMethodOrDie(messageClass, "get" + camelCaseName + "Count");
+        getCountMethodBuilder =
+            getMethodOrDie(builderClass, "get" + camelCaseName + "Count");
 
         clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName);
       }
 
-      protected final Class<?> type;
-      protected final Method getMethod;
-      protected final Method getRepeatedMethod;
-      protected final Method setRepeatedMethod;
-      protected final Method addRepeatedMethod;
-      protected final Method getCountMethod;
-      protected final Method clearMethod;
-
       public Object get(final GeneratedMessage message) {
         return invokeOrDie(getMethod, message);
       }
+      public Object get(GeneratedMessage.Builder builder) {
+        return invokeOrDie(getMethodBuilder, builder);
+      }
       public void set(final Builder builder, final Object value) {
         // Add all the elements individually.  This serves two purposes:
         // 1) Verifies that each element has the correct type.
@@ -1143,6 +1612,9 @@
                                 final int index) {
         return invokeOrDie(getRepeatedMethod, message, index);
       }
+      public Object getRepeated(GeneratedMessage.Builder builder, int index) {
+        return invokeOrDie(getRepeatedMethodBuilder, builder, index);
+      }
       public void setRepeated(final Builder builder,
                               final int index, final Object value) {
         invokeOrDie(setRepeatedMethod, builder, index, value);
@@ -1154,9 +1626,16 @@
         throw new UnsupportedOperationException(
           "hasField() called on a singular field.");
       }
+      public boolean has(GeneratedMessage.Builder builder) {
+        throw new UnsupportedOperationException(
+          "hasField() called on a singular field.");
+      }
       public int getRepeatedCount(final GeneratedMessage message) {
         return (Integer) invokeOrDie(getCountMethod, message);
       }
+      public int getRepeatedCount(GeneratedMessage.Builder builder) {
+        return (Integer) invokeOrDie(getCountMethodBuilder, builder);
+      }
       public void clear(final Builder builder) {
         invokeOrDie(clearMethod, builder);
       }
@@ -1189,6 +1668,12 @@
       public Object get(final GeneratedMessage message) {
         return invokeOrDie(getValueDescriptorMethod, super.get(message));
       }
+
+      @Override
+      public Object get(final GeneratedMessage.Builder builder) {
+        return invokeOrDie(getValueDescriptorMethod, super.get(builder));
+      }
+
       @Override
       public void set(final Builder builder, final Object value) {
         super.set(builder, invokeOrDie(valueOfMethod, null, value));
@@ -1221,6 +1706,17 @@
         }
         return Collections.unmodifiableList(newList);
       }
+
+      @Override
+      @SuppressWarnings("unchecked")
+      public Object get(final GeneratedMessage.Builder builder) {
+        final List newList = new ArrayList();
+        for (final Object element : (List) super.get(builder)) {
+          newList.add(invokeOrDie(getValueDescriptorMethod, element));
+        }
+        return Collections.unmodifiableList(newList);
+      }
+
       @Override
       public Object getRepeated(final GeneratedMessage message,
                                 final int index) {
@@ -1228,6 +1724,12 @@
           super.getRepeated(message, index));
       }
       @Override
+      public Object getRepeated(final GeneratedMessage.Builder builder,
+                                final int index) {
+        return invokeOrDie(getValueDescriptorMethod,
+          super.getRepeated(builder, index));
+      }
+      @Override
       public void setRepeated(final Builder builder,
                               final int index, final Object value) {
         super.setRepeated(builder, index, invokeOrDie(valueOfMethod, null,
@@ -1318,4 +1820,14 @@
       }
     }
   }
+
+  /**
+   * Replaces this object in the output stream with a serialized form.
+   * Part of Java's serialization magic.  Generated sub-classes must override
+   * this method by calling <code>return super.writeReplace();</code>
+   * @return a SerializedForm of this message
+   */
+  protected Object writeReplace() throws ObjectStreamException {
+    return new GeneratedMessageLite.SerializedForm(this);
+  }
 }
diff --git a/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java b/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
index 9a799b4..30a7571 100644
--- a/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
+++ b/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
@@ -31,6 +31,10 @@
 package com.google.protobuf;
 
 import java.io.IOException;
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
@@ -41,8 +45,14 @@
  *
  * @author kenton@google.com Kenton Varda
  */
-public abstract class GeneratedMessageLite extends AbstractMessageLite {
-  protected GeneratedMessageLite() {}
+public abstract class GeneratedMessageLite extends AbstractMessageLite
+    implements Serializable {
+
+  protected GeneratedMessageLite() {
+  }
+
+  protected GeneratedMessageLite(Builder builder) {
+  }
 
   @SuppressWarnings("unchecked")
   public abstract static class Builder<MessageType extends GeneratedMessageLite,
@@ -50,6 +60,11 @@
       extends AbstractMessageLite.Builder<BuilderType> {
     protected Builder() {}
 
+    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    public BuilderType clear() {
+      return (BuilderType) this;
+    }
+
     // This is implemented here only to work around an apparent bug in the
     // Java compiler and/or build system.  See bug #1898463.  The mere presence
     // of this dummy clone() implementation makes it go away.
@@ -66,12 +81,6 @@
     public abstract MessageType getDefaultInstanceForType();
 
     /**
-     * Get the message being built.  We don't just pass this to the
-     * constructor because it becomes null when build() is called.
-     */
-    protected abstract MessageType internalGetResult();
-
-    /**
      * Called by subclasses to parse an unknown field.
      * @return {@code true} unless the tag is an end-group tag.
      */
@@ -87,14 +96,45 @@
   // Extensions-related stuff
 
   /**
+   * Lite equivalent of {@link com.google.protobuf.GeneratedMessage.ExtendableMessageOrBuilder}.
+   */
+  public interface ExtendableMessageOrBuilder<
+      MessageType extends ExtendableMessage> extends MessageLiteOrBuilder {
+
+    /** Check if a singular extension is present. */
+    <Type> boolean hasExtension(
+        GeneratedExtension<MessageType, Type> extension);
+
+    /** Get the number of elements in a repeated extension. */
+    <Type> int getExtensionCount(
+        GeneratedExtension<MessageType, List<Type>> extension);
+
+    /** Get the value of an extension. */
+    <Type> Type getExtension(GeneratedExtension<MessageType, Type> extension);
+
+    /** Get one element of a repeated extension. */
+    <Type> Type getExtension(
+        GeneratedExtension<MessageType, List<Type>> extension,
+        int index);
+  }
+
+  /**
    * Lite equivalent of {@link GeneratedMessage.ExtendableMessage}.
    */
   public abstract static class ExtendableMessage<
         MessageType extends ExtendableMessage<MessageType>>
-      extends GeneratedMessageLite {
-    protected ExtendableMessage() {}
-    private final FieldSet<ExtensionDescriptor> extensions =
-        FieldSet.newFieldSet();
+      extends GeneratedMessageLite
+      implements ExtendableMessageOrBuilder<MessageType> {
+
+    private final FieldSet<ExtensionDescriptor> extensions;
+
+    protected ExtendableMessage() {
+      this.extensions = FieldSet.newFieldSet();
+    }
+
+    protected ExtendableMessage(ExtendableBuilder<MessageType, ?> builder) {
+      this.extensions = builder.buildExtensions();
+    }
 
     private void verifyExtensionContainingType(
         final GeneratedExtension<MessageType, ?> extension) {
@@ -108,13 +148,15 @@
     }
 
     /** Check if a singular extension is present. */
-    public final boolean hasExtension(
-        final GeneratedExtension<MessageType, ?> extension) {
+    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    public final <Type> boolean hasExtension(
+        final GeneratedExtension<MessageType, Type> extension) {
       verifyExtensionContainingType(extension);
       return extensions.hasField(extension.descriptor);
     }
 
     /** Get the number of elements in a repeated extension. */
+    //@Override (Java 1.6 override semantics, but we must support 1.5)
     public final <Type> int getExtensionCount(
         final GeneratedExtension<MessageType, List<Type>> extension) {
       verifyExtensionContainingType(extension);
@@ -122,6 +164,7 @@
     }
 
     /** Get the value of an extension. */
+    //@Override (Java 1.6 override semantics, but we must support 1.5)
     @SuppressWarnings("unchecked")
     public final <Type> Type getExtension(
         final GeneratedExtension<MessageType, Type> extension) {
@@ -135,6 +178,7 @@
     }
 
     /** Get one element of a repeated extension. */
+    //@Override (Java 1.6 override semantics, but we must support 1.5)
     @SuppressWarnings("unchecked")
     public final <Type> Type getExtension(
         final GeneratedExtension<MessageType, List<Type>> extension,
@@ -214,9 +258,88 @@
   public abstract static class ExtendableBuilder<
         MessageType extends ExtendableMessage<MessageType>,
         BuilderType extends ExtendableBuilder<MessageType, BuilderType>>
-      extends Builder<MessageType, BuilderType> {
+      extends Builder<MessageType, BuilderType>
+      implements ExtendableMessageOrBuilder<MessageType> {
     protected ExtendableBuilder() {}
 
+    private FieldSet<ExtensionDescriptor> extensions = FieldSet.emptySet();
+    private boolean extensionsIsMutable;
+
+    @Override
+    public BuilderType clear() {
+      extensions.clear();
+      extensionsIsMutable = false;
+      return super.clear();
+    }
+
+    private void ensureExtensionsIsMutable() {
+      if (!extensionsIsMutable) {
+        extensions = extensions.clone();
+        extensionsIsMutable = true;
+      }
+    }
+
+    /**
+     * Called by the build code path to create a copy of the extensions for
+     * building the message.
+     */
+    private FieldSet<ExtensionDescriptor> buildExtensions() {
+      extensions.makeImmutable();
+      extensionsIsMutable = false;
+      return extensions;
+    }
+
+    private void verifyExtensionContainingType(
+        final GeneratedExtension<MessageType, ?> extension) {
+      if (extension.getContainingTypeDefaultInstance() !=
+          getDefaultInstanceForType()) {
+        // This can only happen if someone uses unchecked operations.
+        throw new IllegalArgumentException(
+          "This extension is for a different message type.  Please make " +
+          "sure that you are not suppressing any generics type warnings.");
+      }
+    }
+
+    /** Check if a singular extension is present. */
+    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    public final <Type> boolean hasExtension(
+        final GeneratedExtension<MessageType, Type> extension) {
+      verifyExtensionContainingType(extension);
+      return extensions.hasField(extension.descriptor);
+    }
+
+    /** Get the number of elements in a repeated extension. */
+    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    public final <Type> int getExtensionCount(
+        final GeneratedExtension<MessageType, List<Type>> extension) {
+      verifyExtensionContainingType(extension);
+      return extensions.getRepeatedFieldCount(extension.descriptor);
+    }
+
+    /** Get the value of an extension. */
+    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    @SuppressWarnings("unchecked")
+    public final <Type> Type getExtension(
+        final GeneratedExtension<MessageType, Type> extension) {
+      verifyExtensionContainingType(extension);
+      final Object value = extensions.getField(extension.descriptor);
+      if (value == null) {
+        return extension.defaultValue;
+      } else {
+        return (Type) value;
+      }
+    }
+
+    /** Get one element of a repeated extension. */
+    @SuppressWarnings("unchecked")
+    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    public final <Type> Type getExtension(
+        final GeneratedExtension<MessageType, List<Type>> extension,
+        final int index) {
+      verifyExtensionContainingType(extension);
+      return (Type) extensions.getRepeatedField(extension.descriptor, index);
+    }
+
     // This is implemented here only to work around an apparent bug in the
     // Java compiler and/or build system.  See bug #1898463.  The mere presence
     // of this dummy clone() implementation makes it go away.
@@ -226,41 +349,13 @@
           "This is supposed to be overridden by subclasses.");
     }
 
-    @Override
-    protected abstract MessageType internalGetResult();
-
-    /** Check if a singular extension is present. */
-    public final boolean hasExtension(
-        final GeneratedExtension<MessageType, ?> extension) {
-      return internalGetResult().hasExtension(extension);
-    }
-
-    /** Get the number of elements in a repeated extension. */
-    public final <Type> int getExtensionCount(
-        final GeneratedExtension<MessageType, List<Type>> extension) {
-      return internalGetResult().getExtensionCount(extension);
-    }
-
-    /** Get the value of an extension. */
-    public final <Type> Type getExtension(
-        final GeneratedExtension<MessageType, Type> extension) {
-      return internalGetResult().getExtension(extension);
-    }
-
-    /** Get one element of a repeated extension. */
-    public final <Type> Type getExtension(
-        final GeneratedExtension<MessageType, List<Type>> extension,
-        final int index) {
-      return internalGetResult().getExtension(extension, index);
-    }
-
     /** Set the value of an extension. */
     public final <Type> BuilderType setExtension(
         final GeneratedExtension<MessageType, Type> extension,
         final Type value) {
-      final ExtendableMessage<MessageType> message = internalGetResult();
-      message.verifyExtensionContainingType(extension);
-      message.extensions.setField(extension.descriptor, value);
+      verifyExtensionContainingType(extension);
+      ensureExtensionsIsMutable();
+      extensions.setField(extension.descriptor, value);
       return (BuilderType) this;
     }
 
@@ -268,9 +363,9 @@
     public final <Type> BuilderType setExtension(
         final GeneratedExtension<MessageType, List<Type>> extension,
         final int index, final Type value) {
-      final ExtendableMessage<MessageType> message = internalGetResult();
-      message.verifyExtensionContainingType(extension);
-      message.extensions.setRepeatedField(extension.descriptor, index, value);
+      verifyExtensionContainingType(extension);
+      ensureExtensionsIsMutable();
+      extensions.setRepeatedField(extension.descriptor, index, value);
       return (BuilderType) this;
     }
 
@@ -278,21 +373,26 @@
     public final <Type> BuilderType addExtension(
         final GeneratedExtension<MessageType, List<Type>> extension,
         final Type value) {
-      final ExtendableMessage<MessageType> message = internalGetResult();
-      message.verifyExtensionContainingType(extension);
-      message.extensions.addRepeatedField(extension.descriptor, value);
+      verifyExtensionContainingType(extension);
+      ensureExtensionsIsMutable();
+      extensions.addRepeatedField(extension.descriptor, value);
       return (BuilderType) this;
     }
 
     /** Clear an extension. */
     public final <Type> BuilderType clearExtension(
         final GeneratedExtension<MessageType, ?> extension) {
-      final ExtendableMessage<MessageType> message = internalGetResult();
-      message.verifyExtensionContainingType(extension);
-      message.extensions.clearField(extension.descriptor);
+      verifyExtensionContainingType(extension);
+      ensureExtensionsIsMutable();
+      extensions.clearField(extension.descriptor);
       return (BuilderType) this;
     }
 
+    /** Called by subclasses to check if all extensions are initialized. */
+    protected boolean extensionsAreInitialized() {
+      return extensions.isInitialized();
+    }
+
     /**
      * Called by subclasses to parse an unknown field or an extension.
      * @return {@code true} unless the tag is an end-group tag.
@@ -302,9 +402,6 @@
         final CodedInputStream input,
         final ExtensionRegistryLite extensionRegistry,
         final int tag) throws IOException {
-      final FieldSet<ExtensionDescriptor> extensions =
-          ((ExtendableMessage) internalGetResult()).extensions;
-
       final int wireType = WireFormat.getTagWireType(tag);
       final int fieldNumber = WireFormat.getTagFieldNumber(tag);
 
@@ -347,6 +444,7 @@
               // enum, drop it (don't even add it to unknownFields).
               return true;
             }
+            ensureExtensionsIsMutable();
             extensions.addRepeatedField(extension.descriptor, value);
           }
         } else {
@@ -354,6 +452,7 @@
             final Object value =
               FieldSet.readPrimitiveField(input,
                                           extension.descriptor.getLiteType());
+            ensureExtensionsIsMutable();
             extensions.addRepeatedField(extension.descriptor, value);
           }
         }
@@ -400,8 +499,10 @@
         }
 
         if (extension.descriptor.isRepeated()) {
+          ensureExtensionsIsMutable();
           extensions.addRepeatedField(extension.descriptor, value);
         } else {
+          ensureExtensionsIsMutable();
           extensions.setField(extension.descriptor, value);
         }
       }
@@ -410,8 +511,8 @@
     }
 
     protected final void mergeExtensionFields(final MessageType other) {
-      ((ExtendableMessage) internalGetResult()).extensions.mergeFrom(
-          ((ExtendableMessage) other).extensions);
+      ensureExtensionsIsMutable();
+      extensions.mergeFrom(((ExtendableMessage) other).extensions);
     }
   }
 
@@ -420,8 +521,40 @@
   /** For use by generated code only. */
   public static <ContainingType extends MessageLite, Type>
       GeneratedExtension<ContainingType, Type>
-      newGeneratedExtension() {
-    return new GeneratedExtension<ContainingType, Type>();
+          newSingularGeneratedExtension(
+              final ContainingType containingTypeDefaultInstance,
+              final Type defaultValue,
+              final MessageLite messageDefaultInstance,
+              final Internal.EnumLiteMap<?> enumTypeMap,
+              final int number,
+              final WireFormat.FieldType type) {
+    return new GeneratedExtension<ContainingType, Type>(
+        containingTypeDefaultInstance,
+        defaultValue,
+        messageDefaultInstance,
+        new ExtensionDescriptor(enumTypeMap, number, type,
+                                false /* isRepeated */,
+                                false /* isPacked */));
+  }
+
+  /** For use by generated code only. */
+  public static <ContainingType extends MessageLite, Type>
+      GeneratedExtension<ContainingType, Type>
+          newRepeatedGeneratedExtension(
+              final ContainingType containingTypeDefaultInstance,
+              final MessageLite messageDefaultInstance,
+              final Internal.EnumLiteMap<?> enumTypeMap,
+              final int number,
+              final WireFormat.FieldType type,
+              final boolean isPacked) {
+    @SuppressWarnings("unchecked")  // Subclasses ensure Type is a List
+    Type emptyList = (Type) Collections.emptyList();
+    return new GeneratedExtension<ContainingType, Type>(
+        containingTypeDefaultInstance,
+        emptyList,
+        messageDefaultInstance,
+        new ExtensionDescriptor(
+            enumTypeMap, number, type, true /* isRepeated */, isPacked));
   }
 
   private static final class ExtensionDescriptor
@@ -489,60 +622,33 @@
    */
   public static final class GeneratedExtension<
       ContainingType extends MessageLite, Type> {
-    // We can't always initialize a GeneratedExtension when we first construct
-    // it due to initialization order difficulties (namely, the default
-    // instances may not have been constructed yet).  So, we construct an
-    // uninitialized GeneratedExtension once, then call internalInit() on it
-    // later.  Generated code will always call internalInit() on all extensions
-    // as part of the static initialization code, and internalInit() throws an
-    // exception if called more than once, so this method is useless to users.
-    private GeneratedExtension() {}
 
-    private void internalInit(
+    private GeneratedExtension(
         final ContainingType containingTypeDefaultInstance,
         final Type defaultValue,
         final MessageLite messageDefaultInstance,
         final ExtensionDescriptor descriptor) {
+      // Defensive checks to verify the correct initialization order of
+      // GeneratedExtensions and their related GeneratedMessages.
+      if (containingTypeDefaultInstance == null) {
+        throw new IllegalArgumentException(
+            "Null containingTypeDefaultInstance");
+      }
+      if (descriptor.getLiteType() == WireFormat.FieldType.MESSAGE &&
+          messageDefaultInstance == null) {
+        throw new IllegalArgumentException(
+            "Null messageDefaultInstance");
+      }
       this.containingTypeDefaultInstance = containingTypeDefaultInstance;
       this.defaultValue = defaultValue;
       this.messageDefaultInstance = messageDefaultInstance;
       this.descriptor = descriptor;
     }
 
-    /** For use by generated code only. */
-    public void internalInitSingular(
-        final ContainingType containingTypeDefaultInstance,
-        final Type defaultValue,
-        final MessageLite messageDefaultInstance,
-        final Internal.EnumLiteMap<?> enumTypeMap,
-        final int number,
-        final WireFormat.FieldType type) {
-      internalInit(
-        containingTypeDefaultInstance, defaultValue, messageDefaultInstance,
-        new ExtensionDescriptor(enumTypeMap, number, type,
-          false /* isRepeated */, false /* isPacked */));
-    }
-
-    /** For use by generated code only. */
-    @SuppressWarnings("unchecked")
-    public void internalInitRepeated(
-        final ContainingType containingTypeDefaultInstance,
-        final MessageLite messageDefaultInstance,
-        final Internal.EnumLiteMap<?> enumTypeMap,
-        final int number,
-        final WireFormat.FieldType type,
-        final boolean isPacked) {
-      internalInit(
-        containingTypeDefaultInstance, (Type) Collections.emptyList(),
-        messageDefaultInstance,
-        new ExtensionDescriptor(
-          enumTypeMap, number, type, true /* isRepeated */, isPacked));
-    }
-
-    private ContainingType containingTypeDefaultInstance;
-    private Type defaultValue;
-    private MessageLite messageDefaultInstance;
-    private ExtensionDescriptor descriptor;
+    private final ContainingType containingTypeDefaultInstance;
+    private final Type defaultValue;
+    private final MessageLite messageDefaultInstance;
+    private final ExtensionDescriptor descriptor;
 
     /**
      * Default instance of the type being extended, used to identify that type.
@@ -564,4 +670,61 @@
       return messageDefaultInstance;
     }
   }
+
+  /**
+   * A serialized (serializable) form of the generated message.  Stores the
+   * message as a class name and a byte array.
+   */
+  static final class SerializedForm implements Serializable {
+    private static final long serialVersionUID = 0L;
+
+    private String messageClassName;
+    private byte[] asBytes;
+
+    /**
+     * Creates the serialized form by calling {@link com.google.protobuf.MessageLite#toByteArray}.
+     * @param regularForm the message to serialize
+     */
+    SerializedForm(MessageLite regularForm) {
+      messageClassName = regularForm.getClass().getName();
+      asBytes = regularForm.toByteArray();
+    }
+
+    /**
+     * When read from an ObjectInputStream, this method converts this object
+     * back to the regular form.  Part of Java's serialization magic.
+     * @return a GeneratedMessage of the type that was serialized
+     */
+    @SuppressWarnings("unchecked")
+    protected Object readResolve() throws ObjectStreamException {
+      try {
+        Class messageClass = Class.forName(messageClassName);
+        Method newBuilder = messageClass.getMethod("newBuilder");
+        MessageLite.Builder builder =
+            (MessageLite.Builder) newBuilder.invoke(null);
+        builder.mergeFrom(asBytes);
+        return builder.buildPartial();
+      } catch (ClassNotFoundException e) {
+        throw new RuntimeException("Unable to find proto buffer class", e);
+      } catch (NoSuchMethodException e) {
+        throw new RuntimeException("Unable to find newBuilder method", e);
+      } catch (IllegalAccessException e) {
+        throw new RuntimeException("Unable to call newBuilder method", e);
+      } catch (InvocationTargetException e) {
+        throw new RuntimeException("Error calling newBuilder", e.getCause());
+      } catch (InvalidProtocolBufferException e) {
+        throw new RuntimeException("Unable to understand proto buffer", e);
+      }
+    }
+  }
+
+  /**
+   * Replaces this object in the output stream with a serialized form.
+   * Part of Java's serialization magic.  Generated sub-classes must override
+   * this method by calling <code>return super.writeReplace();</code>
+   * @return a SerializedForm of this message
+   */
+  protected Object writeReplace() throws ObjectStreamException {
+    return new SerializedForm(this);
+  }
 }
diff --git a/java/src/main/java/com/google/protobuf/Internal.java b/java/src/main/java/com/google/protobuf/Internal.java
index 965465e..05eab57 100644
--- a/java/src/main/java/com/google/protobuf/Internal.java
+++ b/java/src/main/java/com/google/protobuf/Internal.java
@@ -100,6 +100,91 @@
   }
 
   /**
+   * Helper called by generated code to determine if a byte array is a valid
+   * UTF-8 encoded string such that the original bytes can be converted to
+   * a String object and then back to a byte array round tripping the bytes
+   * without loss.
+   * <p>
+   * This is inspired by UTF_8.java in sun.nio.cs.
+   *
+   * @param byteString the string to check
+   * @return whether the byte array is round trippable
+   */
+  public static boolean isValidUtf8(ByteString byteString) {
+    int index = 0;
+    int size = byteString.size();
+    // To avoid the masking, we could change this to use bytes;
+    // Then X > 0xC2 gets turned into X < -0xC2; X < 0x80
+    // gets turned into X >= 0, etc.
+
+    while (index < size) {
+      int byte1 = byteString.byteAt(index++) & 0xFF;
+      if (byte1 < 0x80) {
+        // fast loop for single bytes
+        continue;
+
+        // we know from this point on that we have 2-4 byte forms
+      } else if (byte1 < 0xC2 || byte1 > 0xF4) {
+        // catch illegal first bytes: < C2 or > F4
+        return false;
+      }
+      if (index >= size) {
+        // fail if we run out of bytes
+        return false;
+      }
+      int byte2 = byteString.byteAt(index++) & 0xFF;
+      if (byte2 < 0x80 || byte2 > 0xBF) {
+        // general trail-byte test
+        return false;
+      }
+      if (byte1 <= 0xDF) {
+        // two-byte form; general trail-byte test is sufficient
+        continue;
+      }
+
+      // we know from this point on that we have 3 or 4 byte forms
+      if (index >= size) {
+        // fail if we run out of bytes
+        return false;
+      }
+      int byte3 = byteString.byteAt(index++) & 0xFF;
+      if (byte3 < 0x80 || byte3 > 0xBF) {
+        // general trail-byte test
+        return false;
+      }
+      if (byte1 <= 0xEF) {
+        // three-byte form. Vastly more frequent than four-byte forms
+        // The following has an extra test, but not worth restructuring
+        if (byte1 == 0xE0 && byte2 < 0xA0 ||
+            byte1 == 0xED && byte2 > 0x9F) {
+          // check special cases of byte2
+          return false;
+        }
+
+      } else {
+        // four-byte form
+
+        if (index >= size) {
+          // fail if we run out of bytes
+          return false;
+        }
+        int byte4 = byteString.byteAt(index++) & 0xFF;
+        if (byte4 < 0x80 || byte4 > 0xBF) {
+          // general trail-byte test
+          return false;
+        }
+        // The following has an extra test, but not worth restructuring
+        if (byte1 == 0xF0 && byte2 < 0x90 ||
+            byte1 == 0xF4 && byte2 > 0x8F) {
+          // check special cases of byte2
+          return false;
+        }
+      }
+    }
+    return true;
+  }
+
+  /**
    * Interface for an enum value or value descriptor, to be used in FieldSet.
    * The lite library stores enum values directly in FieldSets but the full
    * library stores EnumValueDescriptors in order to better support reflection.
diff --git a/java/src/main/java/com/google/protobuf/LazyStringArrayList.java b/java/src/main/java/com/google/protobuf/LazyStringArrayList.java
new file mode 100644
index 0000000..1683a64
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/LazyStringArrayList.java
@@ -0,0 +1,155 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import java.util.List;
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.RandomAccess;
+import java.util.Collection;
+
+/**
+ * An implementation of {@link LazyStringList} that wraps an ArrayList. Each
+ * element is either a ByteString or a String. It caches the last one requested
+ * which is most likely the one needed next. This minimizes memory usage while
+ * satisfying the most common use cases.
+ * <p>
+ * <strong>Note that this implementation is not synchronized.</strong>
+ * If multiple threads access an <tt>ArrayList</tt> instance concurrently,
+ * and at least one of the threads modifies the list structurally, it
+ * <i>must</i> be synchronized externally.  (A structural modification is
+ * any operation that adds or deletes one or more elements, or explicitly
+ * resizes the backing array; merely setting the value of an element is not
+ * a structural modification.)  This is typically accomplished by
+ * synchronizing on some object that naturally encapsulates the list.
+ * <p>
+ * If the implementation is accessed via concurrent reads, this is thread safe.
+ * Conversions are done in a thread safe manner. It's possible that the
+ * conversion may happen more than once if two threads attempt to access the
+ * same element and the modifications were not visible to each other, but this
+ * will not result in any corruption of the list or change in behavior other
+ * than performance.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class LazyStringArrayList extends AbstractList<String>
+    implements LazyStringList, RandomAccess {
+
+  public final static LazyStringList EMPTY = new UnmodifiableLazyStringList(
+      new LazyStringArrayList());
+
+  private final List<Object> list;
+
+  public LazyStringArrayList() {
+    list = new ArrayList<Object>();
+  }
+
+  public LazyStringArrayList(List<String> from) {
+    list = new ArrayList<Object>(from);
+  }
+
+  @Override
+  public String get(int index) {
+    Object o = list.get(index);
+    if (o instanceof String) {
+      return (String) o;
+    } else {
+      ByteString bs = (ByteString) o;
+      String s = bs.toStringUtf8();
+      if (Internal.isValidUtf8(bs)) {
+        list.set(index, s);
+      }
+      return s;
+    }
+  }
+
+  @Override
+  public int size() {
+    return list.size();
+  }
+
+  @Override
+  public String set(int index, String s) {
+    Object o = list.set(index, s);
+    return asString(o);
+  }
+
+  @Override
+  public void add(int index, String element) {
+    list.add(index, element);
+    modCount++;
+  }
+
+  @Override
+  public boolean addAll(int index, Collection<? extends String> c) {
+    boolean ret = list.addAll(index, c);
+    modCount++;
+    return ret;
+  }
+
+  @Override
+  public String remove(int index) {
+    Object o = list.remove(index);
+    modCount++;
+    return asString(o);
+  }
+
+  public void clear() {
+    list.clear();
+    modCount++;
+  }
+
+  // @Override
+  public void add(ByteString element) {
+    list.add(element);
+    modCount++;
+  }
+
+  // @Override
+  public ByteString getByteString(int index) {
+    Object o = list.get(index);
+    if (o instanceof String) {
+      ByteString b = ByteString.copyFromUtf8((String) o);
+      list.set(index, b);
+      return b;
+    } else {
+      return (ByteString) o;
+    }
+  }
+
+  private String asString(Object o) {
+    if (o instanceof String) {
+      return (String) o;
+    } else {
+      return ((ByteString) o).toStringUtf8();
+    }
+  }
+}
diff --git a/java/src/main/java/com/google/protobuf/LazyStringList.java b/java/src/main/java/com/google/protobuf/LazyStringList.java
new file mode 100644
index 0000000..97139ca
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/LazyStringList.java
@@ -0,0 +1,72 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import java.util.List;
+
+/**
+ * An interface extending List&lt;String&gt; that also provides access to the
+ * items of the list as UTF8-encoded ByteString objects. This is used by the
+ * protocol buffer implementation to support lazily converting bytes parsed
+ * over the wire to String objects until needed and also increases the
+ * efficiency of serialization if the String was never requested as the
+ * ByteString is already cached.
+ * <p>
+ * This only adds additional methods that are required for the use in the
+ * protocol buffer code in order to be able successfuly round trip byte arrays
+ * through parsing and serialization without conversion to strings. It's not
+ * attempting to support the functionality of say List&ltByteString&gt, hence
+ * why only these two very specific methods are added.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public interface LazyStringList extends List<String> {
+
+  /**
+   * Returns the element at the specified position in this list as a ByteString.
+   *
+   * @param index index of the element to return
+   * @return the element at the specified position in this list
+   * @throws IndexOutOfBoundsException if the index is out of range
+   *         (<tt>index &lt; 0 || index &gt;= size()</tt>)
+   */
+  ByteString getByteString(int index);
+
+  /**
+   * Appends the specified element to the end of this list (optional
+   * operation).
+   *
+   * @param element element to be appended to this list
+   * @throws UnsupportedOperationException if the <tt>add</tt> operation
+   *         is not supported by this list
+   */
+  void add(ByteString element);
+}
diff --git a/java/src/main/java/com/google/protobuf/Message.java b/java/src/main/java/com/google/protobuf/Message.java
index 8c29e21..67c4148 100644
--- a/java/src/main/java/com/google/protobuf/Message.java
+++ b/java/src/main/java/com/google/protobuf/Message.java
@@ -48,69 +48,7 @@
  *
  * @author kenton@google.com Kenton Varda
  */
-public interface Message extends MessageLite {
-  /**
-   * Get the message's type's descriptor.  This differs from the
-   * {@code getDescriptor()} method of generated message classes in that
-   * this method is an abstract method of the {@code Message} interface
-   * whereas {@code getDescriptor()} is a static method of a specific class.
-   * They return the same thing.
-   */
-  Descriptors.Descriptor getDescriptorForType();
-
-  // (From MessageLite, re-declared here only for return type covariance.)
-  Message getDefaultInstanceForType();
-
-  /**
-   * Returns a collection of all the fields in this message which are set
-   * and their corresponding values.  A singular ("required" or "optional")
-   * field is set iff hasField() returns true for that field.  A "repeated"
-   * field is set iff getRepeatedFieldSize() is greater than zero.  The
-   * values are exactly what would be returned by calling
-   * {@link #getField(Descriptors.FieldDescriptor)} for each field.  The map
-   * is guaranteed to be a sorted map, so iterating over it will return fields
-   * in order by field number.
-   */
-  Map<Descriptors.FieldDescriptor, Object> getAllFields();
-
-  /**
-   * Returns true if the given field is set.  This is exactly equivalent to
-   * calling the generated "has" accessor method corresponding to the field.
-   * @throws IllegalArgumentException The field is a repeated field, or
-   *           {@code field.getContainingType() != getDescriptorForType()}.
-   */
-  boolean hasField(Descriptors.FieldDescriptor field);
-
-  /**
-   * Obtains the value of the given field, or the default value if it is
-   * not set.  For primitive fields, the boxed primitive value is returned.
-   * For enum fields, the EnumValueDescriptor for the value is returend. For
-   * embedded message fields, the sub-message is returned.  For repeated
-   * fields, a java.util.List is returned.
-   */
-  Object getField(Descriptors.FieldDescriptor field);
-
-  /**
-   * Gets the number of elements of a repeated field.  This is exactly
-   * equivalent to calling the generated "Count" accessor method corresponding
-   * to the field.
-   * @throws IllegalArgumentException The field is not a repeated field, or
-   *           {@code field.getContainingType() != getDescriptorForType()}.
-   */
-  int getRepeatedFieldCount(Descriptors.FieldDescriptor field);
-
-  /**
-   * Gets an element of a repeated field.  For primitive fields, the boxed
-   * primitive value is returned.  For enum fields, the EnumValueDescriptor
-   * for the value is returend. For embedded message fields, the sub-message
-   * is returned.
-   * @throws IllegalArgumentException The field is not a repeated field, or
-   *           {@code field.getContainingType() != getDescriptorForType()}.
-   */
-  Object getRepeatedField(Descriptors.FieldDescriptor field, int index);
-
-  /** Get the {@link UnknownFieldSet} for this message. */
-  UnknownFieldSet getUnknownFields();
+public interface Message extends MessageLite, MessageOrBuilder {
 
   // -----------------------------------------------------------------
   // Comparison and hashing
@@ -119,7 +57,8 @@
    * Compares the specified object with this message for equality.  Returns
    * <tt>true</tt> if the given object is a message of the same type (as
    * defined by {@code getDescriptorForType()}) and has identical values for
-   * all of its fields.
+   * all of its fields.  Subclasses must implement this; inheriting
+   * {@code Object.equals()} is incorrect.
    *
    * @param other object to be compared for equality with this message
    * @return <tt>true</tt> if the specified object is equal to this message
@@ -129,8 +68,9 @@
 
   /**
    * Returns the hash code value for this message.  The hash code of a message
-   * is defined to be <tt>getDescriptor().hashCode() ^ map.hashCode()</tt>,
-   * where <tt>map</tt> is a map of field numbers to field values.
+   * should mix the message's type (object identity of the decsriptor) with its
+   * contents (known and unknown field values).  Subclasses must implement this;
+   * inheriting {@code Object.hashCode()} is incorrect.
    *
    * @return the hash code value for this message
    * @see Map#hashCode()
@@ -158,7 +98,7 @@
   /**
    * Abstract interface implemented by Protocol Message builders.
    */
-  interface Builder extends MessageLite.Builder {
+  interface Builder extends MessageLite.Builder, MessageOrBuilder {
     // (From MessageLite.Builder, re-declared here only for return type
     // covariance.)
     Builder clear();
@@ -197,17 +137,6 @@
      */
     Descriptors.Descriptor getDescriptorForType();
 
-    // (From MessageLite.Builder, re-declared here only for return type
-    // covariance.)
-    Message getDefaultInstanceForType();
-
-    /**
-     * Like {@link Message#getAllFields()}.  The returned map may or may not
-     * reflect future changes to the builder.  Either way, the returned map is
-     * itself unmodifiable.
-     */
-    Map<Descriptors.FieldDescriptor, Object> getAllFields();
-
     /**
      * Create a Builder for messages of the appropriate type for the given
      * field.  Messages built with this can then be passed to setField(),
@@ -215,12 +144,6 @@
      */
     Builder newBuilderForField(Descriptors.FieldDescriptor field);
 
-    /** Like {@link Message#hasField(Descriptors.FieldDescriptor)} */
-    boolean hasField(Descriptors.FieldDescriptor field);
-
-    /** Like {@link Message#getField(Descriptors.FieldDescriptor)} */
-    Object getField(Descriptors.FieldDescriptor field);
-
     /**
      * Sets a field to the given value.  The value must be of the correct type
      * for this field, i.e. the same type that
@@ -235,16 +158,6 @@
     Builder clearField(Descriptors.FieldDescriptor field);
 
     /**
-     * Like {@link Message#getRepeatedFieldCount(Descriptors.FieldDescriptor)}
-     */
-    int getRepeatedFieldCount(Descriptors.FieldDescriptor field);
-
-    /**
-     * Like {@link Message#getRepeatedField(Descriptors.FieldDescriptor,int)}
-     */
-    Object getRepeatedField(Descriptors.FieldDescriptor field, int index);
-
-    /**
      * Sets an element of a repeated field to the given value.  The value must
      * be of the correct type for this field, i.e. the same type that
      * {@link Message#getRepeatedField(Descriptors.FieldDescriptor,int)} would
@@ -262,9 +175,6 @@
      */
     Builder addRepeatedField(Descriptors.FieldDescriptor field, Object value);
 
-    /** Get the {@link UnknownFieldSet} for this message. */
-    UnknownFieldSet getUnknownFields();
-
     /** Set the {@link UnknownFieldSet} for this message. */
     Builder setUnknownFields(UnknownFieldSet unknownFields);
 
diff --git a/java/src/main/java/com/google/protobuf/MessageLite.java b/java/src/main/java/com/google/protobuf/MessageLite.java
index cf7f39e..31b8256 100644
--- a/java/src/main/java/com/google/protobuf/MessageLite.java
+++ b/java/src/main/java/com/google/protobuf/MessageLite.java
@@ -64,22 +64,8 @@
  *
  * @author kenton@google.com Kenton Varda
  */
-public interface MessageLite {
-  /**
-   * Get an instance of the type with all fields set to their default values.
-   * This may or may not be a singleton.  This differs from the
-   * {@code getDefaultInstance()} method of generated message classes in that
-   * this method is an abstract method of the {@code MessageLite} interface
-   * whereas {@code getDefaultInstance()} is a static method of a specific
-   * class.  They return the same thing.
-   */
-  MessageLite getDefaultInstanceForType();
+public interface MessageLite extends MessageLiteOrBuilder {
 
-  /**
-   * Returns true if all required fields in the message and all embedded
-   * messages are set, false otherwise.
-   */
-  boolean isInitialized();
 
   /**
    * Serializes the message and writes it to {@code output}.  This does not
@@ -153,7 +139,7 @@
   /**
    * Abstract interface implemented by Protocol Message builders.
    */
-  interface Builder extends Cloneable {
+  interface Builder extends MessageLiteOrBuilder, Cloneable {
     /** Resets all fields to their default values. */
     Builder clear();
 
@@ -187,12 +173,6 @@
     Builder clone();
 
     /**
-     * Returns true if all required fields in the message and all embedded
-     * messages are set, false otherwise.
-     */
-    boolean isInitialized();
-
-    /**
      * Parses a message of this type from the input and merges it with this
      * message, as if using {@link Builder#mergeFrom(MessageLite)}.
      *
@@ -230,12 +210,6 @@
                       ExtensionRegistryLite extensionRegistry)
                       throws IOException;
 
-    /**
-     * Get the message's type's default instance.
-     * See {@link MessageLite#getDefaultInstanceForType()}.
-     */
-    MessageLite getDefaultInstanceForType();
-
     // ---------------------------------------------------------------
     // Convenience methods.
 
@@ -243,6 +217,8 @@
      * Parse {@code data} as a message of this type and merge it with the
      * message being built.  This is just a small wrapper around
      * {@link #mergeFrom(CodedInputStream)}.
+     *
+     * @return this
      */
     Builder mergeFrom(ByteString data) throws InvalidProtocolBufferException;
 
@@ -250,6 +226,8 @@
      * Parse {@code data} as a message of this type and merge it with the
      * message being built.  This is just a small wrapper around
      * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
+     *
+     * @return this
      */
     Builder mergeFrom(ByteString data,
                       ExtensionRegistryLite extensionRegistry)
@@ -259,6 +237,8 @@
      * Parse {@code data} as a message of this type and merge it with the
      * message being built.  This is just a small wrapper around
      * {@link #mergeFrom(CodedInputStream)}.
+     *
+     * @return this
      */
     Builder mergeFrom(byte[] data) throws InvalidProtocolBufferException;
 
@@ -266,6 +246,8 @@
      * Parse {@code data} as a message of this type and merge it with the
      * message being built.  This is just a small wrapper around
      * {@link #mergeFrom(CodedInputStream)}.
+     *
+     * @return this
      */
     Builder mergeFrom(byte[] data, int off, int len)
                       throws InvalidProtocolBufferException;
@@ -274,6 +256,8 @@
      * Parse {@code data} as a message of this type and merge it with the
      * message being built.  This is just a small wrapper around
      * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
+     *
+     * @return this
      */
     Builder mergeFrom(byte[] data,
                       ExtensionRegistryLite extensionRegistry)
@@ -283,6 +267,8 @@
      * Parse {@code data} as a message of this type and merge it with the
      * message being built.  This is just a small wrapper around
      * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
+     *
+     * @return this
      */
     Builder mergeFrom(byte[] data, int off, int len,
                       ExtensionRegistryLite extensionRegistry)
@@ -299,6 +285,8 @@
      * and {@link #mergeDelimitedFrom(InputStream)} to read it.
      * <p>
      * Despite usually reading the entire input, this does not close the stream.
+     *
+     * @return this
      */
     Builder mergeFrom(InputStream input) throws IOException;
 
@@ -306,6 +294,8 @@
      * Parse a message of this type from {@code input} and merge it with the
      * message being built.  This is just a small wrapper around
      * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
+     *
+     * @return this
      */
     Builder mergeFrom(InputStream input,
                       ExtensionRegistryLite extensionRegistry)
diff --git a/java/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java b/java/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java
new file mode 100644
index 0000000..a2a7448
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java
@@ -0,0 +1,56 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+/**
+ * Base interface for methods common to {@link MessageLite}
+ * and {@link MessageLite.Builder} to provide type equivalency.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public interface MessageLiteOrBuilder {
+  /**
+   * Get an instance of the type with all fields set to their default values.
+   * This may or may not be a singleton.  This differs from the
+   * {@code getDefaultInstance()} method of generated message classes in that
+   * this method is an abstract method of the {@code MessageLite} interface
+   * whereas {@code getDefaultInstance()} is a static method of a specific
+   * class.  They return the same thing.
+   */
+  MessageLite getDefaultInstanceForType();
+
+  /**
+   * Returns true if all required fields in the message and all embedded
+   * messages are set, false otherwise.
+   */
+  boolean isInitialized();
+
+}
diff --git a/java/src/main/java/com/google/protobuf/MessageOrBuilder.java b/java/src/main/java/com/google/protobuf/MessageOrBuilder.java
new file mode 100644
index 0000000..0132e7c
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/MessageOrBuilder.java
@@ -0,0 +1,110 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import java.util.Map;
+
+/**
+ * Base interface for methods common to {@link Message} and
+ * {@link Message.Builder} to provide type equivalency.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public interface MessageOrBuilder extends MessageLiteOrBuilder {
+
+  // (From MessageLite, re-declared here only for return type covariance.)
+  //@Override (Java 1.6 override semantics, but we must support 1.5)
+  Message getDefaultInstanceForType();
+
+  /**
+   * Get the message's type's descriptor.  This differs from the
+   * {@code getDescriptor()} method of generated message classes in that
+   * this method is an abstract method of the {@code Message} interface
+   * whereas {@code getDescriptor()} is a static method of a specific class.
+   * They return the same thing.
+   */
+  Descriptors.Descriptor getDescriptorForType();
+
+  /**
+   * Returns a collection of all the fields in this message which are set
+   * and their corresponding values.  A singular ("required" or "optional")
+   * field is set iff hasField() returns true for that field.  A "repeated"
+   * field is set iff getRepeatedFieldSize() is greater than zero.  The
+   * values are exactly what would be returned by calling
+   * {@link #getField(Descriptors.FieldDescriptor)} for each field.  The map
+   * is guaranteed to be a sorted map, so iterating over it will return fields
+   * in order by field number.
+   * <br>
+   * If this is for a builder, the returned map may or may not reflect future
+   * changes to the builder.  Either way, the returned map is itself
+   * unmodifiable.
+   */
+  Map<Descriptors.FieldDescriptor, Object> getAllFields();
+
+  /**
+   * Returns true if the given field is set.  This is exactly equivalent to
+   * calling the generated "has" accessor method corresponding to the field.
+   * @throws IllegalArgumentException The field is a repeated field, or
+   *           {@code field.getContainingType() != getDescriptorForType()}.
+   */
+  boolean hasField(Descriptors.FieldDescriptor field);
+
+  /**
+   * Obtains the value of the given field, or the default value if it is
+   * not set.  For primitive fields, the boxed primitive value is returned.
+   * For enum fields, the EnumValueDescriptor for the value is returend. For
+   * embedded message fields, the sub-message is returned.  For repeated
+   * fields, a java.util.List is returned.
+   */
+  Object getField(Descriptors.FieldDescriptor field);
+
+  /**
+   * Gets the number of elements of a repeated field.  This is exactly
+   * equivalent to calling the generated "Count" accessor method corresponding
+   * to the field.
+   * @throws IllegalArgumentException The field is not a repeated field, or
+   *           {@code field.getContainingType() != getDescriptorForType()}.
+   */
+  int getRepeatedFieldCount(Descriptors.FieldDescriptor field);
+
+  /**
+   * Gets an element of a repeated field.  For primitive fields, the boxed
+   * primitive value is returned.  For enum fields, the EnumValueDescriptor
+   * for the value is returend. For embedded message fields, the sub-message
+   * is returned.
+   * @throws IllegalArgumentException The field is not a repeated field, or
+   *           {@code field.getContainingType() != getDescriptorForType()}.
+   */
+  Object getRepeatedField(Descriptors.FieldDescriptor field, int index);
+
+  /** Get the {@link UnknownFieldSet} for this message. */
+  UnknownFieldSet getUnknownFields();
+}
diff --git a/java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java b/java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java
new file mode 100644
index 0000000..0772eac
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java
@@ -0,0 +1,696 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * <code>RepeatedFieldBuilder</code> implements a structure that a protocol
+ * message uses to hold a repeated field of other protocol messages. It supports
+ * the classical use case of adding immutable {@link Message}'s to the
+ * repeated field and is highly optimized around this (no extra memory
+ * allocations and sharing of immutable arrays).
+ * <br>
+ * It also supports the additional use case of adding a {@link Message.Builder}
+ * to the repeated field and deferring conversion of that <code>Builder</code>
+ * to an immutable <code>Message</code>. In this way, it's possible to maintain
+ * a tree of <code>Builder</code>'s that acts as a fully read/write data
+ * structure.
+ * <br>
+ * Logically, one can think of a tree of builders as converting the entire tree
+ * to messages when build is called on the root or when any method is called
+ * that desires a Message instead of a Builder. In terms of the implementation,
+ * the <code>SingleFieldBuilder</code> and <code>RepeatedFieldBuilder</code>
+ * classes cache messages that were created so that messages only need to be
+ * created when some change occured in its builder or a builder for one of its
+ * descendants.
+ *
+ * @param <MType> the type of message for the field
+ * @param <BType> the type of builder for the field
+ * @param <IType> the common interface for the message and the builder
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class RepeatedFieldBuilder
+    <MType extends GeneratedMessage,
+     BType extends GeneratedMessage.Builder,
+     IType extends MessageOrBuilder>
+    implements GeneratedMessage.BuilderParent {
+
+  // Parent to send changes to.
+  private GeneratedMessage.BuilderParent parent;
+
+  // List of messages. Never null. It may be immutable, in which case
+  // isMessagesListImmutable will be true. See note below.
+  private List<MType> messages;
+
+  // Whether messages is an mutable array that can be modified.
+  private boolean isMessagesListMutable;
+
+  // List of builders. May be null, in which case, no nested builders were
+  // created. If not null, entries represent the builder for that index.
+  private List<SingleFieldBuilder<MType, BType, IType>> builders;
+
+  // Here are the invariants for messages and builders:
+  // 1. messages is never null and its count corresponds to the number of items
+  //    in the repeated field.
+  // 2. If builders is non-null, messages and builders MUST always
+  //    contain the same number of items.
+  // 3. Entries in either array can be null, but for any index, there MUST be
+  //    either a Message in messages or a builder in builders.
+  // 4. If the builder at an index is non-null, the builder is
+  //    authoritative. This is the case where a Builder was set on the index.
+  //    Any message in the messages array MUST be ignored.
+  // t. If the builder at an index is null, the message in the messages
+  //    list is authoritative. This is the case where a Message (not a Builder)
+  //    was set directly for an index.
+
+  // Indicates that we've built a message and so we are now obligated
+  // to dispatch dirty invalidations. See GeneratedMessage.BuilderListener.
+  private boolean isClean;
+
+  // A view of this builder that exposes a List interface of messages. This is
+  // initialized on demand. This is fully backed by this object and all changes
+  // are reflected in it. Access to any item converts it to a message if it
+  // was a builder.
+  private MessageExternalList<MType, BType, IType> externalMessageList;
+
+  // A view of this builder that exposes a List interface of builders. This is
+  // initialized on demand. This is fully backed by this object and all changes
+  // are reflected in it. Access to any item converts it to a builder if it
+  // was a message.
+  private BuilderExternalList<MType, BType, IType> externalBuilderList;
+
+  // A view of this builder that exposes a List interface of the interface
+  // implemented by messages and builders. This is initialized on demand. This
+  // is fully backed by this object and all changes are reflected in it.
+  // Access to any item returns either a builder or message depending on
+  // what is most efficient.
+  private MessageOrBuilderExternalList<MType, BType, IType>
+      externalMessageOrBuilderList;
+
+  /**
+   * Constructs a new builder with an empty list of messages.
+   *
+   * @param messages the current list of messages
+   * @param isMessagesListMutable Whether the messages list is mutable
+   * @param parent a listener to notify of changes
+   * @param isClean whether the builder is initially marked clean
+   */
+  public RepeatedFieldBuilder(
+      List<MType> messages,
+      boolean isMessagesListMutable,
+      GeneratedMessage.BuilderParent parent,
+      boolean isClean) {
+    this.messages = messages;
+    this.isMessagesListMutable = isMessagesListMutable;
+    this.parent = parent;
+    this.isClean = isClean;
+  }
+
+  public void dispose() {
+    // Null out parent so we stop sending it invalidations.
+    parent = null;
+  }
+
+  /**
+   * Ensures that the list of messages is mutable so it can be updated. If it's
+   * immutable, a copy is made.
+   */
+  private void ensureMutableMessageList() {
+    if (!isMessagesListMutable) {
+      messages = new ArrayList<MType>(messages);
+      isMessagesListMutable = true;
+    }
+  }
+
+  /**
+   * Ensures that the list of builders is not null. If it's null, the list is
+   * created and initialized to be the same size as the messages list with
+   * null entries.
+   */
+  private void ensureBuilders() {
+    if (this.builders == null) {
+      this.builders =
+          new ArrayList<SingleFieldBuilder<MType, BType, IType>>(
+              messages.size());
+      for (int i = 0; i < messages.size(); i++) {
+        builders.add(null);
+      }
+    }
+  }
+
+  /**
+   * Gets the count of items in the list.
+   *
+   * @return the count of items in the list.
+   */
+  public int getCount() {
+    return messages.size();
+  }
+
+  /**
+   * Gets whether the list is empty.
+   *
+   * @return whether the list is empty
+   */
+  public boolean isEmpty() {
+    return messages.isEmpty();
+  }
+
+  /**
+   * Get the message at the specified index. If the message is currently stored
+   * as a <code>Builder</code>, it is converted to a <code>Message</code> by
+   * calling {@link Message.Builder#buildPartial} on it.
+   *
+   * @param index the index of the message to get
+   * @return the message for the specified index
+   */
+  public MType getMessage(int index) {
+    return getMessage(index, false);
+  }
+
+  /**
+   * Get the message at the specified index. If the message is currently stored
+   * as a <code>Builder</code>, it is converted to a <code>Message</code> by
+   * calling {@link Message.Builder#buildPartial} on it.
+   *
+   * @param index the index of the message to get
+   * @param forBuild this is being called for build so we want to make sure
+   *     we SingleFieldBuilder.build to send dirty invalidations
+   * @return the message for the specified index
+   */
+  private MType getMessage(int index, boolean forBuild) {
+    if (this.builders == null) {
+      // We don't have any builders -- return the current Message.
+      // This is the case where no builder was created, so we MUST have a
+      // Message.
+      return messages.get(index);
+    }
+
+    SingleFieldBuilder<MType, BType, IType> builder = builders.get(index);
+    if (builder == null) {
+      // We don't have a builder -- return the current message.
+      // This is the case where no builder was created for the entry at index,
+      // so we MUST have a message.
+      return messages.get(index);
+
+    } else {
+      return forBuild ? builder.build() : builder.getMessage();
+    }
+  }
+
+  /**
+   * Gets a builder for the specified index. If no builder has been created for
+   * that index, a builder is created on demand by calling
+   * {@link Message#toBuilder}.
+   *
+   * @param index the index of the message to get
+   * @return The builder for that index
+   */
+  public BType getBuilder(int index) {
+    ensureBuilders();
+    SingleFieldBuilder<MType, BType, IType> builder = builders.get(index);
+    if (builder == null) {
+      MType message = messages.get(index);
+      builder = new SingleFieldBuilder<MType, BType, IType>(
+          message, this, isClean);
+      builders.set(index, builder);
+    }
+    return builder.getBuilder();
+  }
+
+  /**
+   * Gets the base class interface for the specified index. This may either be
+   * a builder or a message. It will return whatever is more efficient.
+   *
+   * @param index the index of the message to get
+   * @return the message or builder for the index as the base class interface
+   */
+  @SuppressWarnings("unchecked")
+  public IType getMessageOrBuilder(int index) {
+    if (this.builders == null) {
+      // We don't have any builders -- return the current Message.
+      // This is the case where no builder was created, so we MUST have a
+      // Message.
+      return (IType) messages.get(index);
+    }
+
+    SingleFieldBuilder<MType, BType, IType> builder = builders.get(index);
+    if (builder == null) {
+      // We don't have a builder -- return the current message.
+      // This is the case where no builder was created for the entry at index,
+      // so we MUST have a message.
+      return (IType) messages.get(index);
+
+    } else {
+      return builder.getMessageOrBuilder();
+    }
+  }
+
+  /**
+   * Sets a  message at the specified index replacing the existing item at
+   * that index.
+   *
+   * @param index the index to set.
+   * @param message the message to set
+   * @return the builder
+   */
+  public RepeatedFieldBuilder<MType, BType, IType> setMessage(
+      int index, MType message) {
+    if (message == null) {
+      throw new NullPointerException();
+    }
+    ensureMutableMessageList();
+    messages.set(index, message);
+    if (builders != null) {
+      SingleFieldBuilder<MType, BType, IType> entry =
+          builders.set(index, null);
+      if (entry != null) {
+        entry.dispose();
+      }
+    }
+    onChanged();
+    incrementModCounts();
+    return this;
+  }
+
+  /**
+   * Appends the specified element to the end of this list.
+   *
+   * @param message the message to add
+   * @return the builder
+   */
+  public RepeatedFieldBuilder<MType, BType, IType> addMessage(
+      MType message) {
+    if (message == null) {
+      throw new NullPointerException();
+    }
+    ensureMutableMessageList();
+    messages.add(message);
+    if (builders != null) {
+      builders.add(null);
+    }
+    onChanged();
+    incrementModCounts();
+    return this;
+  }
+
+  /**
+   * Inserts the specified message at the specified position in this list.
+   * Shifts the element currently at that position (if any) and any subsequent
+   * elements to the right (adds one to their indices).
+   *
+   * @param index the index at which to insert the message
+   * @param message the message to add
+   * @return the builder
+   */
+  public RepeatedFieldBuilder<MType, BType, IType> addMessage(
+      int index, MType message) {
+    if (message == null) {
+      throw new NullPointerException();
+    }
+    ensureMutableMessageList();
+    messages.add(index, message);
+    if (builders != null) {
+      builders.add(index, null);
+    }
+    onChanged();
+    incrementModCounts();
+    return this;
+  }
+
+  /**
+   * Appends all of the messages in the specified collection to the end of
+   * this list, in the order that they are returned by the specified
+   * collection's iterator.
+   *
+   * @param values the messages to add
+   * @return the builder
+   */
+  public RepeatedFieldBuilder<MType, BType, IType> addAllMessages(
+      Iterable<? extends MType> values) {
+    for (final MType value : values) {
+      if (value == null) {
+        throw new NullPointerException();
+      }
+    }
+    if (values instanceof Collection) {
+      @SuppressWarnings("unchecked") final
+      Collection<MType> collection = (Collection<MType>) values;
+      if (collection.size() == 0) {
+        return this;
+      }
+      ensureMutableMessageList();
+      for (MType value : values) {
+        addMessage(value);
+      }
+    } else {
+      ensureMutableMessageList();
+      for (MType value : values) {
+        addMessage(value);
+      }
+    }
+    onChanged();
+    incrementModCounts();
+    return this;
+  }
+
+  /**
+   * Appends a new builder to the end of this list and returns the builder.
+   *
+   * @param message the message to add which is the basis of the builder
+   * @return the new builder
+   */
+  public BType addBuilder(MType message) {
+    ensureMutableMessageList();
+    ensureBuilders();
+    SingleFieldBuilder<MType, BType, IType> builder =
+        new SingleFieldBuilder<MType, BType, IType>(
+            message, this, isClean);
+    messages.add(null);
+    builders.add(builder);
+    onChanged();
+    incrementModCounts();
+    return builder.getBuilder();
+  }
+
+  /**
+   * Inserts a new builder at the specified position in this list.
+   * Shifts the element currently at that position (if any) and any subsequent
+   * elements to the right (adds one to their indices).
+   *
+   * @param index the index at which to insert the builder
+   * @param message the message to add which is the basis of the builder
+   * @return the builder
+   */
+  public BType addBuilder(int index, MType message) {
+    ensureMutableMessageList();
+    ensureBuilders();
+    SingleFieldBuilder<MType, BType, IType> builder =
+        new SingleFieldBuilder<MType, BType, IType>(
+            message, this, isClean);
+    messages.add(index, null);
+    builders.add(index, builder);
+    onChanged();
+    incrementModCounts();
+    return builder.getBuilder();
+  }
+
+  /**
+   * Removes the element at the specified position in this list. Shifts any
+   * subsequent elements to the left (subtracts one from their indices).
+   * Returns the element that was removed from the list.
+   *
+   * @param index the index at which to remove the message
+   */
+  public void remove(int index) {
+    ensureMutableMessageList();
+    messages.remove(index);
+    if (builders != null) {
+      SingleFieldBuilder<MType, BType, IType> entry =
+          builders.remove(index);
+      if (entry != null) {
+        entry.dispose();
+      }
+    }
+    onChanged();
+    incrementModCounts();
+  }
+
+  /**
+   * Removes all of the elements from this list.
+   * The list will be empty after this call returns.
+   */
+  public void clear() {
+    messages = Collections.emptyList();
+    isMessagesListMutable = false;
+    if (builders != null) {
+      for (SingleFieldBuilder<MType, BType, IType> entry :
+          builders) {
+        if (entry != null) {
+          entry.dispose();
+        }
+      }
+      builders = null;
+    }
+    onChanged();
+    incrementModCounts();
+  }
+
+  /**
+   * Builds the list of messages from the builder and returns them.
+   *
+   * @return an immutable list of messages
+   */
+  public List<MType> build() {
+    // Now that build has been called, we are required to dispatch
+    // invalidations.
+    isClean = true;
+
+    if (!isMessagesListMutable && builders == null) {
+      // We still have an immutable list and we never created a builder.
+      return messages;
+    }
+
+    boolean allMessagesInSync = true;
+    if (!isMessagesListMutable) {
+      // We still have an immutable list. Let's see if any of them are out
+      // of sync with their builders.
+      for (int i = 0; i < messages.size(); i++) {
+        Message message = messages.get(i);
+        SingleFieldBuilder<MType, BType, IType> builder = builders.get(i);
+        if (builder != null) {
+          if (builder.build() != message) {
+            allMessagesInSync = false;
+            break;
+          }
+        }
+      }
+      if (allMessagesInSync) {
+        // Immutable list is still in sync.
+        return messages;
+      }
+    }
+
+    // Need to make sure messages is up to date
+    ensureMutableMessageList();
+    for (int i = 0; i < messages.size(); i++) {
+      messages.set(i, getMessage(i, true));
+    }
+
+    // We're going to return our list as immutable so we mark that we can
+    // no longer update it.
+    messages = Collections.unmodifiableList(messages);
+    isMessagesListMutable = false;
+    return messages;
+  }
+
+  /**
+   * Gets a view of the builder as a list of messages. The returned list is live
+   * and will reflect any changes to the underlying builder.
+   *
+   * @return the messages in the list
+   */
+  public List<MType> getMessageList() {
+    if (externalMessageList == null) {
+      externalMessageList =
+          new MessageExternalList<MType, BType, IType>(this);
+    }
+    return externalMessageList;
+  }
+
+  /**
+   * Gets a view of the builder as a list of builders. This returned list is
+   * live and will reflect any changes to the underlying builder.
+   *
+   * @return the builders in the list
+   */
+  public List<BType> getBuilderList() {
+    if (externalBuilderList == null) {
+      externalBuilderList =
+          new BuilderExternalList<MType, BType, IType>(this);
+    }
+    return externalBuilderList;
+  }
+
+  /**
+   * Gets a view of the builder as a list of MessageOrBuilders. This returned
+   * list is live and will reflect any changes to the underlying builder.
+   *
+   * @return the builders in the list
+   */
+  public List<IType> getMessageOrBuilderList() {
+    if (externalMessageOrBuilderList == null) {
+      externalMessageOrBuilderList =
+          new MessageOrBuilderExternalList<MType, BType, IType>(this);
+    }
+    return externalMessageOrBuilderList;
+  }
+
+  /**
+   * Called when a the builder or one of its nested children has changed
+   * and any parent should be notified of its invalidation.
+   */
+  private void onChanged() {
+    if (isClean && parent != null) {
+      parent.markDirty();
+
+      // Don't keep dispatching invalidations until build is called again.
+      isClean = false;
+    }
+  }
+
+  @Override
+  public void markDirty() {
+    onChanged();
+  }
+
+  /**
+   * Increments the mod counts so that an ConcurrentModificationException can
+   * be thrown if calling code tries to modify the builder while its iterating
+   * the list.
+   */
+  private void incrementModCounts() {
+    if (externalMessageList != null) {
+      externalMessageList.incrementModCount();
+    }
+    if (externalBuilderList != null) {
+      externalBuilderList.incrementModCount();
+    }
+    if (externalMessageOrBuilderList != null) {
+      externalMessageOrBuilderList.incrementModCount();
+    }
+  }
+
+  /**
+   * Provides a live view of the builder as a list of messages.
+   *
+   * @param <MType> the type of message for the field
+   * @param <BType> the type of builder for the field
+   * @param <IType> the common interface for the message and the builder
+   */
+  private static class MessageExternalList<
+      MType extends GeneratedMessage,
+      BType extends GeneratedMessage.Builder,
+      IType extends MessageOrBuilder>
+      extends AbstractList<MType> implements List<MType> {
+
+    RepeatedFieldBuilder<MType, BType, IType> builder;
+
+    MessageExternalList(
+        RepeatedFieldBuilder<MType, BType, IType> builder) {
+      this.builder = builder;
+    }
+
+    public int size() {
+      return this.builder.getCount();
+    }
+
+    public MType get(int index) {
+      return builder.getMessage(index);
+    }
+
+    void incrementModCount() {
+      modCount++;
+    }
+  }
+
+  /**
+   * Provides a live view of the builder as a list of builders.
+   *
+   * @param <MType> the type of message for the field
+   * @param <BType> the type of builder for the field
+   * @param <IType> the common interface for the message and the builder
+   */
+  private static class BuilderExternalList<
+      MType extends GeneratedMessage,
+      BType extends GeneratedMessage.Builder,
+      IType extends MessageOrBuilder>
+      extends AbstractList<BType> implements List<BType> {
+
+    RepeatedFieldBuilder<MType, BType, IType> builder;
+
+    BuilderExternalList(
+        RepeatedFieldBuilder<MType, BType, IType> builder) {
+      this.builder = builder;
+    }
+
+    public int size() {
+      return this.builder.getCount();
+    }
+
+    public BType get(int index) {
+      return builder.getBuilder(index);
+    }
+
+    void incrementModCount() {
+      modCount++;
+    }
+  }
+
+  /**
+   * Provides a live view of the builder as a list of builders.
+   *
+   * @param <MType> the type of message for the field
+   * @param <BType> the type of builder for the field
+   * @param <IType> the common interface for the message and the builder
+   */
+  private static class MessageOrBuilderExternalList<
+      MType extends GeneratedMessage,
+      BType extends GeneratedMessage.Builder,
+      IType extends MessageOrBuilder>
+      extends AbstractList<IType> implements List<IType> {
+
+    RepeatedFieldBuilder<MType, BType, IType> builder;
+
+    MessageOrBuilderExternalList(
+        RepeatedFieldBuilder<MType, BType, IType> builder) {
+      this.builder = builder;
+    }
+
+    public int size() {
+      return this.builder.getCount();
+    }
+
+    public IType get(int index) {
+      return builder.getMessageOrBuilder(index);
+    }
+
+    void incrementModCount() {
+      modCount++;
+    }
+  }
+}
diff --git a/java/src/main/java/com/google/protobuf/ServiceException.java b/java/src/main/java/com/google/protobuf/ServiceException.java
index c043a77..cde669d 100644
--- a/java/src/main/java/com/google/protobuf/ServiceException.java
+++ b/java/src/main/java/com/google/protobuf/ServiceException.java
@@ -35,10 +35,18 @@
  *
  * @author cpovirk@google.com (Chris Povirk)
  */
-public final class ServiceException extends Exception {
+public class ServiceException extends Exception {
   private static final long serialVersionUID = -1219262335729891920L;
 
   public ServiceException(final String message) {
     super(message);
   }
+
+  public ServiceException(final Throwable cause) {
+    super(cause);
+  }
+
+  public ServiceException(final String message, final Throwable cause) {
+    super(message, cause);
+  }
 }
diff --git a/java/src/main/java/com/google/protobuf/SingleFieldBuilder.java b/java/src/main/java/com/google/protobuf/SingleFieldBuilder.java
new file mode 100644
index 0000000..a92042e
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/SingleFieldBuilder.java
@@ -0,0 +1,241 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+/**
+ * <code>SingleFieldBuilder</code> implements a structure that a protocol
+ * message uses to hold a single field of another protocol message. It supports
+ * the classical use case of setting an immutable {@link Message} as the value
+ * of the field and is highly optimized around this.
+ * <br>
+ * It also supports the additional use case of setting a {@link Message.Builder}
+ * as the field and deferring conversion of that <code>Builder</code>
+ * to an immutable <code>Message</code>. In this way, it's possible to maintain
+ * a tree of <code>Builder</code>'s that acts as a fully read/write data
+ * structure.
+ * <br>
+ * Logically, one can think of a tree of builders as converting the entire tree
+ * to messages when build is called on the root or when any method is called
+ * that desires a Message instead of a Builder. In terms of the implementation,
+ * the <code>SingleFieldBuilder</code> and <code>RepeatedFieldBuilder</code>
+ * classes cache messages that were created so that messages only need to be
+ * created when some change occured in its builder or a builder for one of its
+ * descendants.
+ *
+ * @param <MType> the type of message for the field
+ * @param <BType> the type of builder for the field
+ * @param <IType> the common interface for the message and the builder
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class SingleFieldBuilder
+    <MType extends GeneratedMessage,
+     BType extends GeneratedMessage.Builder,
+     IType extends MessageOrBuilder>
+    implements GeneratedMessage.BuilderParent {
+
+  // Parent to send changes to.
+  private GeneratedMessage.BuilderParent parent;
+
+  // Invariant: one of builder or message fields must be non-null.
+
+  // If set, this is the case where we are backed by a builder. In this case,
+  // message field represents a cached message for the builder (or null if
+  // there is no cached message).
+  private BType builder;
+
+  // If builder is non-null, this represents a cached message from the builder.
+  // If builder is null, this is the authoritative message for the field.
+  private MType message;
+
+  // Indicates that we've built a message and so we are now obligated
+  // to dispatch dirty invalidations. See GeneratedMessage.BuilderListener.
+  private boolean isClean;
+
+  public SingleFieldBuilder(
+      MType message,
+      GeneratedMessage.BuilderParent parent,
+      boolean isClean) {
+    if (message == null) {
+      throw new NullPointerException();
+    }
+    this.message = message;
+    this.parent = parent;
+    this.isClean = isClean;
+  }
+
+  public void dispose() {
+    // Null out parent so we stop sending it invalidations.
+    parent = null;
+  }
+
+  /**
+   * Get the message for the field. If the message is currently stored
+   * as a <code>Builder</code>, it is converted to a <code>Message</code> by
+   * calling {@link Message.Builder#buildPartial} on it. If no message has
+   * been set, returns the default instance of the message.
+   *
+   * @return the message for the field
+   */
+  @SuppressWarnings("unchecked")
+  public MType getMessage() {
+    if (message == null) {
+      // If message is null, the invariant is that we must be have a builder.
+      message = (MType) builder.buildPartial();
+    }
+    return message;
+  }
+
+  /**
+   * Builds the message and returns it.
+   *
+   * @return the message
+   */
+  public MType build() {
+    // Now that build has been called, we are required to dispatch
+    // invalidations.
+    isClean = true;
+    return getMessage();
+  }
+
+  /**
+   * Gets a builder for the field. If no builder has been created yet, a
+   * builder is created on demand by calling {@link Message#toBuilder}.
+   *
+   * @return The builder for the field
+   */
+  @SuppressWarnings("unchecked")
+  public BType getBuilder() {
+    if (builder == null) {
+      // builder.mergeFrom() on a fresh builder
+      // does not create any sub-objects with independent clean/dirty states,
+      // therefore setting the builder itself to clean without actually calling
+      // build() cannot break any invariants.
+      builder = (BType) message.newBuilderForType(this);
+      builder.mergeFrom(message); // no-op if message is the default message
+      builder.markClean();
+    }
+    return builder;
+  }
+
+  /**
+   * Gets the base class interface for the field. This may either be a builder
+   * or a message. It will return whatever is more efficient.
+   *
+   * @return the message or builder for the field as the base class interface
+   */
+  @SuppressWarnings("unchecked")
+  public IType getMessageOrBuilder() {
+    if (builder != null) {
+      return  (IType) builder;
+    } else {
+      return (IType) message;
+    }
+  }
+
+  /**
+   * Sets a  message for the field replacing any existing value.
+   *
+   * @param message the message to set
+   * @return the builder
+   */
+  public SingleFieldBuilder<MType, BType, IType> setMessage(
+      MType message) {
+    if (message == null) {
+      throw new NullPointerException();
+    }
+    this.message = message;
+    if (builder != null) {
+      builder.dispose();
+      builder = null;
+    }
+    onChanged();
+    return this;
+  }
+
+  /**
+   * Merges the field from another field.
+   *
+   * @param value the value to merge from
+   * @return the builder
+   */
+  public SingleFieldBuilder<MType, BType, IType> mergeFrom(
+      MType value) {
+    if (builder == null && message == message.getDefaultInstanceForType()) {
+      message = value;
+    } else {
+      getBuilder().mergeFrom(value);
+    }
+    onChanged();
+    return this;
+  }
+
+  /**
+   * Clears the value of the field.
+   *
+   * @return the builder
+   */
+  @SuppressWarnings("unchecked")
+  public SingleFieldBuilder<MType, BType, IType> clear() {
+    message = (MType) (message != null ?
+        message.getDefaultInstanceForType() :
+        builder.getDefaultInstanceForType());
+    if (builder != null) {
+      builder.dispose();
+      builder = null;
+    }
+    onChanged();
+    return this;
+  }
+
+  /**
+   * Called when a the builder or one of its nested children has changed
+   * and any parent should be notified of its invalidation.
+   */
+  private void onChanged() {
+    // If builder is null, this is the case where onChanged is being called
+    // from setMessage or clear.
+    if (builder != null) {
+      message = null;
+    }
+    if (isClean && parent != null) {
+      parent.markDirty();
+
+      // Don't keep dispatching invalidations until build is called again.
+      isClean = false;
+    }
+  }
+
+  @Override
+  public void markDirty() {
+    onChanged();
+  }
+}
diff --git a/java/src/main/java/com/google/protobuf/SmallSortedMap.java b/java/src/main/java/com/google/protobuf/SmallSortedMap.java
new file mode 100644
index 0000000..ccc2016
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/SmallSortedMap.java
@@ -0,0 +1,618 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import java.util.AbstractMap;
+import java.util.AbstractSet;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.TreeMap;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.SortedMap;
+
+/**
+ * A custom map implementation from FieldDescriptor to Object optimized to
+ * minimize the number of memory allocations for instances with a small number
+ * of mappings. The implementation stores the first {@code k} mappings in an
+ * array for a configurable value of {@code k}, allowing direct access to the
+ * corresponding {@code Entry}s without the need to create an Iterator. The
+ * remaining entries are stored in an overflow map. Iteration over the entries
+ * in the map should be done as follows:
+ *
+ * <pre>
+ * for (int i = 0; i &lt; fieldMap.getNumArrayEntries(); i++) {
+ *   process(fieldMap.getArrayEntryAt(i));
+ * }
+ * for (Map.Entry&lt;K, V&gt; entry : fieldMap.getOverflowEntries()) {
+ *   process(entry);
+ * }
+ * </pre>
+ *
+ * The resulting iteration is in order of ascending field tag number. The
+ * object returned by {@link #entrySet()} adheres to the same contract but is
+ * less efficient as it necessarily involves creating an object for iteration.
+ * <p>
+ * The tradeoff for this memory efficiency is that the worst case running time
+ * of the {@code put()} operation is {@code O(k + lg n)}, which happens when
+ * entries are added in descending order. {@code k} should be chosen such that
+ * it covers enough common cases without adversely affecting larger maps. In
+ * practice, the worst case scenario does not happen for extensions because
+ * extension fields are serialized and deserialized in order of ascending tag
+ * number, but the worst case scenario can happen for DynamicMessages.
+ * <p>
+ * The running time for all other operations is similar to that of
+ * {@code TreeMap}.
+ * <p>
+ * Instances are not thread-safe until {@link #makeImmutable()} is called,
+ * after which any modifying operation will result in an
+ * {@link UnsupportedOperationException}.
+ *
+ * @author darick@google.com Darick Tong
+ */
+// This class is final for all intents and purposes because the constructor is
+// private. However, the FieldDescriptor-specific logic is encapsulated in
+// a subclass to aid testability of the core logic.
+class SmallSortedMap<K extends Comparable<K>, V> extends AbstractMap<K, V> {
+
+  /**
+   * Creates a new instance for mapping FieldDescriptors to their values.
+   * The {@link #makeImmutable()} implementation will convert the List values
+   * of any repeated fields to unmodifiable lists.
+   *
+   * @param arraySize The size of the entry array containing the
+   *        lexicographically smallest mappings.
+   */
+  static <FieldDescriptorType extends
+      FieldSet.FieldDescriptorLite<FieldDescriptorType>>
+      SmallSortedMap<FieldDescriptorType, Object> newFieldMap(int arraySize) {
+    return new SmallSortedMap<FieldDescriptorType, Object>(arraySize) {
+      @Override
+      @SuppressWarnings("unchecked")
+      public void makeImmutable() {
+        if (!isImmutable()) {
+          for (int i = 0; i < getNumArrayEntries(); i++) {
+            final Map.Entry<FieldDescriptorType, Object> entry =
+                getArrayEntryAt(i);
+            if (entry.getKey().isRepeated()) {
+              final List value = (List) entry.getValue();
+              entry.setValue(Collections.unmodifiableList(value));
+            }
+          }
+          for (Map.Entry<FieldDescriptorType, Object> entry :
+                   getOverflowEntries()) {
+            if (entry.getKey().isRepeated()) {
+              final List value = (List) entry.getValue();
+              entry.setValue(Collections.unmodifiableList(value));
+            }
+          }
+        }
+        super.makeImmutable();
+      }
+    };
+  }
+
+  /**
+   * Creates a new instance for testing.
+   *
+   * @param arraySize The size of the entry array containing the
+   *        lexicographically smallest mappings.
+   */
+  static <K extends Comparable<K>, V> SmallSortedMap<K, V> newInstanceForTest(
+      int arraySize) {
+    return new SmallSortedMap<K, V>(arraySize);
+  }
+
+  private final int maxArraySize;
+  // The "entry array" is actually a List because generic arrays are not
+  // allowed. ArrayList also nicely handles the entry shifting on inserts and
+  // removes.
+  private List<Entry> entryList;
+  private Map<K, V> overflowEntries;
+  private boolean isImmutable;
+  // The EntrySet is a stateless view of the Map. It's initialized the first
+  // time it is requested and reused henceforth.
+  private volatile EntrySet lazyEntrySet;
+
+  /**
+   * @code arraySize Size of the array in which the lexicographically smallest
+   *       mappings are stored. (i.e. the {@code k} referred to in the class
+   *       documentation).
+   */
+  private SmallSortedMap(int arraySize) {
+    this.maxArraySize = arraySize;
+    this.entryList = Collections.emptyList();
+    this.overflowEntries = Collections.emptyMap();
+  }
+
+  /** Make this map immutable from this point forward. */
+  public void makeImmutable() {
+    if (!isImmutable) {
+      // Note: There's no need to wrap the entryList in an unmodifiableList
+      // because none of the list's accessors are exposed. The iterator() of
+      // overflowEntries, on the other hand, is exposed so it must be made
+      // unmodifiable.
+      overflowEntries = overflowEntries.isEmpty() ?
+          Collections.<K, V>emptyMap() :
+          Collections.unmodifiableMap(overflowEntries);
+      isImmutable = true;
+    }
+  }
+
+  /** @return Whether {@link #makeImmutable()} has been called. */
+  public boolean isImmutable() {
+    return isImmutable;
+  }
+
+  /** @return The number of entries in the entry array. */
+  public int getNumArrayEntries() {
+    return entryList.size();
+  }
+
+  /** @return The array entry at the given {@code index}. */
+  public Map.Entry<K, V> getArrayEntryAt(int index) {
+    return entryList.get(index);
+  }
+
+  /** @return There number of overflow entries. */
+  public int getNumOverflowEntries() {
+    return overflowEntries.size();
+  }
+
+  /** @return An iterable over the overflow entries. */
+  public Iterable<Map.Entry<K, V>> getOverflowEntries() {
+    return overflowEntries.isEmpty() ?
+        EmptySet.<Map.Entry<K, V>>iterable() :
+        overflowEntries.entrySet();
+  }
+
+  @Override
+  public int size() {
+    return entryList.size() + overflowEntries.size();
+  }
+
+  /**
+   * The implementation throws a {@code ClassCastException} if o is not an
+   * object of type {@code K}.
+   *
+   * {@inheritDoc}
+   */
+  @Override
+  public boolean containsKey(Object o) {
+    @SuppressWarnings("unchecked")
+    final K key = (K) o;
+    return binarySearchInArray(key) >= 0 || overflowEntries.containsKey(key);
+  }
+
+  /**
+   * The implementation throws a {@code ClassCastException} if o is not an
+   * object of type {@code K}.
+   *
+   * {@inheritDoc}
+   */
+  @Override
+  public V get(Object o) {
+    @SuppressWarnings("unchecked")
+    final K key = (K) o;
+    final int index = binarySearchInArray(key);
+    if (index >= 0) {
+      return entryList.get(index).getValue();
+    }
+    return overflowEntries.get(key);
+  }
+
+  @Override
+  public V put(K key, V value) {
+    checkMutable();
+    final int index = binarySearchInArray(key);
+    if (index >= 0) {
+      // Replace existing array entry.
+      return entryList.get(index).setValue(value);
+    }
+    ensureEntryArrayMutable();
+    final int insertionPoint = -(index + 1);
+    if (insertionPoint >= maxArraySize) {
+      // Put directly in overflow.
+      return getOverflowEntriesMutable().put(key, value);
+    }
+    // Insert new Entry in array.
+    if (entryList.size() == maxArraySize) {
+      // Shift the last array entry into overflow.
+      final Entry lastEntryInArray = entryList.remove(maxArraySize - 1);
+      getOverflowEntriesMutable().put(lastEntryInArray.getKey(),
+                                      lastEntryInArray.getValue());
+    }
+    entryList.add(insertionPoint, new Entry(key, value));
+    return null;
+  }
+
+  @Override
+  public void clear() {
+    checkMutable();
+    if (!entryList.isEmpty()) {
+      entryList.clear();
+    }
+    if (!overflowEntries.isEmpty()) {
+      overflowEntries.clear();
+    }
+  }
+
+  /**
+   * The implementation throws a {@code ClassCastException} if o is not an
+   * object of type {@code K}.
+   *
+   * {@inheritDoc}
+   */
+  @Override
+  public V remove(Object o) {
+    checkMutable();
+    @SuppressWarnings("unchecked")
+    final K key = (K) o;
+    final int index = binarySearchInArray(key);
+    if (index >= 0) {
+      return removeArrayEntryAt(index);
+    }
+    // overflowEntries might be Collections.unmodifiableMap(), so only
+    // call remove() if it is non-empty.
+    if (overflowEntries.isEmpty()) {
+      return null;
+    } else {
+      return overflowEntries.remove(key);
+    }
+  }
+
+  private V removeArrayEntryAt(int index) {
+    checkMutable();
+    final V removed = entryList.remove(index).getValue();
+    if (!overflowEntries.isEmpty()) {
+      // Shift the first entry in the overflow to be the last entry in the
+      // array.
+      final Iterator<Map.Entry<K, V>> iterator =
+          getOverflowEntriesMutable().entrySet().iterator();
+      entryList.add(new Entry(iterator.next()));
+      iterator.remove();
+    }
+    return removed;
+  }
+
+  /**
+   * @param key The key to find in the entry array.
+   * @return The returned integer position follows the same semantics as the
+   *     value returned by {@link java.util.Arrays#binarySearch()}.
+   */
+  private int binarySearchInArray(K key) {
+    int left = 0;
+    int right = entryList.size() - 1;
+
+    // Optimization: For the common case in which entries are added in
+    // ascending tag order, check the largest element in the array before
+    // doing a full binary search.
+    if (right >= 0) {
+      int cmp = key.compareTo(entryList.get(right).getKey());
+      if (cmp > 0) {
+        return -(right + 2);  // Insert point is after "right".
+      } else if (cmp == 0) {
+        return right;
+      }
+    }
+
+    while (left <= right) {
+      int mid = (left + right) / 2;
+      int cmp = key.compareTo(entryList.get(mid).getKey());
+      if (cmp < 0) {
+        right = mid - 1;
+      } else if (cmp > 0) {
+        left = mid + 1;
+      } else {
+        return mid;
+      }
+    }
+    return -(left + 1);
+  }
+
+  /**
+   * Similar to the AbstractMap implementation of {@code keySet()} and
+   * {@code values()}, the entry set is created the first time this method is
+   * called, and returned in response to all subsequent calls.
+   *
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Map.Entry<K, V>> entrySet() {
+    if (lazyEntrySet == null) {
+      lazyEntrySet = new EntrySet();
+    }
+    return lazyEntrySet;
+  }
+
+  /**
+   * @throws UnsupportedOperationException if {@link #makeImmutable()} has
+   *         has been called.
+   */
+  private void checkMutable() {
+    if (isImmutable) {
+      throw new UnsupportedOperationException();
+    }
+  }
+
+  /**
+   * @return a {@link SortedMap} to which overflow entries mappings can be
+   *         added or removed.
+   * @throws UnsupportedOperationException if {@link #makeImmutable()} has been
+   *         called.
+   */
+  @SuppressWarnings("unchecked")
+  private SortedMap<K, V> getOverflowEntriesMutable() {
+    checkMutable();
+    if (overflowEntries.isEmpty() && !(overflowEntries instanceof TreeMap)) {
+      overflowEntries = new TreeMap<K, V>();
+    }
+    return (SortedMap<K, V>) overflowEntries;
+  }
+
+  /**
+   * Lazily creates the entry list. Any code that adds to the list must first
+   * call this method.
+   */
+  private void ensureEntryArrayMutable() {
+    checkMutable();
+    if (entryList.isEmpty() && !(entryList instanceof ArrayList)) {
+      entryList = new ArrayList<Entry>(maxArraySize);
+    }
+  }
+
+  /**
+   * Entry implementation that implements Comparable in order to support
+   * binary search witin the entry array. Also checks mutability in
+   * {@link #setValue()}.
+   */
+  private class Entry implements Map.Entry<K, V>, Comparable<Entry> {
+
+    private final K key;
+    private V value;
+
+    Entry(Map.Entry<K, V> copy) {
+      this(copy.getKey(), copy.getValue());
+    }
+
+    Entry(K key, V value) {
+      this.key = key;
+      this.value = value;
+    }
+
+    @Override
+    public K getKey() {
+      return key;
+    }
+
+    @Override
+    public V getValue() {
+      return value;
+    }
+
+    @Override
+    public int compareTo(Entry other) {
+      return getKey().compareTo(other.getKey());
+    }
+
+    @Override
+    public V setValue(V newValue) {
+      checkMutable();
+      final V oldValue = this.value;
+      this.value = newValue;
+      return oldValue;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+      if (o == this) {
+        return true;
+      }
+      if (!(o instanceof Map.Entry)) {
+        return false;
+      }
+      @SuppressWarnings("unchecked")
+      Map.Entry<?, ?> other = (Map.Entry<?, ?>) o;
+      return equals(key, other.getKey()) && equals(value, other.getValue());
+    }
+
+    @Override
+    public int hashCode() {
+      return (key == null ? 0 : key.hashCode()) ^
+          (value == null ? 0 : value.hashCode());
+    }
+
+    @Override
+    public String toString() {
+      return key + "=" + value;
+    }
+
+    /** equals() that handles null values. */
+    private boolean equals(Object o1, Object o2) {
+      return o1 == null ? o2 == null : o1.equals(o2);
+    }
+  }
+
+  /**
+   * Stateless view of the entries in the field map.
+   */
+  private class EntrySet extends AbstractSet<Map.Entry<K, V>> {
+
+    @Override
+    public Iterator<Map.Entry<K, V>> iterator() {
+      return new EntryIterator();
+    }
+
+    @Override
+    public int size() {
+      return SmallSortedMap.this.size();
+    }
+
+    /**
+     * Throws a {@link ClassCastException} if o is not of the expected type.
+     *
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean contains(Object o) {
+      @SuppressWarnings("unchecked")
+      final Map.Entry<K, V> entry = (Map.Entry<K, V>) o;
+      final V existing = get(entry.getKey());
+      final V value = entry.getValue();
+      return existing == value ||
+          (existing != null && existing.equals(value));
+    }
+
+    @Override
+    public boolean add(Map.Entry<K, V> entry) {
+      if (!contains(entry)) {
+        put(entry.getKey(), entry.getValue());
+        return true;
+      }
+      return false;
+    }
+
+    /**
+     * Throws a {@link ClassCastException} if o is not of the expected type.
+     *
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean remove(Object o) {
+      @SuppressWarnings("unchecked")
+      final Map.Entry<K, V> entry = (Map.Entry<K, V>) o;
+      if (contains(entry)) {
+        SmallSortedMap.this.remove(entry.getKey());
+        return true;
+      }
+      return false;
+    }
+
+    @Override
+    public void clear() {
+      SmallSortedMap.this.clear();
+    }
+  }
+
+  /**
+   * Iterator implementation that switches from the entry array to the overflow
+   * entries appropriately.
+   */
+  private class EntryIterator implements Iterator<Map.Entry<K, V>> {
+
+    private int pos = -1;
+    private boolean nextCalledBeforeRemove;
+    private Iterator<Map.Entry<K, V>> lazyOverflowIterator;
+
+    @Override
+    public boolean hasNext() {
+      return (pos + 1) < entryList.size() ||
+          getOverflowIterator().hasNext();
+    }
+
+    @Override
+    public Map.Entry<K, V> next() {
+      nextCalledBeforeRemove = true;
+      // Always increment pos so that we know whether the last returned value
+      // was from the array or from overflow.
+      if (++pos < entryList.size()) {
+        return entryList.get(pos);
+      }
+      return getOverflowIterator().next();
+    }
+
+    @Override
+    public void remove() {
+      if (!nextCalledBeforeRemove) {
+        throw new IllegalStateException("remove() was called before next()");
+      }
+      nextCalledBeforeRemove = false;
+      checkMutable();
+
+      if (pos < entryList.size()) {
+        removeArrayEntryAt(pos--);
+      } else {
+        getOverflowIterator().remove();
+      }
+    }
+
+    /**
+     * It is important to create the overflow iterator only after the array
+     * entries have been iterated over because the overflow entry set changes
+     * when the client calls remove() on the array entries, which invalidates
+     * any existing iterators.
+     */
+    private Iterator<Map.Entry<K, V>> getOverflowIterator() {
+      if (lazyOverflowIterator == null) {
+        lazyOverflowIterator = overflowEntries.entrySet().iterator();
+      }
+      return lazyOverflowIterator;
+    }
+  }
+
+  /**
+   * Helper class that holds immutable instances of an Iterable/Iterator that
+   * we return when the overflow entries is empty. This eliminates the creation
+   * of an Iterator object when there is nothing to iterate over.
+   */
+  private static class EmptySet {
+
+    private static final Iterator<Object> ITERATOR = new Iterator<Object>() {
+      @Override
+      public boolean hasNext() {
+        return false;
+      }
+      @Override
+      public Object next() {
+        throw new NoSuchElementException();
+      }
+      @Override
+      public void remove() {
+        throw new UnsupportedOperationException();
+      }
+    };
+
+    private static final Iterable<Object> ITERABLE = new Iterable<Object>() {
+      @Override
+      public Iterator<Object> iterator() {
+        return ITERATOR;
+      }
+    };
+
+    @SuppressWarnings("unchecked")
+    static <T> Iterable<T> iterable() {
+      return (Iterable<T>) ITERABLE;
+    }
+  }
+}
diff --git a/java/src/main/java/com/google/protobuf/TextFormat.java b/java/src/main/java/com/google/protobuf/TextFormat.java
index 7ca2b4b..d5fbdab 100644
--- a/java/src/main/java/com/google/protobuf/TextFormat.java
+++ b/java/src/main/java/com/google/protobuf/TextFormat.java
@@ -46,15 +46,17 @@
 import java.util.regex.Pattern;
 
 /**
- * Provide ascii text parsing and formatting support for proto2 instances.
+ * Provide text parsing and formatting support for proto2 instances.
  * The implementation largely follows google/protobuf/text_format.cc.
  *
  * @author wenboz@google.com Wenbo Zhu
  * @author kenton@google.com Kenton Varda
  */
 public final class TextFormat {
-  private TextFormat() {
-  }
+  private TextFormat() {}
+
+  private static final Printer DEFAULT_PRINTER = new Printer(false);
+  private static final Printer SINGLE_LINE_PRINTER = new Printer(true);
 
   /**
    * Outputs a textual representation of the Protocol Message supplied into
@@ -63,16 +65,44 @@
    */
   public static void print(final Message message, final Appendable output)
                            throws IOException {
-    final TextGenerator generator = new TextGenerator(output);
-    print(message, generator);
+    DEFAULT_PRINTER.print(message, new TextGenerator(output));
   }
 
   /** Outputs a textual representation of {@code fields} to {@code output}. */
   public static void print(final UnknownFieldSet fields,
                            final Appendable output)
                            throws IOException {
-    final TextGenerator generator = new TextGenerator(output);
-    printUnknownFields(fields, generator);
+    DEFAULT_PRINTER.printUnknownFields(fields, new TextGenerator(output));
+  }
+
+  /**
+   * Generates a human readable form of this message, useful for debugging and
+   * other purposes, with no newline characters.
+   */
+  public static String shortDebugString(final Message message) {
+    try {
+      final StringBuilder sb = new StringBuilder();
+      SINGLE_LINE_PRINTER.print(message, new TextGenerator(sb));
+      // Single line mode currently might have an extra space at the end.
+      return sb.toString().trim();
+    } catch (IOException e) {
+      throw new IllegalStateException(e);
+    }
+  }
+
+  /**
+   * Generates a human readable form of the unknown fields, useful for debugging
+   * and other purposes, with no newline characters.
+   */
+  public static String shortDebugString(final UnknownFieldSet fields) {
+    try {
+      final StringBuilder sb = new StringBuilder();
+      SINGLE_LINE_PRINTER.printUnknownFields(fields, new TextGenerator(sb));
+      // Single line mode currently might have an extra space at the end.
+      return sb.toString().trim();
+    } catch (IOException e) {
+      throw new IllegalStateException(e);
+    }
   }
 
   /**
@@ -85,9 +115,7 @@
       print(message, text);
       return text.toString();
     } catch (IOException e) {
-      throw new RuntimeException(
-        "Writing to a StringBuilder threw an IOException (should never " +
-        "happen).", e);
+      throw new IllegalStateException(e);
     }
   }
 
@@ -101,28 +129,15 @@
       print(fields, text);
       return text.toString();
     } catch (IOException e) {
-      throw new RuntimeException(
-        "Writing to a StringBuilder threw an IOException (should never " +
-        "happen).", e);
+      throw new IllegalStateException(e);
     }
   }
 
-  private static void print(final Message message,
-                            final TextGenerator generator)
-      throws IOException {
-    for (final Map.Entry<FieldDescriptor, Object> field :
-         message.getAllFields().entrySet()) {
-      printField(field.getKey(), field.getValue(), generator);
-    }
-    printUnknownFields(message.getUnknownFields(), generator);
-  }
-
   public static void printField(final FieldDescriptor field,
                                 final Object value,
                                 final Appendable output)
                                 throws IOException {
-    final TextGenerator generator = new TextGenerator(output);
-    printField(field, value, generator);
+    DEFAULT_PRINTER.printField(field, value, new TextGenerator(output));
   }
 
   public static String printFieldToString(final FieldDescriptor field,
@@ -132,157 +147,263 @@
       printField(field, value, text);
       return text.toString();
     } catch (IOException e) {
-      throw new RuntimeException(
-        "Writing to a StringBuilder threw an IOException (should never " +
-        "happen).", e);
+      throw new IllegalStateException(e);
     }
   }
 
-  private static void printField(final FieldDescriptor field,
-                                final Object value,
-                                final TextGenerator generator)
-                                throws IOException {
-    if (field.isRepeated()) {
-      // Repeated field.  Print each element.
-      for (final Object element : (List<?>) value) {
-        printSingleField(field, element, generator);
-      }
-    } else {
-      printSingleField(field, value, generator);
-    }
+  /**
+   * Outputs a textual representation of the value of given field value.
+   *
+   * @param field the descriptor of the field
+   * @param value the value of the field
+   * @param output the output to which to append the formatted value
+   * @throws ClassCastException if the value is not appropriate for the
+   *     given field descriptor
+   * @throws IOException if there is an exception writing to the output
+   */
+  public static void printFieldValue(final FieldDescriptor field,
+                                     final Object value,
+                                     final Appendable output)
+                                     throws IOException {
+    DEFAULT_PRINTER.printFieldValue(field, value, new TextGenerator(output));
   }
 
-  private static void printSingleField(final FieldDescriptor field,
-                                       final Object value,
-                                       final TextGenerator generator)
-                                       throws IOException {
-    if (field.isExtension()) {
-      generator.print("[");
-      // We special-case MessageSet elements for compatibility with proto1.
-      if (field.getContainingType().getOptions().getMessageSetWireFormat()
-          && (field.getType() == FieldDescriptor.Type.MESSAGE)
-          && (field.isOptional())
-          // object equality
-          && (field.getExtensionScope() == field.getMessageType())) {
-        generator.print(field.getMessageType().getFullName());
-      } else {
-        generator.print(field.getFullName());
-      }
-      generator.print("]");
-    } else {
-      if (field.getType() == FieldDescriptor.Type.GROUP) {
-        // Groups must be serialized with their original capitalization.
-        generator.print(field.getMessageType().getName());
-      } else {
-        generator.print(field.getName());
-      }
-    }
-
-    if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
-      generator.print(" {\n");
-      generator.indent();
-    } else {
-      generator.print(": ");
-    }
-
-    printFieldValue(field, value, generator);
-
-    if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
-      generator.outdent();
-      generator.print("}");
-    }
-    generator.print("\n");
+  /**
+   * Outputs a textual representation of the value of an unknown field.
+   *
+   * @param tag the field's tag number
+   * @param value the value of the field
+   * @param output the output to which to append the formatted value
+   * @throws ClassCastException if the value is not appropriate for the
+   *     given field descriptor
+   * @throws IOException if there is an exception writing to the output
+   */
+  public static void printUnknownFieldValue(final int tag,
+                                            final Object value,
+                                            final Appendable output)
+                                            throws IOException {
+    printUnknownFieldValue(tag, value, new TextGenerator(output));
   }
 
-  private static void printFieldValue(final FieldDescriptor field,
-                                      final Object value,
-                                      final TextGenerator generator)
-                                      throws IOException {
-    switch (field.getType()) {
-      case INT32:
-      case INT64:
-      case SINT32:
-      case SINT64:
-      case SFIXED32:
-      case SFIXED64:
-      case FLOAT:
-      case DOUBLE:
-      case BOOL:
-        // Good old toString() does what we want for these types.
-        generator.print(value.toString());
-        break;
-
-      case UINT32:
-      case FIXED32:
-        generator.print(unsignedToString((Integer) value));
-        break;
-
-      case UINT64:
-      case FIXED64:
+  private static void printUnknownFieldValue(final int tag,
+                                             final Object value,
+                                             final TextGenerator generator)
+                                             throws IOException {
+    switch (WireFormat.getTagWireType(tag)) {
+      case WireFormat.WIRETYPE_VARINT:
         generator.print(unsignedToString((Long) value));
         break;
-
-      case STRING:
-        generator.print("\"");
-        generator.print(escapeText((String) value));
-        generator.print("\"");
+      case WireFormat.WIRETYPE_FIXED32:
+        generator.print(
+            String.format((Locale) null, "0x%08x", (Integer) value));
         break;
-
-      case BYTES:
+      case WireFormat.WIRETYPE_FIXED64:
+        generator.print(String.format((Locale) null, "0x%016x", (Long) value));
+        break;
+      case WireFormat.WIRETYPE_LENGTH_DELIMITED:
         generator.print("\"");
         generator.print(escapeBytes((ByteString) value));
         generator.print("\"");
         break;
-
-      case ENUM:
-        generator.print(((EnumValueDescriptor) value).getName());
+      case WireFormat.WIRETYPE_START_GROUP:
+        DEFAULT_PRINTER.printUnknownFields((UnknownFieldSet) value, generator);
         break;
-
-      case MESSAGE:
-      case GROUP:
-        print((Message) value, generator);
-        break;
+      default:
+        throw new IllegalArgumentException("Bad tag: " + tag);
     }
   }
 
-  private static void printUnknownFields(final UnknownFieldSet unknownFields,
-                                         final TextGenerator generator)
-                                         throws IOException {
-    for (final Map.Entry<Integer, UnknownFieldSet.Field> entry :
-         unknownFields.asMap().entrySet()) {
-      final UnknownFieldSet.Field field = entry.getValue();
+  /** Helper class for converting protobufs to text. */
+  private static final class Printer {
+    /** Whether to omit newlines from the output. */
+    final boolean singleLineMode;
 
-      for (final long value : field.getVarintList()) {
-        generator.print(entry.getKey().toString());
+    private Printer(final boolean singleLineMode) {
+      this.singleLineMode = singleLineMode;
+    }
+
+    private void print(final Message message, final TextGenerator generator)
+        throws IOException {
+      for (Map.Entry<FieldDescriptor, Object> field
+          : message.getAllFields().entrySet()) {
+        printField(field.getKey(), field.getValue(), generator);
+      }
+      printUnknownFields(message.getUnknownFields(), generator);
+    }
+
+    private void printField(final FieldDescriptor field, final Object value,
+        final TextGenerator generator) throws IOException {
+      if (field.isRepeated()) {
+        // Repeated field.  Print each element.
+        for (Object element : (List<?>) value) {
+          printSingleField(field, element, generator);
+        }
+      } else {
+        printSingleField(field, value, generator);
+      }
+    }
+
+    private void printSingleField(final FieldDescriptor field,
+                                  final Object value,
+                                  final TextGenerator generator)
+                                  throws IOException {
+      if (field.isExtension()) {
+        generator.print("[");
+        // We special-case MessageSet elements for compatibility with proto1.
+        if (field.getContainingType().getOptions().getMessageSetWireFormat()
+            && (field.getType() == FieldDescriptor.Type.MESSAGE)
+            && (field.isOptional())
+            // object equality
+            && (field.getExtensionScope() == field.getMessageType())) {
+          generator.print(field.getMessageType().getFullName());
+        } else {
+          generator.print(field.getFullName());
+        }
+        generator.print("]");
+      } else {
+        if (field.getType() == FieldDescriptor.Type.GROUP) {
+          // Groups must be serialized with their original capitalization.
+          generator.print(field.getMessageType().getName());
+        } else {
+          generator.print(field.getName());
+        }
+      }
+
+      if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+        if (singleLineMode) {
+          generator.print(" { ");
+        } else {
+          generator.print(" {\n");
+          generator.indent();
+        }
+      } else {
         generator.print(": ");
-        generator.print(unsignedToString(value));
-        generator.print("\n");
       }
-      for (final int value : field.getFixed32List()) {
-        generator.print(entry.getKey().toString());
+
+      printFieldValue(field, value, generator);
+
+      if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+        if (singleLineMode) {
+          generator.print("} ");
+        } else {
+          generator.outdent();
+          generator.print("}\n");
+        }
+      } else {
+        if (singleLineMode) {
+          generator.print(" ");
+        } else {
+          generator.print("\n");
+        }
+      }
+    }
+
+    private void printFieldValue(final FieldDescriptor field,
+                                 final Object value,
+                                 final TextGenerator generator)
+                                 throws IOException {
+      switch (field.getType()) {
+        case INT32:
+        case SINT32:
+        case SFIXED32:
+          generator.print(((Integer) value).toString());
+          break;
+
+        case INT64:
+        case SINT64:
+        case SFIXED64:
+          generator.print(((Long) value).toString());
+          break;
+
+        case BOOL:
+          generator.print(((Boolean) value).toString());
+          break;
+
+        case FLOAT:
+          generator.print(((Float) value).toString());
+          break;
+
+        case DOUBLE:
+          generator.print(((Double) value).toString());
+          break;
+
+        case UINT32:
+        case FIXED32:
+          generator.print(unsignedToString((Integer) value));
+          break;
+
+        case UINT64:
+        case FIXED64:
+          generator.print(unsignedToString((Long) value));
+          break;
+
+        case STRING:
+          generator.print("\"");
+          generator.print(escapeText((String) value));
+          generator.print("\"");
+          break;
+
+        case BYTES:
+          generator.print("\"");
+          generator.print(escapeBytes((ByteString) value));
+          generator.print("\"");
+          break;
+
+        case ENUM:
+          generator.print(((EnumValueDescriptor) value).getName());
+          break;
+
+        case MESSAGE:
+        case GROUP:
+          print((Message) value, generator);
+          break;
+      }
+    }
+
+    private void printUnknownFields(final UnknownFieldSet unknownFields,
+                                    final TextGenerator generator)
+                                    throws IOException {
+      for (Map.Entry<Integer, UnknownFieldSet.Field> entry :
+               unknownFields.asMap().entrySet()) {
+        final int number = entry.getKey();
+        final UnknownFieldSet.Field field = entry.getValue();
+        printUnknownField(number, WireFormat.WIRETYPE_VARINT,
+            field.getVarintList(), generator);
+        printUnknownField(number, WireFormat.WIRETYPE_FIXED32,
+            field.getFixed32List(), generator);
+        printUnknownField(number, WireFormat.WIRETYPE_FIXED64,
+            field.getFixed64List(), generator);
+        printUnknownField(number, WireFormat.WIRETYPE_LENGTH_DELIMITED,
+            field.getLengthDelimitedList(), generator);
+        for (final UnknownFieldSet value : field.getGroupList()) {
+          generator.print(entry.getKey().toString());
+          if (singleLineMode) {
+            generator.print(" { ");
+          } else {
+            generator.print(" {\n");
+            generator.indent();
+          }
+          printUnknownFields(value, generator);
+          if (singleLineMode) {
+            generator.print("} ");
+          } else {
+            generator.outdent();
+            generator.print("}\n");
+          }
+        }
+      }
+    }
+
+    private void printUnknownField(final int number,
+                                   final int wireType,
+                                   final List<?> values,
+                                   final TextGenerator generator)
+                                   throws IOException {
+      for (final Object value : values) {
+        generator.print(String.valueOf(number));
         generator.print(": ");
-        generator.print(String.format((Locale) null, "0x%08x", value));
-        generator.print("\n");
-      }
-      for (final long value : field.getFixed64List()) {
-        generator.print(entry.getKey().toString());
-        generator.print(": ");
-        generator.print(String.format((Locale) null, "0x%016x", value));
-        generator.print("\n");
-      }
-      for (final ByteString value : field.getLengthDelimitedList()) {
-        generator.print(entry.getKey().toString());
-        generator.print(": \"");
-        generator.print(escapeBytes(value));
-        generator.print("\"\n");
-      }
-      for (final UnknownFieldSet value : field.getGroupList()) {
-        generator.print(entry.getKey().toString());
-        generator.print(" {\n");
-        generator.indent();
-        printUnknownFields(value, generator);
-        generator.outdent();
-        generator.print("}\n");
+        printUnknownFieldValue(wireType, value, generator);
+        generator.print(singleLineMode ? " " : "\n");
       }
     }
   }
@@ -312,9 +433,9 @@
    * An inner class for writing text to the output stream.
    */
   private static final class TextGenerator {
-    private Appendable output;
-    private boolean atStartOfLine = true;
+    private final Appendable output;
     private final StringBuilder indent = new StringBuilder();
+    private boolean atStartOfLine = true;
 
     private TextGenerator(final Appendable output) {
       this.output = output;
@@ -670,10 +791,14 @@
      * Otherwise, throw a {@link ParseException}.
      */
     public boolean consumeBoolean() throws ParseException {
-      if (currentToken.equals("true")) {
+      if (currentToken.equals("true") ||
+          currentToken.equals("t") ||
+          currentToken.equals("1")) {
         nextToken();
         return true;
-      } else if (currentToken.equals("false")) {
+      } else if (currentToken.equals("false") ||
+                 currentToken.equals("f") ||
+                 currentToken.equals("0")) {
         nextToken();
         return false;
       } else {
@@ -1063,6 +1188,9 @@
         case '\'': builder.append("\\\'"); break;
         case '"' : builder.append("\\\""); break;
         default:
+          // Note:  Bytes with the high-order bit set should be escaped.  Since
+          //   bytes are signed, such bytes will compare less than 0x20, hence
+          //   the following line is correct.
           if (b >= 0x20) {
             builder.append((char) b);
           } else {
@@ -1082,27 +1210,37 @@
    * {@link #escapeBytes(ByteString)}.  Two-digit hex escapes (starting with
    * "\x") are also recognized.
    */
-  static ByteString unescapeBytes(final CharSequence input)
+  static ByteString unescapeBytes(final CharSequence charString)
       throws InvalidEscapeSequenceException {
-    final byte[] result = new byte[input.length()];
+    // First convert the Java characater sequence to UTF-8 bytes.
+    ByteString input = ByteString.copyFromUtf8(charString.toString());
+    // Then unescape certain byte sequences introduced by ASCII '\\'.  The valid
+    // escapes can all be expressed with ASCII characters, so it is safe to
+    // operate on bytes here.
+    //
+    // Unescaping the input byte array will result in a byte sequence that's no
+    // longer than the input.  That's because each escape sequence is between
+    // two and four bytes long and stands for a single byte.
+    final byte[] result = new byte[input.size()];
     int pos = 0;
-    for (int i = 0; i < input.length(); i++) {
-      char c = input.charAt(i);
+    for (int i = 0; i < input.size(); i++) {
+      byte c = input.byteAt(i);
       if (c == '\\') {
-        if (i + 1 < input.length()) {
+        if (i + 1 < input.size()) {
           ++i;
-          c = input.charAt(i);
+          c = input.byteAt(i);
           if (isOctal(c)) {
             // Octal escape.
             int code = digitValue(c);
-            if (i + 1 < input.length() && isOctal(input.charAt(i + 1))) {
+            if (i + 1 < input.size() && isOctal(input.byteAt(i + 1))) {
               ++i;
-              code = code * 8 + digitValue(input.charAt(i));
+              code = code * 8 + digitValue(input.byteAt(i));
             }
-            if (i + 1 < input.length() && isOctal(input.charAt(i + 1))) {
+            if (i + 1 < input.size() && isOctal(input.byteAt(i + 1))) {
               ++i;
-              code = code * 8 + digitValue(input.charAt(i));
+              code = code * 8 + digitValue(input.byteAt(i));
             }
+            // TODO: Check that 0 <= code && code <= 0xFF.
             result[pos++] = (byte)code;
           } else {
             switch (c) {
@@ -1120,31 +1258,31 @@
               case 'x':
                 // hex escape
                 int code = 0;
-                if (i + 1 < input.length() && isHex(input.charAt(i + 1))) {
+                if (i + 1 < input.size() && isHex(input.byteAt(i + 1))) {
                   ++i;
-                  code = digitValue(input.charAt(i));
+                  code = digitValue(input.byteAt(i));
                 } else {
                   throw new InvalidEscapeSequenceException(
-                    "Invalid escape sequence: '\\x' with no digits");
+                      "Invalid escape sequence: '\\x' with no digits");
                 }
-                if (i + 1 < input.length() && isHex(input.charAt(i + 1))) {
+                if (i + 1 < input.size() && isHex(input.byteAt(i + 1))) {
                   ++i;
-                  code = code * 16 + digitValue(input.charAt(i));
+                  code = code * 16 + digitValue(input.byteAt(i));
                 }
                 result[pos++] = (byte)code;
                 break;
 
               default:
                 throw new InvalidEscapeSequenceException(
-                  "Invalid escape sequence: '\\" + c + '\'');
+                    "Invalid escape sequence: '\\" + (char)c + '\'');
             }
           }
         } else {
           throw new InvalidEscapeSequenceException(
-            "Invalid escape sequence: '\\' at end of string.");
+              "Invalid escape sequence: '\\' at end of string.");
         }
       } else {
-        result[pos++] = (byte)c;
+        result[pos++] = c;
       }
     }
 
@@ -1182,12 +1320,12 @@
   }
 
   /** Is this an octal digit? */
-  private static boolean isOctal(final char c) {
+  private static boolean isOctal(final byte c) {
     return '0' <= c && c <= '7';
   }
 
   /** Is this a hex digit? */
-  private static boolean isHex(final char c) {
+  private static boolean isHex(final byte c) {
     return ('0' <= c && c <= '9') ||
            ('a' <= c && c <= 'f') ||
            ('A' <= c && c <= 'F');
@@ -1198,7 +1336,7 @@
    * numeric value.  This is like {@code Character.digit()} but we don't accept
    * non-ASCII digits.
    */
-  private static int digitValue(final char c) {
+  private static int digitValue(final byte c) {
     if ('0' <= c && c <= '9') {
       return c - '0';
     } else if ('a' <= c && c <= 'z') {
diff --git a/java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java b/java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java
new file mode 100644
index 0000000..ee8fe19
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java
@@ -0,0 +1,146 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import java.util.AbstractList;
+import java.util.RandomAccess;
+import java.util.ListIterator;
+import java.util.Iterator;
+
+/**
+ * An implementation of {@link LazyStringList} that wraps another
+ * {@link LazyStringList} such that it cannot be modified via the wrapper.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class UnmodifiableLazyStringList extends AbstractList<String>
+    implements LazyStringList, RandomAccess {
+
+  private final LazyStringList list;
+
+  public UnmodifiableLazyStringList(LazyStringList list) {
+    this.list = list;
+  }
+
+  @Override
+  public String get(int index) {
+    return list.get(index);
+  }
+
+  @Override
+  public int size() {
+    return list.size();
+  }
+
+  @Override
+  public ByteString getByteString(int index) {
+    return list.getByteString(index);
+  }
+
+  @Override
+  public void add(ByteString element) {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public ListIterator<String> listIterator(final int index) {
+    return new ListIterator<String>() {
+      ListIterator<String> iter = list.listIterator(index);
+
+      @Override
+      public boolean hasNext() {
+        return iter.hasNext();
+      }
+
+      @Override
+      public String next() {
+        return iter.next();
+      }
+
+      @Override
+      public boolean hasPrevious() {
+        return iter.hasPrevious();
+      }
+
+      @Override
+      public String previous() {
+        return iter.previous();
+      }
+
+      @Override
+      public int nextIndex() {
+        return iter.nextIndex();
+      }
+
+      @Override
+      public int previousIndex() {
+        return iter.previousIndex();
+      }
+
+      @Override
+      public void remove() {
+        throw new UnsupportedOperationException();
+      }
+
+      @Override
+      public void set(String o) {
+        throw new UnsupportedOperationException();
+      }
+
+      @Override
+      public void add(String o) {
+        throw new UnsupportedOperationException();
+      }
+    };
+  }
+
+  @Override
+  public Iterator<String> iterator() {
+    return new Iterator<String>() {
+      Iterator<String> iter = list.iterator();
+
+      @Override
+      public boolean hasNext() {
+        return iter.hasNext();
+      }
+
+      @Override
+      public String next() {
+        return iter.next();
+      }
+
+      @Override
+      public void remove() {
+        throw new UnsupportedOperationException();
+      }
+    };
+  }
+}
diff --git a/java/src/main/java/com/google/protobuf/WireFormat.java b/java/src/main/java/com/google/protobuf/WireFormat.java
index c46f7b0..a30f2a3 100644
--- a/java/src/main/java/com/google/protobuf/WireFormat.java
+++ b/java/src/main/java/com/google/protobuf/WireFormat.java
@@ -45,12 +45,12 @@
   // Do not allow instantiation.
   private WireFormat() {}
 
-  static final int WIRETYPE_VARINT           = 0;
-  static final int WIRETYPE_FIXED64          = 1;
-  static final int WIRETYPE_LENGTH_DELIMITED = 2;
-  static final int WIRETYPE_START_GROUP      = 3;
-  static final int WIRETYPE_END_GROUP        = 4;
-  static final int WIRETYPE_FIXED32          = 5;
+  public static final int WIRETYPE_VARINT           = 0;
+  public static final int WIRETYPE_FIXED64          = 1;
+  public static final int WIRETYPE_LENGTH_DELIMITED = 2;
+  public static final int WIRETYPE_START_GROUP      = 3;
+  public static final int WIRETYPE_END_GROUP        = 4;
+  public static final int WIRETYPE_FIXED32          = 5;
 
   static final int TAG_TYPE_BITS = 3;
   static final int TAG_TYPE_MASK = (1 << TAG_TYPE_BITS) - 1;
diff --git a/java/src/test/java/com/google/protobuf/AbstractMessageTest.java b/java/src/test/java/com/google/protobuf/AbstractMessageTest.java
index c44d660..d53ce8d 100644
--- a/java/src/test/java/com/google/protobuf/AbstractMessageTest.java
+++ b/java/src/test/java/com/google/protobuf/AbstractMessageTest.java
@@ -366,7 +366,7 @@
 
   // -----------------------------------------------------------------
   // Tests for equals and hashCode
-  
+
   public void testEqualsAndHashCode() throws Exception {
     TestAllTypes a = TestUtil.getAllSet();
     TestAllTypes b = TestAllTypes.newBuilder().build();
@@ -382,7 +382,7 @@
     checkEqualsIsConsistent(d);
     checkEqualsIsConsistent(e);
     checkEqualsIsConsistent(f);
-    
+
     checkNotEqual(a, b);
     checkNotEqual(a, c);
     checkNotEqual(a, d);
@@ -413,19 +413,20 @@
     checkEqualsIsConsistent(eUnknownFields);
     checkEqualsIsConsistent(fUnknownFields);
 
-    // Subseqent reconstitutions should be identical
+    // Subsequent reconstitutions should be identical
     UnittestProto.TestEmptyMessage eUnknownFields2 =
         UnittestProto.TestEmptyMessage.parseFrom(e.toByteArray());
     checkEqualsIsConsistent(eUnknownFields, eUnknownFields2);
   }
-  
+
+
   /**
    * Asserts that the given proto has symetric equals and hashCode methods.
    */
   private void checkEqualsIsConsistent(Message message) {
     // Object should be equal to itself.
     assertEquals(message, message);
-    
+
     // Object should be equal to a dynamic copy of itself.
     DynamicMessage dynamic = DynamicMessage.newBuilder(message).build();
     checkEqualsIsConsistent(message, dynamic);
@@ -442,7 +443,7 @@
 
   /**
    * Asserts that the given protos are not equal and have different hash codes.
-   * 
+   *
    * @warning It's valid for non-equal objects to have the same hash code, so
    *   this test is stricter than it needs to be. However, this should happen
    *   relatively rarely.
diff --git a/java/src/test/java/com/google/protobuf/CodedInputStreamTest.java b/java/src/test/java/com/google/protobuf/CodedInputStreamTest.java
index 6acd322..83f7f8d 100644
--- a/java/src/test/java/com/google/protobuf/CodedInputStreamTest.java
+++ b/java/src/test/java/com/google/protobuf/CodedInputStreamTest.java
@@ -325,6 +325,27 @@
     assertEquals(2, input.readRawByte());
   }
 
+  /**
+   * Test that a bug in skipRawBytes() has been fixed:  if the skip skips
+   * past the end of a buffer with a limit that has been set past the end of
+   * that buffer, this should not break things.
+   */
+  public void testSkipRawBytesPastEndOfBufferWithLimit() throws Exception {
+    byte[] rawBytes = new byte[] { 1, 2, 3, 4, 5 };
+    CodedInputStream input = CodedInputStream.newInstance(
+        new SmallBlockInputStream(rawBytes, 3));
+
+    int limit = input.pushLimit(4);
+    // In order to expose the bug we need to read at least one byte to prime the
+    // buffer inside the CodedInputStream.
+    assertEquals(1, input.readRawByte());
+    // Skip to the end of the limit.
+    input.skipRawBytes(3);
+    assertTrue(input.isAtEnd());
+    input.popLimit(limit);
+    assertEquals(5, input.readRawByte());
+  }
+
   public void testReadHugeBlob() throws Exception {
     // Allocate and initialize a 1MB blob.
     byte[] blob = new byte[1 << 20];
diff --git a/java/src/test/java/com/google/protobuf/DeprecatedFieldTest.java b/java/src/test/java/com/google/protobuf/DeprecatedFieldTest.java
new file mode 100644
index 0000000..1f8bb44
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/DeprecatedFieldTest.java
@@ -0,0 +1,80 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import protobuf_unittest.UnittestProto.TestDeprecatedFields;
+
+import junit.framework.TestCase;
+
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Method;
+/**
+ * Test field deprecation
+ * 
+ * @author birdo@google.com (Roberto Scaramuzzi)
+ */
+public class DeprecatedFieldTest extends TestCase {
+  private String[] deprecatedGetterNames = {
+      "hasDeprecatedInt32",
+      "getDeprecatedInt32"};
+  
+  private String[] deprecatedBuilderGetterNames = {
+      "hasDeprecatedInt32",
+      "getDeprecatedInt32",
+      "clearDeprecatedInt32"};
+  
+  private String[] deprecatedBuilderSetterNames = {
+      "setDeprecatedInt32"}; 
+  
+  public void testDeprecatedField() throws Exception {
+    Class<?> deprecatedFields = TestDeprecatedFields.class;
+    Class<?> deprecatedFieldsBuilder = TestDeprecatedFields.Builder.class;
+    for (String name : deprecatedGetterNames) {
+      Method method = deprecatedFields.getMethod(name);
+      assertTrue("Method " + name + " should be deprecated",
+          isDeprecated(method));
+    }
+    for (String name : deprecatedBuilderGetterNames) {
+      Method method = deprecatedFieldsBuilder.getMethod(name);
+      assertTrue("Method " + name + " should be deprecated",
+          isDeprecated(method));
+    }
+    for (String name : deprecatedBuilderSetterNames) {
+      Method method = deprecatedFieldsBuilder.getMethod(name, int.class);
+      assertTrue("Method " + name + " should be deprecated",
+          isDeprecated(method));
+    }
+  }
+  
+  private boolean isDeprecated(AnnotatedElement annotated) {
+    return annotated.isAnnotationPresent(Deprecated.class);
+  }
+}
diff --git a/java/src/test/java/com/google/protobuf/DescriptorsTest.java b/java/src/test/java/com/google/protobuf/DescriptorsTest.java
index c77af5d..65d06e3 100644
--- a/java/src/test/java/com/google/protobuf/DescriptorsTest.java
+++ b/java/src/test/java/com/google/protobuf/DescriptorsTest.java
@@ -44,6 +44,7 @@
 
 import com.google.protobuf.test.UnittestImport;
 import com.google.protobuf.test.UnittestImport.ImportEnum;
+import com.google.protobuf.test.UnittestImport.ImportMessage;
 import protobuf_unittest.UnittestProto;
 import protobuf_unittest.UnittestProto.ForeignEnum;
 import protobuf_unittest.UnittestProto.ForeignMessage;
diff --git a/java/src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java b/java/src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java
new file mode 100644
index 0000000..108a28e
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java
@@ -0,0 +1,48 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+/**
+ * A prerun for a test suite that allows running the full protocol buffer
+ * tests in a mode that disables the optimization for not using
+ * {@link RepeatedFieldBuilder} and {@link SingleFieldBuilder} until they are
+ * requested. This allows us to run all the tests through both code paths
+ * and ensures that both code paths produce identical results.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class ForceFieldBuildersPreRun implements Runnable {
+
+  @Override
+  public void run() {
+    GeneratedMessage.enableAlwaysUseFieldBuildersForTesting();
+  }
+}
diff --git a/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java b/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
index 73c71f3..3675e00 100644
--- a/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
+++ b/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
@@ -30,26 +30,43 @@
 
 package com.google.protobuf;
 
+import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
+import com.google.protobuf.test.UnittestImport;
+import protobuf_unittest.EnumWithNoOuter;
+import protobuf_unittest.MessageWithNoOuter;
+import protobuf_unittest.MultipleFilesTestProto;
+import protobuf_unittest.NestedExtension.MyNestedExtension;
+import protobuf_unittest.NestedExtensionLite.MyNestedExtensionLite;
+import protobuf_unittest.NonNestedExtension;
+import protobuf_unittest.NonNestedExtension.MessageToBeExtended;
+import protobuf_unittest.NonNestedExtension.MyNonNestedExtension;
+import protobuf_unittest.NonNestedExtensionLite;
+import protobuf_unittest.NonNestedExtensionLite.MessageLiteToBeExtended;
+import protobuf_unittest.NonNestedExtensionLite.MyNonNestedExtensionLite;
+import protobuf_unittest.ServiceWithNoOuter;
 import protobuf_unittest.UnittestOptimizeFor.TestOptimizedForSize;
 import protobuf_unittest.UnittestOptimizeFor.TestOptionalOptimizedForSize;
 import protobuf_unittest.UnittestOptimizeFor.TestRequiredOptimizedForSize;
 import protobuf_unittest.UnittestProto;
-import protobuf_unittest.UnittestProto.ForeignMessage;
 import protobuf_unittest.UnittestProto.ForeignEnum;
-import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.ForeignMessage;
+import protobuf_unittest.UnittestProto.ForeignMessageOrBuilder;
 import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder;
 import protobuf_unittest.UnittestProto.TestExtremeDefaultValues;
 import protobuf_unittest.UnittestProto.TestPackedTypes;
 import protobuf_unittest.UnittestProto.TestUnpackedTypes;
-import protobuf_unittest.MultipleFilesTestProto;
-import protobuf_unittest.MessageWithNoOuter;
-import protobuf_unittest.EnumWithNoOuter;
-import protobuf_unittest.ServiceWithNoOuter;
-import com.google.protobuf.UnittestLite;
-import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
 
 import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
 import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
 
 /**
  * Unit test for generated messages and generated code.  See also
@@ -68,32 +85,111 @@
                TestAllTypes.newBuilder().getDefaultInstanceForType());
   }
 
-  public void testAccessors() throws Exception {
+  public void testMessageOrBuilder() throws Exception {
     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
     TestUtil.setAllFields(builder);
     TestAllTypes message = builder.build();
     TestUtil.assertAllFieldsSet(message);
   }
 
-  public void testDoubleBuildError() throws Exception {
+  public void testUsingBuilderMultipleTimes() throws Exception {
     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-    builder.build();
-    try {
-      builder.build();
-      fail("Should have thrown exception.");
-    } catch (IllegalStateException e) {
-      // Success.
-    }
+    // primitive field scalar and repeated
+    builder.setOptionalSfixed64(100);
+    builder.addRepeatedInt32(100);
+    // enum field scalar and repeated
+    builder.setOptionalImportEnum(UnittestImport.ImportEnum.IMPORT_BAR);
+    builder.addRepeatedImportEnum(UnittestImport.ImportEnum.IMPORT_BAR);
+    // proto field scalar and repeated
+    builder.setOptionalForeignMessage(ForeignMessage.newBuilder().setC(1));
+    builder.addRepeatedForeignMessage(ForeignMessage.newBuilder().setC(1));
+
+    TestAllTypes value1 = builder.build();
+
+    assertEquals(100, value1.getOptionalSfixed64());
+    assertEquals(100, value1.getRepeatedInt32(0));
+    assertEquals(UnittestImport.ImportEnum.IMPORT_BAR,
+        value1.getOptionalImportEnum());
+    assertEquals(UnittestImport.ImportEnum.IMPORT_BAR,
+        value1.getRepeatedImportEnum(0));
+    assertEquals(1, value1.getOptionalForeignMessage().getC());
+    assertEquals(1, value1.getRepeatedForeignMessage(0).getC());
+
+    // Make sure that builder didn't update previously created values
+    builder.setOptionalSfixed64(200);
+    builder.setRepeatedInt32(0, 200);
+    builder.setOptionalImportEnum(UnittestImport.ImportEnum.IMPORT_FOO);
+    builder.setRepeatedImportEnum(0, UnittestImport.ImportEnum.IMPORT_FOO);
+    builder.setOptionalForeignMessage(ForeignMessage.newBuilder().setC(2));
+    builder.setRepeatedForeignMessage(0, ForeignMessage.newBuilder().setC(2));
+
+    TestAllTypes value2 = builder.build();
+
+    // Make sure value1 didn't change.
+    assertEquals(100, value1.getOptionalSfixed64());
+    assertEquals(100, value1.getRepeatedInt32(0));
+    assertEquals(UnittestImport.ImportEnum.IMPORT_BAR,
+        value1.getOptionalImportEnum());
+    assertEquals(UnittestImport.ImportEnum.IMPORT_BAR,
+        value1.getRepeatedImportEnum(0));
+    assertEquals(1, value1.getOptionalForeignMessage().getC());
+    assertEquals(1, value1.getRepeatedForeignMessage(0).getC());
+
+    // Make sure value2 is correct
+    assertEquals(200, value2.getOptionalSfixed64());
+    assertEquals(200, value2.getRepeatedInt32(0));
+    assertEquals(UnittestImport.ImportEnum.IMPORT_FOO,
+        value2.getOptionalImportEnum());
+    assertEquals(UnittestImport.ImportEnum.IMPORT_FOO,
+        value2.getRepeatedImportEnum(0));
+    assertEquals(2, value2.getOptionalForeignMessage().getC());
+    assertEquals(2, value2.getRepeatedForeignMessage(0).getC());
   }
 
-  public void testClearAfterBuildError() throws Exception {
+  public void testProtosShareRepeatedArraysIfDidntChange() throws Exception {
     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-    builder.build();
-    try {
-      builder.clear();
-      fail("Should have thrown exception.");
-    } catch (IllegalStateException e) {
-      // Success.
+    builder.addRepeatedInt32(100);
+    builder.addRepeatedImportEnum(UnittestImport.ImportEnum.IMPORT_BAR);
+    builder.addRepeatedForeignMessage(ForeignMessage.getDefaultInstance());
+
+    TestAllTypes value1 = builder.build();
+    TestAllTypes value2 = value1.toBuilder().build();
+
+    assertSame(value1.getRepeatedInt32List(), value2.getRepeatedInt32List());
+    assertSame(value1.getRepeatedImportEnumList(),
+        value2.getRepeatedImportEnumList());
+    assertSame(value1.getRepeatedForeignMessageList(),
+        value2.getRepeatedForeignMessageList());
+  }
+
+  public void testRepeatedArraysAreImmutable() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    builder.addRepeatedInt32(100);
+    builder.addRepeatedImportEnum(UnittestImport.ImportEnum.IMPORT_BAR);
+    builder.addRepeatedForeignMessage(ForeignMessage.getDefaultInstance());
+    assertIsUnmodifiable(builder.getRepeatedInt32List());
+    assertIsUnmodifiable(builder.getRepeatedImportEnumList());
+    assertIsUnmodifiable(builder.getRepeatedForeignMessageList());
+    assertIsUnmodifiable(builder.getRepeatedFloatList());
+
+
+    TestAllTypes value = builder.build();
+    assertIsUnmodifiable(value.getRepeatedInt32List());
+    assertIsUnmodifiable(value.getRepeatedImportEnumList());
+    assertIsUnmodifiable(value.getRepeatedForeignMessageList());
+    assertIsUnmodifiable(value.getRepeatedFloatList());
+  }
+
+  private void assertIsUnmodifiable(List<?> list) {
+    if (list == Collections.emptyList()) {
+      // OKAY -- Need to check this b/c EmptyList allows you to call clear.
+    } else {
+      try {
+        list.clear();
+        fail("List wasn't immutable");
+      } catch (UnsupportedOperationException e) {
+        // good
+      }
     }
   }
 
@@ -316,9 +412,19 @@
     assertTrue(Float.isNaN(message.getNanFloat()));
   }
 
+  public void testClear() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TestUtil.assertClear(builder);
+    TestUtil.setAllFields(builder);
+    builder.clear();
+    TestUtil.assertClear(builder);
+  }
+
   public void testReflectionGetters() throws Exception {
     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
     TestUtil.setAllFields(builder);
+    reflectionTester.assertAllFieldsSetViaReflection(builder);
+
     TestAllTypes message = builder.build();
     reflectionTester.assertAllFieldsSetViaReflection(message);
   }
@@ -326,6 +432,8 @@
   public void testReflectionSetters() throws Exception {
     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
     reflectionTester.setAllFieldsViaReflection(builder);
+    TestUtil.assertAllFieldsSet(builder);
+
     TestAllTypes message = builder.build();
     TestUtil.assertAllFieldsSet(message);
   }
@@ -339,6 +447,8 @@
     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
     reflectionTester.setAllFieldsViaReflection(builder);
     reflectionTester.modifyRepeatedFieldsViaReflection(builder);
+    TestUtil.assertRepeatedFieldsModified(builder);
+
     TestAllTypes message = builder.build();
     TestUtil.assertRepeatedFieldsModified(message);
   }
@@ -391,7 +501,7 @@
     new TestUtil.ReflectionTester(TestAllExtensions.getDescriptor(),
                                   TestUtil.getExtensionRegistry());
 
-  public void testExtensionAccessors() throws Exception {
+  public void testExtensionMessageOrBuilder() throws Exception {
     TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
     TestUtil.setAllExtensions(builder);
     TestAllExtensions message = builder.build();
@@ -414,6 +524,8 @@
   public void testExtensionReflectionGetters() throws Exception {
     TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
     TestUtil.setAllExtensions(builder);
+    extensionsReflectionTester.assertAllFieldsSetViaReflection(builder);
+
     TestAllExtensions message = builder.build();
     extensionsReflectionTester.assertAllFieldsSetViaReflection(message);
   }
@@ -421,6 +533,8 @@
   public void testExtensionReflectionSetters() throws Exception {
     TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
     extensionsReflectionTester.setAllFieldsViaReflection(builder);
+    TestUtil.assertAllExtensionsSet(builder);
+
     TestAllExtensions message = builder.build();
     TestUtil.assertAllExtensionsSet(message);
   }
@@ -434,6 +548,8 @@
     TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
     extensionsReflectionTester.setAllFieldsViaReflection(builder);
     extensionsReflectionTester.modifyRepeatedFieldsViaReflection(builder);
+    TestUtil.assertRepeatedExtensionsModified(builder);
+
     TestAllExtensions message = builder.build();
     TestUtil.assertRepeatedExtensionsModified(message);
   }
@@ -491,9 +607,11 @@
   // lite fields directly since they are implemented exactly the same as
   // regular fields.
 
-  public void testLiteExtensionAccessors() throws Exception {
+  public void testLiteExtensionMessageOrBuilder() throws Exception {
     TestAllExtensionsLite.Builder builder = TestAllExtensionsLite.newBuilder();
     TestUtil.setAllExtensions(builder);
+    TestUtil.assertAllExtensionsSet(builder);
+
     TestAllExtensionsLite message = builder.build();
     TestUtil.assertAllExtensionsSet(message);
   }
@@ -502,6 +620,8 @@
     TestAllExtensionsLite.Builder builder = TestAllExtensionsLite.newBuilder();
     TestUtil.setAllExtensions(builder);
     TestUtil.modifyRepeatedExtensions(builder);
+    TestUtil.assertRepeatedExtensionsModified(builder);
+
     TestAllExtensionsLite message = builder.build();
     TestUtil.assertRepeatedExtensionsModified(message);
   }
@@ -609,6 +729,7 @@
     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
     TestUtil.setAllFields(builder);
     TestAllTypes message = builder.build();
+    TestUtil.assertAllFieldsSet(message);
     TestUtil.assertAllFieldsSet(message.toBuilder().build());
   }
 
@@ -646,4 +767,207 @@
     assertTrue(message.getA() != null);
     assertTrue(message.getA() == message);
   }
+
+  public void testSerialize() throws Exception {
+    ByteArrayOutputStream baos = new ByteArrayOutputStream();
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TestUtil.setAllFields(builder);
+    TestAllTypes expected = builder.build();
+    ObjectOutputStream out = new ObjectOutputStream(baos);
+    out.writeObject(expected);
+    out.close();
+    ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+    ObjectInputStream in = new ObjectInputStream(bais);
+    TestAllTypes actual = (TestAllTypes) in.readObject();
+    assertEquals(expected, actual);
+  }
+
+  public void testSerializePartial() throws Exception {
+    ByteArrayOutputStream baos = new ByteArrayOutputStream();
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TestAllTypes expected = builder.buildPartial();
+    ObjectOutputStream out = new ObjectOutputStream(baos);
+    out.writeObject(expected);
+    out.close();
+    ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+    ObjectInputStream in = new ObjectInputStream(bais);
+    TestAllTypes actual = (TestAllTypes) in.readObject();
+    assertEquals(expected, actual);
+  }
+
+  public void testEnumValues() {
+     assertEquals(
+         TestAllTypes.NestedEnum.BAR.getNumber(),
+         TestAllTypes.NestedEnum.BAR_VALUE);
+    assertEquals(
+        TestAllTypes.NestedEnum.BAZ.getNumber(),
+        TestAllTypes.NestedEnum.BAZ_VALUE);
+    assertEquals(
+        TestAllTypes.NestedEnum.FOO.getNumber(),
+        TestAllTypes.NestedEnum.FOO_VALUE);
+  }
+
+  public void testNonNestedExtensionInitialization() {
+    assertTrue(NonNestedExtension.nonNestedExtension
+               .getMessageDefaultInstance() instanceof MyNonNestedExtension);
+    assertEquals("nonNestedExtension",
+                 NonNestedExtension.nonNestedExtension.getDescriptor().getName());
+  }
+
+  public void testNestedExtensionInitialization() {
+    assertTrue(MyNestedExtension.recursiveExtension.getMessageDefaultInstance()
+               instanceof MessageToBeExtended);
+    assertEquals("recursiveExtension",
+                 MyNestedExtension.recursiveExtension.getDescriptor().getName());
+  }
+
+  public void testNonNestedExtensionLiteInitialization() {
+    assertTrue(NonNestedExtensionLite.nonNestedExtensionLite
+               .getMessageDefaultInstance() instanceof MyNonNestedExtensionLite);
+  }
+
+  public void testNestedExtensionLiteInitialization() {
+    assertTrue(MyNestedExtensionLite.recursiveExtensionLite
+               .getMessageDefaultInstance() instanceof MessageLiteToBeExtended);
+  }
+
+  public void testInvalidations() throws Exception {
+    GeneratedMessage.enableAlwaysUseFieldBuildersForTesting();
+    TestAllTypes.NestedMessage nestedMessage1 =
+        TestAllTypes.NestedMessage.newBuilder().build();
+    TestAllTypes.NestedMessage nestedMessage2 =
+        TestAllTypes.NestedMessage.newBuilder().build();
+
+    // Set all three flavors (enum, primitive, message and singular/repeated)
+    // and verify no invalidations fired
+    TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+
+    TestAllTypes.Builder builder = (TestAllTypes.Builder)
+        ((GeneratedMessage) TestAllTypes.getDefaultInstance()).
+            newBuilderForType(mockParent);
+    builder.setOptionalInt32(1);
+    builder.setOptionalNestedEnum(TestAllTypes.NestedEnum.BAR);
+    builder.setOptionalNestedMessage(nestedMessage1);
+    builder.addRepeatedInt32(1);
+    builder.addRepeatedNestedEnum(TestAllTypes.NestedEnum.BAR);
+    builder.addRepeatedNestedMessage(nestedMessage1);
+    assertEquals(0, mockParent.getInvalidationCount());
+
+    // Now tell it we want changes and make sure it's only fired once
+    // And do this for each flavor
+
+    // primitive single
+    builder.buildPartial();
+    builder.setOptionalInt32(2);
+    builder.setOptionalInt32(3);
+    assertEquals(1, mockParent.getInvalidationCount());
+
+    // enum single
+    builder.buildPartial();
+    builder.setOptionalNestedEnum(TestAllTypes.NestedEnum.BAZ);
+    builder.setOptionalNestedEnum(TestAllTypes.NestedEnum.BAR);
+    assertEquals(2, mockParent.getInvalidationCount());
+
+    // message single
+    builder.buildPartial();
+    builder.setOptionalNestedMessage(nestedMessage2);
+    builder.setOptionalNestedMessage(nestedMessage1);
+    assertEquals(3, mockParent.getInvalidationCount());
+
+    // primitive repated
+    builder.buildPartial();
+    builder.addRepeatedInt32(2);
+    builder.addRepeatedInt32(3);
+    assertEquals(4, mockParent.getInvalidationCount());
+
+    // enum repeated
+    builder.buildPartial();
+    builder.addRepeatedNestedEnum(TestAllTypes.NestedEnum.BAZ);
+    builder.addRepeatedNestedEnum(TestAllTypes.NestedEnum.BAZ);
+    assertEquals(5, mockParent.getInvalidationCount());
+
+    // message repeated
+    builder.buildPartial();
+    builder.addRepeatedNestedMessage(nestedMessage2);
+    builder.addRepeatedNestedMessage(nestedMessage1);
+    assertEquals(6, mockParent.getInvalidationCount());
+
+  }
+
+  public void testInvalidations_Extensions() throws Exception {
+    TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+
+    TestAllExtensions.Builder builder = (TestAllExtensions.Builder)
+        ((GeneratedMessage) TestAllExtensions.getDefaultInstance()).
+            newBuilderForType(mockParent);
+
+    builder.addExtension(UnittestProto.repeatedInt32Extension, 1);
+    builder.setExtension(UnittestProto.repeatedInt32Extension, 0, 2);
+    builder.clearExtension(UnittestProto.repeatedInt32Extension);
+    assertEquals(0, mockParent.getInvalidationCount());
+
+    // Now tell it we want changes and make sure it's only fired once
+    builder.buildPartial();
+    builder.addExtension(UnittestProto.repeatedInt32Extension, 2);
+    builder.addExtension(UnittestProto.repeatedInt32Extension, 3);
+    assertEquals(1, mockParent.getInvalidationCount());
+
+    builder.buildPartial();
+    builder.setExtension(UnittestProto.repeatedInt32Extension, 0, 4);
+    builder.setExtension(UnittestProto.repeatedInt32Extension, 1, 5);
+    assertEquals(2, mockParent.getInvalidationCount());
+
+    builder.buildPartial();
+    builder.clearExtension(UnittestProto.repeatedInt32Extension);
+    builder.clearExtension(UnittestProto.repeatedInt32Extension);
+    assertEquals(3, mockParent.getInvalidationCount());
+  }
+
+  public void testBaseMessageOrBuilder() {
+    // Mostly just makes sure the base interface exists and has some methods.
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TestAllTypes message = builder.buildPartial();
+    TestAllTypesOrBuilder builderAsInterface = (TestAllTypesOrBuilder) builder;
+    TestAllTypesOrBuilder messageAsInterface = (TestAllTypesOrBuilder) message;
+
+    assertEquals(
+        messageAsInterface.getDefaultBool(),
+        messageAsInterface.getDefaultBool());
+    assertEquals(
+        messageAsInterface.getOptionalDouble(),
+        messageAsInterface.getOptionalDouble());
+  }
+
+  public void testMessageOrBuilderGetters() {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+
+    // single fields
+    assertSame(ForeignMessage.getDefaultInstance(),
+        builder.getOptionalForeignMessageOrBuilder());
+    ForeignMessage.Builder subBuilder =
+        builder.getOptionalForeignMessageBuilder();
+    assertSame(subBuilder, builder.getOptionalForeignMessageOrBuilder());
+
+    // repeated fields
+    ForeignMessage m0 = ForeignMessage.newBuilder().buildPartial();
+    ForeignMessage m1 = ForeignMessage.newBuilder().buildPartial();
+    ForeignMessage m2 = ForeignMessage.newBuilder().buildPartial();
+    builder.addRepeatedForeignMessage(m0);
+    builder.addRepeatedForeignMessage(m1);
+    builder.addRepeatedForeignMessage(m2);
+    assertSame(m0, builder.getRepeatedForeignMessageOrBuilder(0));
+    assertSame(m1, builder.getRepeatedForeignMessageOrBuilder(1));
+    assertSame(m2, builder.getRepeatedForeignMessageOrBuilder(2));
+    ForeignMessage.Builder b0 = builder.getRepeatedForeignMessageBuilder(0);
+    ForeignMessage.Builder b1 = builder.getRepeatedForeignMessageBuilder(1);
+    assertSame(b0, builder.getRepeatedForeignMessageOrBuilder(0));
+    assertSame(b1, builder.getRepeatedForeignMessageOrBuilder(1));
+    assertSame(m2, builder.getRepeatedForeignMessageOrBuilder(2));
+
+    List<? extends ForeignMessageOrBuilder> messageOrBuilderList =
+        builder.getRepeatedForeignMessageOrBuilderList();
+    assertSame(b0, messageOrBuilderList.get(0));
+    assertSame(b1, messageOrBuilderList.get(1));
+    assertSame(m2, messageOrBuilderList.get(2));
+  }
 }
diff --git a/java/src/test/java/com/google/protobuf/LazyStringArrayListTest.java b/java/src/test/java/com/google/protobuf/LazyStringArrayListTest.java
new file mode 100644
index 0000000..4dcdc74
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/LazyStringArrayListTest.java
@@ -0,0 +1,118 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for {@link LazyStringArrayList}.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class LazyStringArrayListTest extends TestCase {
+
+  private static String STRING_A = "A";
+  private static String STRING_B = "B";
+  private static String STRING_C = "C";
+
+  private static ByteString BYTE_STRING_A = ByteString.copyFromUtf8("A");
+  private static ByteString BYTE_STRING_B = ByteString.copyFromUtf8("B");
+  private static ByteString BYTE_STRING_C = ByteString.copyFromUtf8("C");
+
+  public void testJustStrings() {
+    LazyStringArrayList list = new LazyStringArrayList();
+    list.add(STRING_A);
+    list.add(STRING_B);
+    list.add(STRING_C);
+
+    assertEquals(3, list.size());
+    assertSame(STRING_A, list.get(0));
+    assertSame(STRING_B, list.get(1));
+    assertSame(STRING_C, list.get(2));
+
+    list.set(1, STRING_C);
+    assertSame(STRING_C, list.get(1));
+
+    list.remove(1);
+    assertSame(STRING_A, list.get(0));
+    assertSame(STRING_C, list.get(1));
+  }
+
+  public void testJustByteString() {
+    LazyStringArrayList list = new LazyStringArrayList();
+    list.add(BYTE_STRING_A);
+    list.add(BYTE_STRING_B);
+    list.add(BYTE_STRING_C);
+
+    assertEquals(3, list.size());
+    assertSame(BYTE_STRING_A, list.getByteString(0));
+    assertSame(BYTE_STRING_B, list.getByteString(1));
+    assertSame(BYTE_STRING_C, list.getByteString(2));
+
+    list.remove(1);
+    assertSame(BYTE_STRING_A, list.getByteString(0));
+    assertSame(BYTE_STRING_C, list.getByteString(1));
+  }
+
+  public void testConversionBackAndForth() {
+    LazyStringArrayList list = new LazyStringArrayList();
+    list.add(STRING_A);
+    list.add(BYTE_STRING_B);
+    list.add(BYTE_STRING_C);
+
+    // String a should be the same because it was originally a string
+    assertSame(STRING_A, list.get(0));
+
+    // String b and c should be different because the string has to be computed
+    // from the ByteString
+    String bPrime = list.get(1);
+    assertNotSame(STRING_B, bPrime);
+    assertEquals(STRING_B, bPrime);
+    String cPrime = list.get(2);
+    assertNotSame(STRING_C, cPrime);
+    assertEquals(STRING_C, cPrime);
+
+    // String c and c should stay the same once cached.
+    assertSame(bPrime, list.get(1));
+    assertSame(cPrime, list.get(2));
+
+    // ByteString needs to be computed from string for both a and b
+    ByteString aPrimeByteString = list.getByteString(0);
+    assertEquals(BYTE_STRING_A, aPrimeByteString);
+    ByteString bPrimeByteString = list.getByteString(1);
+    assertNotSame(BYTE_STRING_B, bPrimeByteString);
+    assertEquals(BYTE_STRING_B, list.getByteString(1));
+
+    // Once cached, ByteString should stay cached.
+    assertSame(aPrimeByteString, list.getByteString(0));
+    assertSame(bPrimeByteString, list.getByteString(1));
+  }
+}
diff --git a/java/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java b/java/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java
new file mode 100644
index 0000000..e6870b5
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java
@@ -0,0 +1,115 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+
+import protobuf_unittest.UnittestProto;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+
+/**
+ * Tests to make sure the lazy conversion of UTF8-encoded byte arrays to
+ * strings works correctly.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class LazyStringEndToEndTest extends TestCase {
+
+  private static ByteString TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8 =
+      ByteString.copyFrom(new byte[] {
+          114, 4, -1, 0, -1, 0, -30, 2, 4, -1,
+          0, -1, 0, -30, 2, 4, -1, 0, -1, 0, });
+
+  /**
+   * Tests that an invalid UTF8 string will roundtrip through a parse
+   * and serialization.
+   */
+  public void testParseAndSerialize() throws InvalidProtocolBufferException {
+    UnittestProto.TestAllTypes tV2 = UnittestProto.TestAllTypes.parseFrom(
+        TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8);
+    ByteString bytes = tV2.toByteString();
+    assertEquals(TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8, bytes);
+
+    tV2.getOptionalString();
+    bytes = tV2.toByteString();
+    assertEquals(TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8, bytes);
+  }
+
+  public void testParseAndWrite() throws IOException {
+    UnittestProto.TestAllTypes tV2 = UnittestProto.TestAllTypes.parseFrom(
+        TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8);
+    byte[] sink = new byte[TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8.size()];
+    CodedOutputStream outputStream = CodedOutputStream.newInstance(sink);
+    tV2.writeTo(outputStream);
+    outputStream.flush();
+    assertEquals(
+        TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8,
+        ByteString.copyFrom(sink));
+  }
+
+  public void testCaching() {
+    String a = "a";
+    String b = "b";
+    String c = "c";
+    UnittestProto.TestAllTypes proto = UnittestProto.TestAllTypes.newBuilder()
+        .setOptionalString(a)
+        .addRepeatedString(b)
+        .addRepeatedString(c)
+        .build();
+
+    // String should be the one we passed it.
+    assertSame(a, proto.getOptionalString());
+    assertSame(b, proto.getRepeatedString(0));
+    assertSame(c, proto.getRepeatedString(1));
+
+
+    // There's no way to directly observe that the ByteString is cached
+    // correctly on serialization, but we can observe that it had to recompute
+    // the string after serialization.
+    proto.toByteString();
+    String aPrime = proto.getOptionalString();
+    assertNotSame(a, aPrime);
+    assertEquals(a, aPrime);
+    String bPrime = proto.getRepeatedString(0);
+    assertNotSame(b, bPrime);
+    assertEquals(b, bPrime);
+    String cPrime = proto.getRepeatedString(1);
+    assertNotSame(c, cPrime);
+    assertEquals(c, cPrime);
+
+    // And now the string should stay cached.
+    assertSame(aPrime, proto.getOptionalString());
+    assertSame(bPrime, proto.getRepeatedString(0));
+    assertSame(cPrime, proto.getRepeatedString(1));
+  }
+}
diff --git a/java/src/test/java/com/google/protobuf/LiteTest.java b/java/src/test/java/com/google/protobuf/LiteTest.java
index 728bad9..4e1003d 100644
--- a/java/src/test/java/com/google/protobuf/LiteTest.java
+++ b/java/src/test/java/com/google/protobuf/LiteTest.java
@@ -37,6 +37,11 @@
 
 import junit.framework.TestCase;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
 /**
  * Test lite runtime.
  *
@@ -113,4 +118,28 @@
     assertEquals(7, message2.getExtension(
         UnittestLite.optionalNestedMessageExtensionLite).getBb());
   }
+
+  public void testSerialize() throws Exception {
+    ByteArrayOutputStream baos = new ByteArrayOutputStream();
+    TestAllTypesLite expected =
+      TestAllTypesLite.newBuilder()
+                      .setOptionalInt32(123)
+                      .addRepeatedString("hello")
+                      .setOptionalNestedMessage(
+                          TestAllTypesLite.NestedMessage.newBuilder().setBb(7))
+                      .build();
+    ObjectOutputStream out = new ObjectOutputStream(baos);
+    out.writeObject(expected);
+    out.close();
+    ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+    ObjectInputStream in = new ObjectInputStream(bais);
+    TestAllTypesLite actual = (TestAllTypesLite) in.readObject();
+    assertEquals(expected.getOptionalInt32(), actual.getOptionalInt32());
+    assertEquals(expected.getRepeatedStringCount(),
+        actual.getRepeatedStringCount());
+    assertEquals(expected.getRepeatedString(0),
+        actual.getRepeatedString(0));
+    assertEquals(expected.getOptionalNestedMessage().getBb(),
+        actual.getOptionalNestedMessage().getBb());
+  }
 }
diff --git a/java/src/test/java/com/google/protobuf/NestedBuildersTest.java b/java/src/test/java/com/google/protobuf/NestedBuildersTest.java
new file mode 100644
index 0000000..f537580
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/NestedBuildersTest.java
@@ -0,0 +1,185 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import protobuf_unittest.Vehicle;
+import protobuf_unittest.Wheel;
+
+import junit.framework.TestCase;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * Test cases that exercise end-to-end use cases involving
+ * {@link SingleFieldBuilder} and {@link RepeatedFieldBuilder}.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class NestedBuildersTest extends TestCase {
+
+  public void testMessagesAndBuilders() {
+    Vehicle.Builder vehicleBuilder = Vehicle.newBuilder();
+    vehicleBuilder.addWheelBuilder()
+        .setRadius(4)
+        .setWidth(1);
+    vehicleBuilder.addWheelBuilder()
+        .setRadius(4)
+        .setWidth(2);
+    vehicleBuilder.addWheelBuilder()
+        .setRadius(4)
+        .setWidth(3);
+    vehicleBuilder.addWheelBuilder()
+        .setRadius(4)
+        .setWidth(4);
+    vehicleBuilder.getEngineBuilder()
+        .setLiters(10);
+
+    Vehicle vehicle = vehicleBuilder.build();
+    assertEquals(4, vehicle.getWheelCount());
+    for (int i = 0; i < 4; i++) {
+      Wheel wheel = vehicle.getWheel(i);
+      assertEquals(4, wheel.getRadius());
+      assertEquals(i + 1, wheel.getWidth());
+    }
+    assertEquals(10, vehicle.getEngine().getLiters());
+
+    for (int i = 0; i < 4; i++) {
+      vehicleBuilder.getWheelBuilder(i)
+          .setRadius(5)
+          .setWidth(i + 10);
+    }
+    vehicleBuilder.getEngineBuilder().setLiters(20);
+
+    vehicle = vehicleBuilder.build();
+    for (int i = 0; i < 4; i++) {
+      Wheel wheel = vehicle.getWheel(i);
+      assertEquals(5, wheel.getRadius());
+      assertEquals(i + 10, wheel.getWidth());
+    }
+    assertEquals(20, vehicle.getEngine().getLiters());
+    assertTrue(vehicle.hasEngine());
+  }
+
+  public void testMessagesAreCached() {
+    Vehicle.Builder vehicleBuilder = Vehicle.newBuilder();
+    vehicleBuilder.addWheelBuilder()
+        .setRadius(1)
+        .setWidth(2);
+    vehicleBuilder.addWheelBuilder()
+        .setRadius(3)
+        .setWidth(4);
+    vehicleBuilder.addWheelBuilder()
+        .setRadius(5)
+        .setWidth(6);
+    vehicleBuilder.addWheelBuilder()
+        .setRadius(7)
+        .setWidth(8);
+
+    // Make sure messages are cached.
+    List<Wheel> wheels = new ArrayList<Wheel>(vehicleBuilder.getWheelList());
+    for (int i = 0; i < wheels.size(); i++) {
+      assertSame(wheels.get(i), vehicleBuilder.getWheel(i));
+    }
+
+    // Now get builders and check they didn't change.
+    for (int i = 0; i < wheels.size(); i++) {
+      vehicleBuilder.getWheel(i);
+    }
+    for (int i = 0; i < wheels.size(); i++) {
+      assertSame(wheels.get(i), vehicleBuilder.getWheel(i));
+    }
+
+    // Change just one
+    vehicleBuilder.getWheelBuilder(3)
+        .setRadius(20).setWidth(20);
+
+    // Now get wheels and check that only that one changed
+    for (int i = 0; i < wheels.size(); i++) {
+      if (i < 3) {
+        assertSame(wheels.get(i), vehicleBuilder.getWheel(i));
+      } else {
+        assertNotSame(wheels.get(i), vehicleBuilder.getWheel(i));
+      }
+    }
+  }
+
+  public void testRemove_WithNestedBuilders() {
+    Vehicle.Builder vehicleBuilder = Vehicle.newBuilder();
+    vehicleBuilder.addWheelBuilder()
+        .setRadius(1)
+        .setWidth(1);
+    vehicleBuilder.addWheelBuilder()
+        .setRadius(2)
+        .setWidth(2);
+    vehicleBuilder.removeWheel(0);
+
+    assertEquals(1, vehicleBuilder.getWheelCount());
+    assertEquals(2, vehicleBuilder.getWheel(0).getRadius());
+  }
+
+  public void testRemove_WithNestedMessages() {
+    Vehicle.Builder vehicleBuilder = Vehicle.newBuilder();
+    vehicleBuilder.addWheel(Wheel.newBuilder()
+        .setRadius(1)
+        .setWidth(1));
+    vehicleBuilder.addWheel(Wheel.newBuilder()
+        .setRadius(2)
+        .setWidth(2));
+    vehicleBuilder.removeWheel(0);
+
+    assertEquals(1, vehicleBuilder.getWheelCount());
+    assertEquals(2, vehicleBuilder.getWheel(0).getRadius());
+  }
+
+  public void testMerge() {
+    Vehicle vehicle1 = Vehicle.newBuilder()
+        .addWheel(Wheel.newBuilder().setRadius(1).build())
+        .addWheel(Wheel.newBuilder().setRadius(2).build())
+        .build();
+
+    Vehicle vehicle2 = Vehicle.newBuilder()
+        .mergeFrom(vehicle1)
+        .build();
+    // List should be the same -- no allocation
+    assertSame(vehicle1.getWheelList(), vehicle2.getWheelList());
+
+    Vehicle vehicle3 = vehicle1.toBuilder().build();
+    assertSame(vehicle1.getWheelList(), vehicle3.getWheelList());
+  }
+
+  public void testGettingBuilderMarksFieldAsHaving() {
+    Vehicle.Builder vehicleBuilder = Vehicle.newBuilder();
+    vehicleBuilder.getEngineBuilder();
+    Vehicle vehicle = vehicleBuilder.buildPartial();
+    assertTrue(vehicle.hasEngine());
+  }
+}
diff --git a/java/src/test/java/com/google/protobuf/RepeatedFieldBuilderTest.java b/java/src/test/java/com/google/protobuf/RepeatedFieldBuilderTest.java
new file mode 100644
index 0000000..cdcdcb2
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/RepeatedFieldBuilderTest.java
@@ -0,0 +1,190 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder;
+
+import junit.framework.TestCase;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Tests for {@link RepeatedFieldBuilder}. This tests basic functionality.
+ * More extensive testing is provided via other tests that exercise the
+ * builder.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class RepeatedFieldBuilderTest extends TestCase {
+
+  public void testBasicUse() {
+    TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+    RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+        TestAllTypesOrBuilder> builder = newRepeatedFieldBuilder(mockParent);
+    builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build());
+    builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build());
+    assertEquals(0, builder.getMessage(0).getOptionalInt32());
+    assertEquals(1, builder.getMessage(1).getOptionalInt32());
+
+    List<TestAllTypes> list = builder.build();
+    assertEquals(2, list.size());
+    assertEquals(0, list.get(0).getOptionalInt32());
+    assertEquals(1, list.get(1).getOptionalInt32());
+    assertIsUnmodifiable(list);
+
+    // Make sure it doesn't change.
+    List<TestAllTypes> list2 = builder.build();
+    assertSame(list, list2);
+    assertEquals(0, mockParent.getInvalidationCount());
+  }
+
+  public void testGoingBackAndForth() {
+    TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+    RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+        TestAllTypesOrBuilder> builder = newRepeatedFieldBuilder(mockParent);
+    builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build());
+    builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build());
+    assertEquals(0, builder.getMessage(0).getOptionalInt32());
+    assertEquals(1, builder.getMessage(1).getOptionalInt32());
+
+    // Convert to list
+    List<TestAllTypes> list = builder.build();
+    assertEquals(2, list.size());
+    assertEquals(0, list.get(0).getOptionalInt32());
+    assertEquals(1, list.get(1).getOptionalInt32());
+    assertIsUnmodifiable(list);
+
+    // Update 0th item
+    assertEquals(0, mockParent.getInvalidationCount());
+    builder.getBuilder(0).setOptionalString("foo");
+    assertEquals(1, mockParent.getInvalidationCount());
+    list = builder.build();
+    assertEquals(2, list.size());
+    assertEquals(0, list.get(0).getOptionalInt32());
+      assertEquals("foo", list.get(0).getOptionalString());
+    assertEquals(1, list.get(1).getOptionalInt32());
+    assertIsUnmodifiable(list);
+    assertEquals(1, mockParent.getInvalidationCount());
+  }
+
+  public void testVariousMethods() {
+    TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+    RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+        TestAllTypesOrBuilder> builder = newRepeatedFieldBuilder(mockParent);
+    builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build());
+    builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(2).build());
+    builder.addBuilder(0, TestAllTypes.getDefaultInstance())
+        .setOptionalInt32(0);
+    builder.addBuilder(TestAllTypes.getDefaultInstance()).setOptionalInt32(3);
+
+    assertEquals(0, builder.getMessage(0).getOptionalInt32());
+    assertEquals(1, builder.getMessage(1).getOptionalInt32());
+    assertEquals(2, builder.getMessage(2).getOptionalInt32());
+    assertEquals(3, builder.getMessage(3).getOptionalInt32());
+
+    assertEquals(0, mockParent.getInvalidationCount());
+    List<TestAllTypes> messages = builder.build();
+    assertEquals(4, messages.size());
+    assertSame(messages, builder.build()); // expect same list
+
+    // Remove a message.
+    builder.remove(2);
+    assertEquals(1, mockParent.getInvalidationCount());
+    assertEquals(3, builder.getCount());
+    assertEquals(0, builder.getMessage(0).getOptionalInt32());
+    assertEquals(1, builder.getMessage(1).getOptionalInt32());
+    assertEquals(3, builder.getMessage(2).getOptionalInt32());
+
+    // Remove a builder.
+    builder.remove(0);
+    assertEquals(1, mockParent.getInvalidationCount());
+    assertEquals(2, builder.getCount());
+    assertEquals(1, builder.getMessage(0).getOptionalInt32());
+    assertEquals(3, builder.getMessage(1).getOptionalInt32());
+
+    // Test clear.
+    builder.clear();
+    assertEquals(1, mockParent.getInvalidationCount());
+    assertEquals(0, builder.getCount());
+    assertTrue(builder.isEmpty());
+  }
+
+  public void testLists() {
+    TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+    RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+        TestAllTypesOrBuilder> builder = newRepeatedFieldBuilder(mockParent);
+    builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build());
+    builder.addMessage(0,
+        TestAllTypes.newBuilder().setOptionalInt32(0).build());
+    assertEquals(0, builder.getMessage(0).getOptionalInt32());
+    assertEquals(1, builder.getMessage(1).getOptionalInt32());
+
+    // Use list of builders.
+    List<TestAllTypes.Builder> builders = builder.getBuilderList();
+    assertEquals(0, builders.get(0).getOptionalInt32());
+    assertEquals(1, builders.get(1).getOptionalInt32());
+    builders.get(0).setOptionalInt32(10);
+    builders.get(1).setOptionalInt32(11);
+
+    // Use list of protos
+    List<TestAllTypes> protos = builder.getMessageList();
+    assertEquals(10, protos.get(0).getOptionalInt32());
+    assertEquals(11, protos.get(1).getOptionalInt32());
+
+    // Add an item to the builders and verify it's updated in both
+    builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(12).build());
+    assertEquals(3, builders.size());
+    assertEquals(3, protos.size());
+  }
+
+  private void assertIsUnmodifiable(List<?> list) {
+    if (list == Collections.emptyList()) {
+      // OKAY -- Need to check this b/c EmptyList allows you to call clear.
+    } else {
+      try {
+        list.clear();
+        fail("List wasn't immutable");
+      } catch (UnsupportedOperationException e) {
+        // good
+      }
+    }
+  }
+
+  private RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+      TestAllTypesOrBuilder>
+      newRepeatedFieldBuilder(GeneratedMessage.BuilderParent parent) {
+    return new RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+        TestAllTypesOrBuilder>(Collections.<TestAllTypes>emptyList(), false,
+        parent, false);
+  }
+}
diff --git a/java/src/test/java/com/google/protobuf/ServiceTest.java b/java/src/test/java/com/google/protobuf/ServiceTest.java
index 802eb0e..4be84f5 100644
--- a/java/src/test/java/com/google/protobuf/ServiceTest.java
+++ b/java/src/test/java/com/google/protobuf/ServiceTest.java
@@ -244,6 +244,14 @@
       //   make assumptions, so I'm just going to accept any character as the
       //   separator.
       assertTrue(fullName.startsWith(outerName));
+
+      if (!Service.class.isAssignableFrom(innerClass) &&
+          !Message.class.isAssignableFrom(innerClass) &&
+          !ProtocolMessageEnum.class.isAssignableFrom(innerClass)) {
+        // Ignore any classes not generated by the base code generator.
+        continue;
+      }
+
       innerClassNames.add(fullName.substring(outerName.length() + 1));
     }
 
diff --git a/java/src/test/java/com/google/protobuf/SingleFieldBuilderTest.java b/java/src/test/java/com/google/protobuf/SingleFieldBuilderTest.java
new file mode 100644
index 0000000..5c2f7e7
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/SingleFieldBuilderTest.java
@@ -0,0 +1,155 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for {@link SingleFieldBuilder}. This tests basic functionality.
+ * More extensive testing is provided via other tests that exercise the
+ * builder.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class SingleFieldBuilderTest extends TestCase {
+
+  public void testBasicUseAndInvalidations() {
+    TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+    SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+        TestAllTypesOrBuilder> builder =
+        new SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+            TestAllTypesOrBuilder>(
+            TestAllTypes.getDefaultInstance(),
+            mockParent,
+            false);
+    assertSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
+    assertEquals(TestAllTypes.getDefaultInstance(),
+        builder.getBuilder().buildPartial());
+    assertEquals(0, mockParent.getInvalidationCount());
+
+    builder.getBuilder().setOptionalInt32(10);
+    assertEquals(0, mockParent.getInvalidationCount());
+    TestAllTypes message = builder.build();
+    assertEquals(10, message.getOptionalInt32());
+
+    // Test that we receive invalidations now that build has been called.
+    assertEquals(0, mockParent.getInvalidationCount());
+    builder.getBuilder().setOptionalInt32(20);
+    assertEquals(1, mockParent.getInvalidationCount());
+
+    // Test that we don't keep getting invalidations on every change
+    builder.getBuilder().setOptionalInt32(30);
+    assertEquals(1, mockParent.getInvalidationCount());
+
+  }
+
+  public void testSetMessage() {
+    TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+    SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+        TestAllTypesOrBuilder> builder =
+        new SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+            TestAllTypesOrBuilder>(
+            TestAllTypes.getDefaultInstance(),
+            mockParent,
+            false);
+    builder.setMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build());
+    assertEquals(0, builder.getMessage().getOptionalInt32());
+
+    // Update message using the builder
+    builder.getBuilder().setOptionalInt32(1);
+    assertEquals(0, mockParent.getInvalidationCount());
+    assertEquals(1, builder.getBuilder().getOptionalInt32());
+    assertEquals(1, builder.getMessage().getOptionalInt32());
+    builder.build();
+    builder.getBuilder().setOptionalInt32(2);
+    assertEquals(2, builder.getBuilder().getOptionalInt32());
+    assertEquals(2, builder.getMessage().getOptionalInt32());
+
+    // Make sure message stays cached
+    assertSame(builder.getMessage(), builder.getMessage());
+  }
+
+  public void testClear() {
+    TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+    SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+        TestAllTypesOrBuilder> builder =
+        new SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+            TestAllTypesOrBuilder>(
+            TestAllTypes.getDefaultInstance(),
+            mockParent,
+            false);
+    builder.setMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build());
+    assertNotSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
+    builder.clear();
+    assertSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
+
+    builder.getBuilder().setOptionalInt32(1);
+    assertNotSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
+    builder.clear();
+    assertSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
+  }
+
+  public void testMerge() {
+    TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+    SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+        TestAllTypesOrBuilder> builder =
+        new SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+            TestAllTypesOrBuilder>(
+            TestAllTypes.getDefaultInstance(),
+            mockParent,
+            false);
+
+    // Merge into default field.
+    builder.mergeFrom(TestAllTypes.getDefaultInstance());
+    assertSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
+
+    // Merge into non-default field on existing builder.
+    builder.getBuilder().setOptionalInt32(2);
+    builder.mergeFrom(TestAllTypes.newBuilder()
+        .setOptionalDouble(4.0)
+        .buildPartial());
+    assertEquals(2, builder.getMessage().getOptionalInt32());
+    assertEquals(4.0, builder.getMessage().getOptionalDouble());
+
+    // Merge into non-default field on existing message
+    builder.setMessage(TestAllTypes.newBuilder()
+        .setOptionalInt32(10)
+        .buildPartial());
+    builder.mergeFrom(TestAllTypes.newBuilder()
+        .setOptionalDouble(5.0)
+        .buildPartial());
+    assertEquals(10, builder.getMessage().getOptionalInt32());
+    assertEquals(5.0, builder.getMessage().getOptionalDouble());
+  }
+}
diff --git a/java/src/test/java/com/google/protobuf/SmallSortedMapTest.java b/java/src/test/java/com/google/protobuf/SmallSortedMapTest.java
new file mode 100644
index 0000000..922115f
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/SmallSortedMapTest.java
@@ -0,0 +1,378 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import junit.framework.TestCase;
+
+import java.util.AbstractMap.SimpleEntry;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ * @author darick@google.com Darick Tong
+ */
+public class SmallSortedMapTest extends TestCase {
+
+  public void testPutAndGetArrayEntriesOnly() {
+    runPutAndGetTest(3);
+  }
+
+  public void testPutAndGetOverflowEntries() {
+    runPutAndGetTest(6);
+  }
+
+  private void runPutAndGetTest(int numElements) {
+    // Test with even and odd arraySize
+    SmallSortedMap<Integer, Integer> map1 =
+        SmallSortedMap.newInstanceForTest(3);
+    SmallSortedMap<Integer, Integer> map2 =
+        SmallSortedMap.newInstanceForTest(4);
+    SmallSortedMap<Integer, Integer> map3 =
+        SmallSortedMap.newInstanceForTest(3);
+    SmallSortedMap<Integer, Integer> map4 =
+        SmallSortedMap.newInstanceForTest(4);
+
+    // Test with puts in ascending order.
+    for (int i = 0; i < numElements; i++) {
+      assertNull(map1.put(i, i + 1));
+      assertNull(map2.put(i, i + 1));
+    }
+    // Test with puts in descending order.
+    for (int i = numElements - 1; i >= 0; i--) {
+      assertNull(map3.put(i, i + 1));
+      assertNull(map4.put(i, i + 1));
+    }
+
+    assertEquals(Math.min(3, numElements), map1.getNumArrayEntries());
+    assertEquals(Math.min(4, numElements), map2.getNumArrayEntries());
+    assertEquals(Math.min(3, numElements), map3.getNumArrayEntries());
+    assertEquals(Math.min(4, numElements), map4.getNumArrayEntries());
+
+    List<SmallSortedMap<Integer, Integer>> allMaps =
+        new ArrayList<SmallSortedMap<Integer, Integer>>();
+    allMaps.add(map1);
+    allMaps.add(map2);
+    allMaps.add(map3);
+    allMaps.add(map4);
+
+    for (SmallSortedMap<Integer, Integer> map : allMaps) {
+      assertEquals(numElements, map.size());
+      for (int i = 0; i < numElements; i++) {
+        assertEquals(new Integer(i + 1), map.get(i));
+      }
+    }
+
+    assertEquals(map1, map2);
+    assertEquals(map2, map3);
+    assertEquals(map3, map4);
+  }
+
+  public void testReplacingPut() {
+    SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+    for (int i = 0; i < 6; i++) {
+      assertNull(map.put(i, i + 1));
+      assertNull(map.remove(i + 1));
+    }
+    for (int i = 0; i < 6; i++) {
+      assertEquals(new Integer(i + 1), map.put(i, i + 2));
+    }
+  }
+
+  public void testRemove() {
+    SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+    for (int i = 0; i < 6; i++) {
+      assertNull(map.put(i, i + 1));
+      assertNull(map.remove(i + 1));
+    }
+
+    assertEquals(3, map.getNumArrayEntries());
+    assertEquals(3, map.getNumOverflowEntries());
+    assertEquals(6,  map.size());
+    assertEquals(makeSortedKeySet(0, 1, 2, 3, 4, 5), map.keySet());
+
+    assertEquals(new Integer(2), map.remove(1));
+    assertEquals(3, map.getNumArrayEntries());
+    assertEquals(2, map.getNumOverflowEntries());
+    assertEquals(5,  map.size());
+    assertEquals(makeSortedKeySet(0, 2, 3, 4, 5), map.keySet());
+
+    assertEquals(new Integer(5), map.remove(4));
+    assertEquals(3, map.getNumArrayEntries());
+    assertEquals(1, map.getNumOverflowEntries());
+    assertEquals(4,  map.size());
+    assertEquals(makeSortedKeySet(0, 2, 3, 5), map.keySet());
+
+    assertEquals(new Integer(4), map.remove(3));
+    assertEquals(3, map.getNumArrayEntries());
+    assertEquals(0, map.getNumOverflowEntries());
+    assertEquals(3, map.size());
+    assertEquals(makeSortedKeySet(0, 2, 5), map.keySet());
+
+    assertNull(map.remove(3));
+    assertEquals(3, map.getNumArrayEntries());
+    assertEquals(0, map.getNumOverflowEntries());
+    assertEquals(3, map.size());
+
+    assertEquals(new Integer(1), map.remove(0));
+    assertEquals(2, map.getNumArrayEntries());
+    assertEquals(0, map.getNumOverflowEntries());
+    assertEquals(2, map.size());
+  }
+
+  public void testClear() {
+    SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+    for (int i = 0; i < 6; i++) {
+      assertNull(map.put(i, i + 1));
+    }
+    map.clear();
+    assertEquals(0, map.getNumArrayEntries());
+    assertEquals(0, map.getNumOverflowEntries());
+    assertEquals(0, map.size());
+  }
+
+  public void testGetArrayEntryAndOverflowEntries() {
+    SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+    for (int i = 0; i < 6; i++) {
+      assertNull(map.put(i, i + 1));
+    }
+    assertEquals(3, map.getNumArrayEntries());
+    for (int i = 0; i < 3; i++) {
+      Map.Entry<Integer, Integer> entry = map.getArrayEntryAt(i);
+      assertEquals(new Integer(i), entry.getKey());
+      assertEquals(new Integer(i + 1), entry.getValue());
+    }
+    Iterator<Map.Entry<Integer, Integer>> it =
+        map.getOverflowEntries().iterator();
+    for (int i = 3; i < 6; i++) {
+      assertTrue(it.hasNext());
+      Map.Entry<Integer, Integer> entry = it.next();
+      assertEquals(new Integer(i), entry.getKey());
+      assertEquals(new Integer(i + 1), entry.getValue());
+    }
+    assertFalse(it.hasNext());
+  }
+
+  public void testEntrySetContains() {
+    SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+    for (int i = 0; i < 6; i++) {
+      assertNull(map.put(i, i + 1));
+    }
+    Set<Map.Entry<Integer, Integer>> entrySet = map.entrySet();
+    for (int i = 0; i < 6; i++) {
+      assertTrue(
+          entrySet.contains(new SimpleEntry<Integer, Integer>(i, i + 1)));
+      assertFalse(
+          entrySet.contains(new SimpleEntry<Integer, Integer>(i, i)));
+    }
+  }
+
+  public void testEntrySetAdd() {
+    SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+    Set<Map.Entry<Integer, Integer>> entrySet = map.entrySet();
+    for (int i = 0; i < 6; i++) {
+      Map.Entry<Integer, Integer> entry =
+          new SimpleEntry<Integer, Integer>(i, i + 1);
+      assertTrue(entrySet.add(entry));
+      assertFalse(entrySet.add(entry));
+    }
+    for (int i = 0; i < 6; i++) {
+      assertEquals(new Integer(i + 1), map.get(i));
+    }
+    assertEquals(3, map.getNumArrayEntries());
+    assertEquals(3, map.getNumOverflowEntries());
+    assertEquals(6, map.size());
+  }
+
+  public void testEntrySetRemove() {
+    SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+    Set<Map.Entry<Integer, Integer>> entrySet = map.entrySet();
+    for (int i = 0; i < 6; i++) {
+      assertNull(map.put(i, i + 1));
+    }
+    for (int i = 0; i < 6; i++) {
+      Map.Entry<Integer, Integer> entry =
+          new SimpleEntry<Integer, Integer>(i, i + 1);
+      assertTrue(entrySet.remove(entry));
+      assertFalse(entrySet.remove(entry));
+    }
+    assertTrue(map.isEmpty());
+    assertEquals(0, map.getNumArrayEntries());
+    assertEquals(0, map.getNumOverflowEntries());
+    assertEquals(0, map.size());
+  }
+
+  public void testEntrySetClear() {
+    SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+    for (int i = 0; i < 6; i++) {
+      assertNull(map.put(i, i + 1));
+    }
+    map.entrySet().clear();
+    assertTrue(map.isEmpty());
+    assertEquals(0, map.getNumArrayEntries());
+    assertEquals(0, map.getNumOverflowEntries());
+    assertEquals(0, map.size());
+  }
+
+  public void testEntrySetIteratorNext() {
+    SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+    for (int i = 0; i < 6; i++) {
+      assertNull(map.put(i, i + 1));
+    }
+    Iterator<Map.Entry<Integer, Integer>> it = map.entrySet().iterator();
+    for (int i = 0; i < 6; i++) {
+      assertTrue(it.hasNext());
+      Map.Entry<Integer, Integer> entry = it.next();
+      assertEquals(new Integer(i), entry.getKey());
+      assertEquals(new Integer(i + 1), entry.getValue());
+    }
+    assertFalse(it.hasNext());
+  }
+
+  public void testEntrySetIteratorRemove() {
+    SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+    for (int i = 0; i < 6; i++) {
+      assertNull(map.put(i, i + 1));
+    }
+    Iterator<Map.Entry<Integer, Integer>> it = map.entrySet().iterator();
+    for (int i = 0; i < 6; i++) {
+      assertTrue(map.containsKey(i));
+      it.next();
+      it.remove();
+      assertFalse(map.containsKey(i));
+      assertEquals(6 - i - 1, map.size());
+    }
+  }
+
+  public void testMapEntryModification() {
+    SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+    for (int i = 0; i < 6; i++) {
+      assertNull(map.put(i, i + 1));
+    }
+    Iterator<Map.Entry<Integer, Integer>> it = map.entrySet().iterator();
+    for (int i = 0; i < 6; i++) {
+      Map.Entry<Integer, Integer> entry = it.next();
+      entry.setValue(i + 23);
+    }
+    for (int i = 0; i < 6; i++) {
+      assertEquals(new Integer(i + 23), map.get(i));
+    }
+  }
+
+  public void testMakeImmutable() {
+    SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+    for (int i = 0; i < 6; i++) {
+      assertNull(map.put(i, i + 1));
+    }
+    map.makeImmutable();
+    assertEquals(new Integer(1), map.get(0));
+    assertEquals(6, map.size());
+
+    try {
+      map.put(23, 23);
+      fail("Expected UnsupportedOperationException");
+    } catch (UnsupportedOperationException expected) {
+    }
+
+    Map<Integer, Integer> other = new HashMap<Integer, Integer>();
+    other.put(23, 23);
+    try {
+      map.putAll(other);
+      fail("Expected UnsupportedOperationException");
+    } catch (UnsupportedOperationException expected) {
+    }
+
+    try {
+      map.remove(0);
+      fail("Expected UnsupportedOperationException");
+    } catch (UnsupportedOperationException expected) {
+    }
+
+    try {
+      map.clear();
+      fail("Expected UnsupportedOperationException");
+    } catch (UnsupportedOperationException expected) {
+    }
+
+    Set<Map.Entry<Integer, Integer>> entrySet = map.entrySet();
+    try {
+      entrySet.clear();
+      fail("Expected UnsupportedOperationException");
+    } catch (UnsupportedOperationException expected) {
+    }
+
+    Iterator<Map.Entry<Integer, Integer>> it = entrySet.iterator();
+    while (it.hasNext()) {
+      Map.Entry<Integer, Integer> entry = it.next();
+      try {
+        entry.setValue(0);
+        fail("Expected UnsupportedOperationException");
+      } catch (UnsupportedOperationException expected) {
+      }
+      try {
+        it.remove();
+        fail("Expected UnsupportedOperationException");
+      } catch (UnsupportedOperationException expected) {
+      }
+    }
+
+    Set<Integer> keySet = map.keySet();
+    try {
+      keySet.clear();
+      fail("Expected UnsupportedOperationException");
+    } catch (UnsupportedOperationException expected) {
+    }
+
+    Iterator<Integer> keys = keySet.iterator();
+    while (keys.hasNext()) {
+      Integer key = keys.next();
+      try {
+        keySet.remove(key);
+        fail("Expected UnsupportedOperationException");
+      } catch (UnsupportedOperationException expected) {
+      }
+      try {
+        keys.remove();
+        fail("Expected UnsupportedOperationException");
+      } catch (UnsupportedOperationException expected) {
+      }
+    }
+  }
+
+  private Set<Integer> makeSortedKeySet(Integer... keys) {
+    return new TreeSet<Integer>(Arrays.<Integer>asList(keys));
+  }
+}
diff --git a/java/src/test/java/com/google/protobuf/TestBadIdentifiers.java b/java/src/test/java/com/google/protobuf/TestBadIdentifiers.java
new file mode 100644
index 0000000..6feec4e
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/TestBadIdentifiers.java
@@ -0,0 +1,49 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests that proto2 api generation doesn't cause compile errors when
+ * compiling protocol buffers that have names that would otherwise conflict
+ * if not fully qualified (like @Deprecated and @Override). 
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class TestBadIdentifiers extends TestCase {
+
+  public void testCompilation() {
+    // If this compiles, it means the generation was correct.
+    TestBadIdentifiersProto.Deprecated.newBuilder();
+    TestBadIdentifiersProto.Override.newBuilder();
+  } 
+}
diff --git a/java/src/test/java/com/google/protobuf/TestUtil.java b/java/src/test/java/com/google/protobuf/TestUtil.java
index 2b8b2af..7c458d7 100644
--- a/java/src/test/java/com/google/protobuf/TestUtil.java
+++ b/java/src/test/java/com/google/protobuf/TestUtil.java
@@ -214,7 +214,9 @@
 import static com.google.protobuf.UnittestLite.packedEnumExtensionLite;
 
 import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllExtensionsOrBuilder;
 import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder;
 import protobuf_unittest.UnittestProto.TestPackedExtensions;
 import protobuf_unittest.UnittestProto.TestPackedTypes;
 import protobuf_unittest.UnittestProto.TestUnpackedTypes;
@@ -225,6 +227,7 @@
 
 import com.google.protobuf.UnittestLite.TestAllTypesLite;
 import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
+import com.google.protobuf.UnittestLite.TestAllExtensionsLiteOrBuilder;
 import com.google.protobuf.UnittestLite.TestPackedExtensionsLite;
 import com.google.protobuf.UnittestLite.ForeignMessageLite;
 import com.google.protobuf.UnittestLite.ForeignEnumLite;
@@ -244,9 +247,12 @@
  * set all fields of a message, serialize it, parse it, and check that all
  * fields are set.
  *
+ * <p>This code is not to be used outside of {@code com.google.protobuf} and
+ * subpackages.
+ *
  * @author kenton@google.com Kenton Varda
  */
-class TestUtil {
+public final class TestUtil {
   private TestUtil() {}
 
   /** Helper to convert a String to ByteString. */
@@ -485,7 +491,7 @@
    * Assert (using {@code junit.framework.Assert}} that all fields of
    * {@code message} are set to the values assigned by {@code setAllFields}.
    */
-  public static void assertAllFieldsSet(TestAllTypes message) {
+  public static void assertAllFieldsSet(TestAllTypesOrBuilder message) {
     Assert.assertTrue(message.hasOptionalInt32   ());
     Assert.assertTrue(message.hasOptionalInt64   ());
     Assert.assertTrue(message.hasOptionalUint32  ());
@@ -682,13 +688,12 @@
   }
 
   // -------------------------------------------------------------------
-
   /**
    * Assert (using {@code junit.framework.Assert}} that all fields of
    * {@code message} are cleared, and that getting the fields returns their
    * default values.
    */
-  public static void assertClear(TestAllTypes message) {
+  public static void assertClear(TestAllTypesOrBuilder message) {
     // hasBlah() should initially be false for all optional fields.
     Assert.assertFalse(message.hasOptionalInt32   ());
     Assert.assertFalse(message.hasOptionalInt64   ());
@@ -838,7 +843,8 @@
    * {@code message} are set to the values assigned by {@code setAllFields}
    * followed by {@code modifyRepeatedFields}.
    */
-  public static void assertRepeatedFieldsModified(TestAllTypes message) {
+  public static void assertRepeatedFieldsModified(
+      TestAllTypesOrBuilder message) {
     // ModifyRepeatedFields only sets the second repeated element of each
     // field.  In addition to verifying this, we also verify that the first
     // element and size were *not* modified.
@@ -1352,7 +1358,8 @@
    * Assert (using {@code junit.framework.Assert}} that all extensions of
    * {@code message} are set to the values assigned by {@code setAllExtensions}.
    */
-  public static void assertAllExtensionsSet(TestAllExtensions message) {
+  public static void assertAllExtensionsSet(
+      TestAllExtensionsOrBuilder message) {
     Assert.assertTrue(message.hasExtension(optionalInt32Extension   ));
     Assert.assertTrue(message.hasExtension(optionalInt64Extension   ));
     Assert.assertTrue(message.hasExtension(optionalUint32Extension  ));
@@ -1567,7 +1574,7 @@
    * {@code message} are cleared, and that getting the extensions returns their
    * default values.
    */
-  public static void assertExtensionsClear(TestAllExtensions message) {
+  public static void assertExtensionsClear(TestAllExtensionsOrBuilder message) {
     // hasBlah() should initially be false for all optional fields.
     Assert.assertFalse(message.hasExtension(optionalInt32Extension   ));
     Assert.assertFalse(message.hasExtension(optionalInt64Extension   ));
@@ -1752,7 +1759,7 @@
    * followed by {@code modifyRepeatedExtensions}.
    */
   public static void assertRepeatedExtensionsModified(
-      TestAllExtensions message) {
+      TestAllExtensionsOrBuilder message) {
     // ModifyRepeatedFields only sets the second repeated element of each
     // field.  In addition to verifying this, we also verify that the first
     // element and size were *not* modified.
@@ -2106,7 +2113,8 @@
    * Assert (using {@code junit.framework.Assert}} that all extensions of
    * {@code message} are set to the values assigned by {@code setAllExtensions}.
    */
-  public static void assertAllExtensionsSet(TestAllExtensionsLite message) {
+  public static void assertAllExtensionsSet(
+      TestAllExtensionsLiteOrBuilder message) {
     Assert.assertTrue(message.hasExtension(optionalInt32ExtensionLite   ));
     Assert.assertTrue(message.hasExtension(optionalInt64ExtensionLite   ));
     Assert.assertTrue(message.hasExtension(optionalUint32ExtensionLite  ));
@@ -2321,7 +2329,8 @@
    * {@code message} are cleared, and that getting the extensions returns their
    * default values.
    */
-  public static void assertExtensionsClear(TestAllExtensionsLite message) {
+  public static void assertExtensionsClear(
+      TestAllExtensionsLiteOrBuilder message) {
     // hasBlah() should initially be false for all optional fields.
     Assert.assertFalse(message.hasExtension(optionalInt32ExtensionLite   ));
     Assert.assertFalse(message.hasExtension(optionalInt64ExtensionLite   ));
@@ -2478,7 +2487,7 @@
    * followed by {@code modifyRepeatedExtensions}.
    */
   public static void assertRepeatedExtensionsModified(
-      TestAllExtensionsLite message) {
+      TestAllExtensionsLiteOrBuilder message) {
     // ModifyRepeatedFields only sets the second repeated element of each
     // field.  In addition to verifying this, we also verify that the first
     // element and size were *not* modified.
@@ -3015,7 +3024,7 @@
      * {@code message} are set to the values assigned by {@code setAllFields},
      * using the {@link Message} reflection interface.
      */
-    public void assertAllFieldsSetViaReflection(Message message) {
+    public void assertAllFieldsSetViaReflection(MessageOrBuilder message) {
       Assert.assertTrue(message.hasField(f("optional_int32"   )));
       Assert.assertTrue(message.hasField(f("optional_int64"   )));
       Assert.assertTrue(message.hasField(f("optional_uint32"  )));
@@ -3248,7 +3257,7 @@
      * {@code message} are cleared, and that getting the fields returns their
      * default values, using the {@link Message} reflection interface.
      */
-    public void assertClearViaReflection(Message message) {
+    public void assertClearViaReflection(MessageOrBuilder message) {
       // has_blah() should initially be false for all optional fields.
       Assert.assertFalse(message.hasField(f("optional_int32"   )));
       Assert.assertFalse(message.hasField(f("optional_int64"   )));
@@ -3405,9 +3414,11 @@
       Assert.assertEquals("123", message.getField(f("default_cord")));
     }
 
+
     // ---------------------------------------------------------------
 
-    public void assertRepeatedFieldsModifiedViaReflection(Message message) {
+    public void assertRepeatedFieldsModifiedViaReflection(
+        MessageOrBuilder message) {
       // ModifyRepeatedFields only sets the second repeated element of each
       // field.  In addition to verifying this, we also verify that the first
       // element and size were *not* modified.
@@ -3543,7 +3554,7 @@
       message.addRepeatedField(f("packed_enum" ),  foreignBaz);
     }
 
-    public void assertPackedFieldsSetViaReflection(Message message) {
+    public void assertPackedFieldsSetViaReflection(MessageOrBuilder message) {
       Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_int32"   )));
       Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_int64"   )));
       Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_uint32"  )));
@@ -3699,7 +3710,7 @@
 
   /**
    * @param filePath The path relative to
-   * {@link com.google.testing.util.TestUtil#getDefaultSrcDir}.
+   * {@link #getTestDataDir}.
    */
   public static String readTextFromFile(String filePath) {
     return readBytesFromFile(filePath).toStringUtf8();
@@ -3728,8 +3739,8 @@
   }
 
   /**
-   * @param filePath The path relative to
-   * {@link com.google.testing.util.TestUtil#getDefaultSrcDir}.
+   * @param filename The path relative to
+   * {@link #getTestDataDir}.
    */
   public static ByteString readBytesFromFile(String filename) {
     File fullPath = new File(getTestDataDir(), filename);
@@ -3749,7 +3760,7 @@
   /**
    * Get the bytes of the "golden message".  This is a serialized TestAllTypes
    * with all fields set as they would be by
-   * {@link setAllFields(TestAllTypes.Builder)}, but it is loaded from a file
+   * {@link #setAllFields(TestAllTypes.Builder)}, but it is loaded from a file
    * on disk rather than generated dynamically.  The file is actually generated
    * by C++ code, so testing against it verifies compatibility with C++.
    */
@@ -3764,7 +3775,7 @@
   /**
    * Get the bytes of the "golden packed fields message".  This is a serialized
    * TestPackedTypes with all fields set as they would be by
-   * {@link setPackedFields(TestPackedTypes.Builder)}, but it is loaded from a
+   * {@link #setPackedFields(TestPackedTypes.Builder)}, but it is loaded from a
    * file on disk rather than generated dynamically.  The file is actually
    * generated by C++ code, so testing against it verifies compatibility with
    * C++.
@@ -3777,4 +3788,24 @@
     return goldenPackedFieldsMessage;
   }
   private static ByteString goldenPackedFieldsMessage = null;
+
+  /**
+   * Mock implementation of {@link GeneratedMessage.BuilderParent} for testing.
+   *
+   * @author jonp@google.com (Jon Perlow)
+   */
+  public static class MockBuilderParent
+      implements GeneratedMessage.BuilderParent {
+
+    private int invalidations;
+
+    @Override
+    public void markDirty() {
+      invalidations++;
+    }
+
+    public int getInvalidationCount() {
+      return invalidations;
+    }
+  }
 }
diff --git a/java/src/test/java/com/google/protobuf/TextFormatTest.java b/java/src/test/java/com/google/protobuf/TextFormatTest.java
index ad48157..47690d1 100644
--- a/java/src/test/java/com/google/protobuf/TextFormatTest.java
+++ b/java/src/test/java/com/google/protobuf/TextFormatTest.java
@@ -31,14 +31,14 @@
 package com.google.protobuf;
 
 import com.google.protobuf.Descriptors.FieldDescriptor;
-import protobuf_unittest.UnittestProto.OneString;
-import protobuf_unittest.UnittestProto.TestAllTypes;
-import protobuf_unittest.UnittestProto.TestAllExtensions;
-import protobuf_unittest.UnittestProto.TestEmptyMessage;
-import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage;
 import protobuf_unittest.UnittestMset.TestMessageSet;
 import protobuf_unittest.UnittestMset.TestMessageSetExtension1;
 import protobuf_unittest.UnittestMset.TestMessageSetExtension2;
+import protobuf_unittest.UnittestProto.OneString;
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage;
+import protobuf_unittest.UnittestProto.TestEmptyMessage;
 
 import junit.framework.TestCase;
 
@@ -133,40 +133,44 @@
     assertEquals(allExtensionsSetText, javaText);
   }
 
+  // Creates an example unknown field set.
+  private UnknownFieldSet makeUnknownFieldSet() {
+    return UnknownFieldSet.newBuilder()
+        .addField(5,
+            UnknownFieldSet.Field.newBuilder()
+            .addVarint(1)
+            .addFixed32(2)
+            .addFixed64(3)
+            .addLengthDelimited(ByteString.copyFromUtf8("4"))
+            .addGroup(
+                UnknownFieldSet.newBuilder()
+                .addField(10,
+                    UnknownFieldSet.Field.newBuilder()
+                    .addVarint(5)
+                    .build())
+                .build())
+            .build())
+        .addField(8,
+            UnknownFieldSet.Field.newBuilder()
+            .addVarint(1)
+            .addVarint(2)
+            .addVarint(3)
+            .build())
+        .addField(15,
+            UnknownFieldSet.Field.newBuilder()
+            .addVarint(0xABCDEF1234567890L)
+            .addFixed32(0xABCD1234)
+            .addFixed64(0xABCDEF1234567890L)
+            .build())
+        .build();
+  }
+
   public void testPrintUnknownFields() throws Exception {
     // Test printing of unknown fields in a message.
 
     TestEmptyMessage message =
       TestEmptyMessage.newBuilder()
-        .setUnknownFields(
-          UnknownFieldSet.newBuilder()
-            .addField(5,
-              UnknownFieldSet.Field.newBuilder()
-                .addVarint(1)
-                .addFixed32(2)
-                .addFixed64(3)
-                .addLengthDelimited(ByteString.copyFromUtf8("4"))
-                .addGroup(
-                  UnknownFieldSet.newBuilder()
-                    .addField(10,
-                      UnknownFieldSet.Field.newBuilder()
-                        .addVarint(5)
-                        .build())
-                    .build())
-                .build())
-            .addField(8,
-              UnknownFieldSet.Field.newBuilder()
-                .addVarint(1)
-                .addVarint(2)
-                .addVarint(3)
-                .build())
-            .addField(15,
-              UnknownFieldSet.Field.newBuilder()
-                .addVarint(0xABCDEF1234567890L)
-                .addFixed32(0xABCD1234)
-                .addFixed64(0xABCDEF1234567890L)
-                .build())
-            .build())
+        .setUnknownFields(makeUnknownFieldSet())
         .build();
 
     assertEquals(
@@ -409,6 +413,9 @@
       "1:16: Expected \"true\" or \"false\".",
       "optional_bool: maybe");
     assertParseError(
+      "1:16: Expected \"true\" or \"false\".",
+      "optional_bool: 2");
+    assertParseError(
       "1:18: Expected string.",
       "optional_string: 123");
     assertParseError(
@@ -485,6 +492,11 @@
     assertEquals(bytes(0xe1, 0x88, 0xb4),
                  TextFormat.unescapeBytes("\\xe1\\x88\\xb4"));
 
+    // Handling of strings with unescaped Unicode characters > 255.
+    final String zh = "\u9999\u6e2f\u4e0a\u6d77\ud84f\udf80\u8c50\u9280\u884c";
+    ByteString zhByteString = ByteString.copyFromUtf8(zh);
+    assertEquals(zhByteString, TextFormat.unescapeBytes(zh));
+
     // Errors.
     try {
       TextFormat.unescapeText("\\x");
@@ -626,6 +638,13 @@
     }
   }
 
+  public void testParseString() throws Exception {
+    final String zh = "\u9999\u6e2f\u4e0a\u6d77\ud84f\udf80\u8c50\u9280\u884c";
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TextFormat.merge("optional_string: \"" + zh + "\"", builder);
+    assertEquals(zh, builder.getOptionalString());
+  }
+
   public void testParseLongString() throws Exception {
     String longText =
       "123456789012345678901234567890123456789012345678901234567890" +
@@ -654,9 +673,80 @@
     assertEquals(longText, builder.getOptionalString());
   }
 
+  public void testParseBoolean() throws Exception {
+    String goodText =
+        "repeated_bool: t  repeated_bool : 0\n" +
+        "repeated_bool :f repeated_bool:1";
+    String goodTextCanonical =
+        "repeated_bool: true\n" +
+        "repeated_bool: false\n" +
+        "repeated_bool: false\n" +
+        "repeated_bool: true\n";
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TextFormat.merge(goodText, builder);
+    assertEquals(goodTextCanonical, builder.build().toString());
+
+    try {
+      TestAllTypes.Builder badBuilder = TestAllTypes.newBuilder();
+      TextFormat.merge("optional_bool:2", badBuilder);
+      fail("Should have thrown an exception.");
+    } catch (TextFormat.ParseException e) {
+      // success
+    }
+    try {
+      TestAllTypes.Builder badBuilder = TestAllTypes.newBuilder();
+      TextFormat.merge("optional_bool: foo", badBuilder);
+      fail("Should have thrown an exception.");
+    } catch (TextFormat.ParseException e) {
+      // success
+    }
+  }
+
   public void testParseAdjacentStringLiterals() throws Exception {
     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
     TextFormat.merge("optional_string: \"foo\" 'corge' \"grault\"", builder);
     assertEquals("foocorgegrault", builder.getOptionalString());
   }
+
+  public void testPrintFieldValue() throws Exception {
+    assertPrintFieldValue("\"Hello\"", "Hello", "repeated_string");
+    assertPrintFieldValue("123.0",  123f, "repeated_float");
+    assertPrintFieldValue("123.0",  123d, "repeated_double");
+    assertPrintFieldValue("123",  123, "repeated_int32");
+    assertPrintFieldValue("123",  123L, "repeated_int64");
+    assertPrintFieldValue("true",  true, "repeated_bool");
+    assertPrintFieldValue("4294967295", 0xFFFFFFFF, "repeated_uint32");
+    assertPrintFieldValue("18446744073709551615",  0xFFFFFFFFFFFFFFFFL,
+        "repeated_uint64");
+    assertPrintFieldValue("\"\\001\\002\\003\"",
+        ByteString.copyFrom(new byte[] {1, 2, 3}), "repeated_bytes");
+  }
+
+  private void assertPrintFieldValue(String expect, Object value,
+      String fieldName) throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    StringBuilder sb = new StringBuilder();
+    TextFormat.printFieldValue(
+        TestAllTypes.getDescriptor().findFieldByName(fieldName),
+        value, sb);
+    assertEquals(expect, sb.toString());
+  }
+
+  public void testShortDebugString() {
+    assertEquals("optional_nested_message { bb: 42 } repeated_int32: 1"
+        + " repeated_uint32: 2",
+        TextFormat.shortDebugString(TestAllTypes.newBuilder()
+            .addRepeatedInt32(1)
+            .addRepeatedUint32(2)
+            .setOptionalNestedMessage(
+                NestedMessage.newBuilder().setBb(42).build())
+            .build()));
+  }
+
+  public void testShortDebugString_unknown() {
+    assertEquals("5: 1 5: 0x00000002 5: 0x0000000000000003 5: \"4\" 5 { 10: 5 }"
+        + " 8: 1 8: 2 8: 3 15: 12379813812177893520 15: 0xabcd1234 15:"
+        + " 0xabcdef1234567890",
+        TextFormat.shortDebugString(makeUnknownFieldSet()));
+  }
 }
diff --git a/java/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java b/java/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java
new file mode 100644
index 0000000..ed5d069
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java
@@ -0,0 +1,152 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import junit.framework.TestCase;
+
+import java.util.Iterator;
+import java.util.ListIterator;
+
+/**
+ * Tests for {@link UnmodifiableLazyStringList}.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class UnmodifiableLazyStringListTest extends TestCase {
+
+  private static String STRING_A = "A";
+  private static String STRING_B = "B";
+  private static String STRING_C = "C";
+
+  private static ByteString BYTE_STRING_A = ByteString.copyFromUtf8("A");
+  private static ByteString BYTE_STRING_B = ByteString.copyFromUtf8("B");
+  private static ByteString BYTE_STRING_C = ByteString.copyFromUtf8("C");
+
+  public void testReadOnlyMethods() {
+    LazyStringArrayList rawList = createSampleList();
+    UnmodifiableLazyStringList list = new UnmodifiableLazyStringList(rawList);
+    assertEquals(3, list.size());
+    assertSame(STRING_A, list.get(0));
+    assertSame(STRING_B, list.get(1));
+    assertSame(STRING_C, list.get(2));
+    assertEquals(BYTE_STRING_A, list.getByteString(0));
+    assertEquals(BYTE_STRING_B, list.getByteString(1));
+    assertEquals(BYTE_STRING_C, list.getByteString(2));
+  }
+
+  public void testModifyMethods() {
+    LazyStringArrayList rawList = createSampleList();
+    UnmodifiableLazyStringList list = new UnmodifiableLazyStringList(rawList);
+
+    try {
+      list.remove(0);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    assertEquals(3, list.size());
+
+    try {
+      list.add(STRING_B);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+    assertEquals(3, list.size());
+
+    try {
+      list.set(1, STRING_B);
+      fail();
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+  }
+
+  public void testIterator() {
+    LazyStringArrayList rawList = createSampleList();
+    UnmodifiableLazyStringList list = new UnmodifiableLazyStringList(rawList);
+
+    Iterator<String> iter = list.iterator();
+    int count = 0;
+    while (iter.hasNext()) {
+      iter.next();
+      count++;
+      try {
+        iter.remove();
+        fail();
+      } catch (UnsupportedOperationException e) {
+        // expected
+      }
+    }
+    assertEquals(3, count);
+
+  }
+
+  public void testListIterator() {
+    LazyStringArrayList rawList = createSampleList();
+    UnmodifiableLazyStringList list = new UnmodifiableLazyStringList(rawList);
+
+    ListIterator<String> iter = list.listIterator();
+    int count = 0;
+    while (iter.hasNext()) {
+      iter.next();
+      count++;
+      try {
+        iter.remove();
+        fail();
+      } catch (UnsupportedOperationException e) {
+        // expected
+      }
+      try {
+        iter.set("bar");
+        fail();
+      } catch (UnsupportedOperationException e) {
+        // expected
+      }
+      try {
+        iter.add("bar");
+        fail();
+      } catch (UnsupportedOperationException e) {
+        // expected
+      }
+    }
+    assertEquals(3, count);
+
+  }
+
+  private LazyStringArrayList createSampleList() {
+    LazyStringArrayList rawList = new LazyStringArrayList();
+    rawList.add(STRING_A);
+    rawList.add(STRING_B);
+    rawList.add(STRING_C);
+    return rawList;
+  }
+}
diff --git a/java/src/test/java/com/google/protobuf/multiple_files_test.proto b/java/src/test/java/com/google/protobuf/multiple_files_test.proto
index 060f159..9a04014 100644
--- a/java/src/test/java/com/google/protobuf/multiple_files_test.proto
+++ b/java/src/test/java/com/google/protobuf/multiple_files_test.proto
@@ -33,6 +33,10 @@
 // A proto file which tests the java_multiple_files option.
 
 
+// Some generic_services option(s) added automatically.
+// See:  http://go/proto2-generic-services-default
+option java_generic_services = true;   // auto-added
+
 import "google/protobuf/unittest.proto";
 
 package protobuf_unittest;
diff --git a/java/src/test/java/com/google/protobuf/nested_builders_test.proto b/java/src/test/java/com/google/protobuf/nested_builders_test.proto
new file mode 100644
index 0000000..abffb9d
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/nested_builders_test.proto
@@ -0,0 +1,53 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: jonp@google.com (Jon Perlow)
+//
+
+package protobuf_unittest;
+
+option java_multiple_files = true;
+option java_outer_classname = "NestedBuilders";
+
+
+message Vehicle {
+  optional Engine engine = 1;
+  repeated Wheel wheel = 2;
+}
+
+message Engine {
+  optional int32 cylinder = 1;
+  optional int32 liters = 2;
+}
+
+message Wheel {
+  optional int32 radius = 1;
+  optional int32 width = 2;
+}
diff --git a/java/src/test/java/com/google/protobuf/nested_extension.proto b/java/src/test/java/com/google/protobuf/nested_extension.proto
new file mode 100644
index 0000000..9fe5d56
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/nested_extension.proto
@@ -0,0 +1,45 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: Darick Tong (darick@google.com)
+//
+// A proto file with nested extensions. Note that this must be defined in
+// a separate file to properly test the initialization of the outer class.
+
+
+import "com/google/protobuf/non_nested_extension.proto";
+
+package protobuf_unittest;
+
+message MyNestedExtension {
+  extend MessageToBeExtended {
+    optional MessageToBeExtended recursiveExtension = 2;
+  }
+}
diff --git a/java/src/test/java/com/google/protobuf/nested_extension_lite.proto b/java/src/test/java/com/google/protobuf/nested_extension_lite.proto
new file mode 100644
index 0000000..16ee46e
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/nested_extension_lite.proto
@@ -0,0 +1,48 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: Darick Tong (darick@google.com)
+//
+// A proto file with nested extensions for a MessageLite messages. Note that
+// this must be defined in a separate file to properly test the initialization
+// of the outer class.
+
+
+package protobuf_unittest;
+
+option optimize_for = LITE_RUNTIME;
+
+import "com/google/protobuf/non_nested_extension_lite.proto";
+
+message MyNestedExtensionLite {
+  extend MessageLiteToBeExtended {
+    optional MessageLiteToBeExtended recursiveExtensionLite = 3;
+  }
+}
diff --git a/java/src/test/java/com/google/protobuf/non_nested_extension.proto b/java/src/test/java/com/google/protobuf/non_nested_extension.proto
new file mode 100644
index 0000000..f61b419
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/non_nested_extension.proto
@@ -0,0 +1,48 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: Darick Tong (darick@google.com)
+//
+// A proto file with extensions.
+
+
+package protobuf_unittest;
+
+message MessageToBeExtended {
+  extensions 1 to max;
+}
+
+message MyNonNestedExtension {
+}
+
+extend MessageToBeExtended {
+  optional MyNonNestedExtension nonNestedExtension = 1;
+}
+
diff --git a/java/src/test/java/com/google/protobuf/non_nested_extension_lite.proto b/java/src/test/java/com/google/protobuf/non_nested_extension_lite.proto
new file mode 100644
index 0000000..3c82659
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/non_nested_extension_lite.proto
@@ -0,0 +1,50 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: Darick Tong (darick@google.com)
+//
+// A proto file with extensions for a MessageLite messages.
+
+
+package protobuf_unittest;
+
+option optimize_for = LITE_RUNTIME;
+
+message MessageLiteToBeExtended {
+  extensions 1 to max;
+}
+
+message MyNonNestedExtensionLite {
+}
+
+extend MessageLiteToBeExtended {
+  optional MyNonNestedExtensionLite nonNestedExtensionLite = 1;
+}
+
diff --git a/java/src/test/java/com/google/protobuf/test_bad_identifiers.proto b/java/src/test/java/com/google/protobuf/test_bad_identifiers.proto
new file mode 100644
index 0000000..5cc42af
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/test_bad_identifiers.proto
@@ -0,0 +1,66 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: jonp@google.com (Jon Perlow)
+
+// This file tests that various identifiers work as field and type names even
+// though the same identifiers are used internally by the java code generator.
+
+
+// Some generic_services option(s) added automatically.
+// See:  http://go/proto2-generic-services-default
+option java_generic_services = true;   // auto-added
+
+package io_protocol_tests;
+
+option java_package = "com.google.protobuf";
+option java_outer_classname = "TestBadIdentifiersProto";
+
+message TestMessage {
+}
+
+message Deprecated {
+  enum TestEnum {
+    FOO = 1;
+  }
+
+  optional int32 field1 = 1 [deprecated=true];
+  optional TestEnum field2 = 2 [deprecated=true];
+  optional TestMessage field3 = 3 [deprecated=true];
+}
+
+message Override {
+ optional int32 override = 1;
+}
+
+service TestConflictingMethodNames {
+  rpc Override(TestMessage) returns (TestMessage);
+}
+
diff --git a/python/google/protobuf/descriptor.py b/python/google/protobuf/descriptor.py
index aa4ab96..cf609be 100755
--- a/python/google/protobuf/descriptor.py
+++ b/python/google/protobuf/descriptor.py
@@ -28,16 +28,6 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-# TODO(robinson): We probably need to provide deep-copy methods for
-# descriptor types.  When a FieldDescriptor is passed into
-# Descriptor.__init__(), we should make a deep copy and then set
-# containing_type on it.  Alternatively, we could just get
-# rid of containing_type (iit's not needed for reflection.py, at least).
-#
-# TODO(robinson): Print method?
-#
-# TODO(robinson): Useful __repr__?
-
 """Descriptors essentially contain exactly the information found in a .proto
 file, in types that make this information accessible in Python.
 """
@@ -45,6 +35,13 @@
 __author__ = 'robinson@google.com (Will Robinson)'
 
 
+from google.protobuf.internal import api_implementation
+
+
+if api_implementation.Type() == 'cpp':
+  from google.protobuf.internal import cpp_message
+
+
 class Error(Exception):
   """Base error for this module."""
 
@@ -396,6 +393,13 @@
     self.enum_type = enum_type
     self.is_extension = is_extension
     self.extension_scope = extension_scope
+    if api_implementation.Type() == 'cpp':
+      if is_extension:
+        self._cdescriptor = cpp_message.GetExtensionDescriptor(full_name)
+      else:
+        self._cdescriptor = cpp_message.GetFieldDescriptor(full_name)
+    else:
+      self._cdescriptor = None
 
 
 class EnumDescriptor(_NestedDescriptorBase):
@@ -567,9 +571,13 @@
     """Constructor."""
     super(FileDescriptor, self).__init__(options, 'FileOptions')
 
+    self.message_types_by_name = {}
     self.name = name
     self.package = package
     self.serialized_pb = serialized_pb
+    if (api_implementation.Type() == 'cpp' and
+        self.serialized_pb is not None):
+      cpp_message.BuildFile(self.serialized_pb)
 
   def CopyToProto(self, proto):
     """Copies this to a descriptor_pb2.FileDescriptorProto.
diff --git a/python/google/protobuf/internal/api_implementation.py b/python/google/protobuf/internal/api_implementation.py
new file mode 100755
index 0000000..b3e412e
--- /dev/null
+++ b/python/google/protobuf/internal/api_implementation.py
@@ -0,0 +1,64 @@
+# Protocol Buffers - Google's data interchange format
+# Copyright 2008 Google Inc.  All rights reserved.
+# http://code.google.com/p/protobuf/
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""
+This module is the central entity that determines which implementation of the
+API is used.
+"""
+
+__author__ = 'petar@google.com (Petar Petrov)'
+
+import os
+# This environment variable can be used to switch to a certain implementation
+# of the Python API. Right now only 'python' and 'cpp' are valid values. Any
+# other value will be ignored.
+_implementation_type = os.getenv('PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION',
+                                 'python')
+
+
+if _implementation_type != 'python':
+  # For now, by default use the pure-Python implementation.
+  # The code below checks if the C extension is available and
+  # uses it if it is available.
+  _implementation_type = 'cpp'
+  ## Determine automatically which implementation to use.
+  #try:
+  #  from google.protobuf.internal import cpp_message
+  #  _implementation_type = 'cpp'
+  #except ImportError, e:
+  #  _implementation_type = 'python'
+
+
+# Usage of this function is discouraged. Clients shouldn't care which
+# implementation of the API is in use. Note that there is no guarantee
+# that differences between APIs will be maintained.
+# Please don't use this function if possible.
+def Type():
+  return _implementation_type
diff --git a/python/google/protobuf/internal/containers.py b/python/google/protobuf/internal/containers.py
index 5cc7d6d..097a3c2 100755
--- a/python/google/protobuf/internal/containers.py
+++ b/python/google/protobuf/internal/containers.py
@@ -72,9 +72,15 @@
     # The concrete classes should define __eq__.
     return not self == other
 
+  def __hash__(self):
+    raise TypeError('unhashable object')
+
   def __repr__(self):
     return repr(self._values)
 
+  def sort(self, sort_function=cmp):
+    self._values.sort(sort_function)
+
 
 class RepeatedScalarFieldContainer(BaseContainer):
 
@@ -198,28 +204,37 @@
     super(RepeatedCompositeFieldContainer, self).__init__(message_listener)
     self._message_descriptor = message_descriptor
 
-  def add(self):
-    new_element = self._message_descriptor._concrete_class()
+  def add(self, **kwargs):
+    """Adds a new element at the end of the list and returns it. Keyword
+    arguments may be used to initialize the element.
+    """
+    new_element = self._message_descriptor._concrete_class(**kwargs)
     new_element._SetListener(self._message_listener)
     self._values.append(new_element)
     if not self._message_listener.dirty:
       self._message_listener.Modified()
     return new_element
 
-  def MergeFrom(self, other):
-    """Appends the contents of another repeated field of the same type to this
-    one, copying each individual message.
+  def extend(self, elem_seq):
+    """Extends by appending the given sequence of elements of the same type
+    as this one, copying each individual message.
     """
     message_class = self._message_descriptor._concrete_class
     listener = self._message_listener
     values = self._values
-    for message in other._values:
+    for message in elem_seq:
       new_element = message_class()
       new_element._SetListener(listener)
       new_element.MergeFrom(message)
       values.append(new_element)
     listener.Modified()
 
+  def MergeFrom(self, other):
+    """Appends the contents of another repeated field of the same type to this
+    one, copying each individual message.
+    """
+    self.extend(other._values)
+
   def __getslice__(self, start, stop):
     """Retrieves the subset of items from between the specified indices."""
     return self._values[start:stop]
diff --git a/python/google/protobuf/internal/cpp_message.py b/python/google/protobuf/internal/cpp_message.py
new file mode 100755
index 0000000..3f42650
--- /dev/null
+++ b/python/google/protobuf/internal/cpp_message.py
@@ -0,0 +1,616 @@
+# Protocol Buffers - Google's data interchange format
+# Copyright 2008 Google Inc.  All rights reserved.
+# http://code.google.com/p/protobuf/
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Contains helper functions used to create protocol message classes from
+Descriptor objects at runtime backed by the protocol buffer C++ API.
+"""
+
+__author__ = 'petar@google.com (Petar Petrov)'
+
+import operator
+from google.protobuf.internal import _net_proto2___python
+from google.protobuf import message
+
+
+_LABEL_REPEATED = _net_proto2___python.LABEL_REPEATED
+_LABEL_OPTIONAL = _net_proto2___python.LABEL_OPTIONAL
+_CPPTYPE_MESSAGE = _net_proto2___python.CPPTYPE_MESSAGE
+_TYPE_MESSAGE = _net_proto2___python.TYPE_MESSAGE
+
+
+def GetDescriptorPool():
+  """Creates a new DescriptorPool C++ object."""
+  return _net_proto2___python.NewCDescriptorPool()
+
+
+_pool = GetDescriptorPool()
+
+
+def GetFieldDescriptor(full_field_name):
+  """Searches for a field descriptor given a full field name."""
+  return _pool.FindFieldByName(full_field_name)
+
+
+def BuildFile(content):
+  """Registers a new proto file in the underlying C++ descriptor pool."""
+  _net_proto2___python.BuildFile(content)
+
+
+def GetExtensionDescriptor(full_extension_name):
+  """Searches for extension descriptor given a full field name."""
+  return _pool.FindExtensionByName(full_extension_name)
+
+
+def NewCMessage(full_message_name):
+  """Creates a new C++ protocol message by its name."""
+  return _net_proto2___python.NewCMessage(full_message_name)
+
+
+def ScalarProperty(cdescriptor):
+  """Returns a scalar property for the given descriptor."""
+
+  def Getter(self):
+    return self._cmsg.GetScalar(cdescriptor)
+
+  def Setter(self, value):
+    self._cmsg.SetScalar(cdescriptor, value)
+
+  return property(Getter, Setter)
+
+
+def CompositeProperty(cdescriptor, message_type):
+  """Returns a Python property the given composite field."""
+
+  def Getter(self):
+    sub_message = self._composite_fields.get(cdescriptor.name, None)
+    if sub_message is None:
+      cmessage = self._cmsg.NewSubMessage(cdescriptor)
+      sub_message = message_type._concrete_class(__cmessage=cmessage)
+      self._composite_fields[cdescriptor.name] = sub_message
+    return sub_message
+
+  return property(Getter)
+
+
+class RepeatedScalarContainer(object):
+  """Container for repeated scalar fields."""
+
+  __slots__ = ['_message', '_cfield_descriptor', '_cmsg']
+
+  def __init__(self, msg, cfield_descriptor):
+    self._message = msg
+    self._cmsg = msg._cmsg
+    self._cfield_descriptor = cfield_descriptor
+
+  def append(self, value):
+    self._cmsg.AddRepeatedScalar(
+        self._cfield_descriptor, value)
+
+  def extend(self, sequence):
+    for element in sequence:
+      self.append(element)
+
+  def insert(self, key, value):
+    values = self[slice(None, None, None)]
+    values.insert(key, value)
+    self._cmsg.AssignRepeatedScalar(self._cfield_descriptor, values)
+
+  def remove(self, value):
+    values = self[slice(None, None, None)]
+    values.remove(value)
+    self._cmsg.AssignRepeatedScalar(self._cfield_descriptor, values)
+
+  def __setitem__(self, key, value):
+    values = self[slice(None, None, None)]
+    values[key] = value
+    self._cmsg.AssignRepeatedScalar(self._cfield_descriptor, values)
+
+  def __getitem__(self, key):
+    return self._cmsg.GetRepeatedScalar(self._cfield_descriptor, key)
+
+  def __delitem__(self, key):
+    self._cmsg.DeleteRepeatedField(self._cfield_descriptor, key)
+
+  def __len__(self):
+    return len(self[slice(None, None, None)])
+
+  def __eq__(self, other):
+    if self is other:
+      return True
+    if not operator.isSequenceType(other):
+      raise TypeError(
+          'Can only compare repeated scalar fields against sequences.')
+    # We are presumably comparing against some other sequence type.
+    return other == self[slice(None, None, None)]
+
+  def __ne__(self, other):
+    return not self == other
+
+  def __hash__(self):
+    raise TypeError('unhashable object')
+
+  def sort(self, sort_function=cmp):
+    values = self[slice(None, None, None)]
+    values.sort(sort_function)
+    self._cmsg.AssignRepeatedScalar(self._cfield_descriptor, values)
+
+
+def RepeatedScalarProperty(cdescriptor):
+  """Returns a Python property the given repeated scalar field."""
+
+  def Getter(self):
+    container = self._composite_fields.get(cdescriptor.name, None)
+    if container is None:
+      container = RepeatedScalarContainer(self, cdescriptor)
+      self._composite_fields[cdescriptor.name] = container
+    return container
+
+  def Setter(self, new_value):
+    raise AttributeError('Assignment not allowed to repeated field '
+                         '"%s" in protocol message object.' % cdescriptor.name)
+
+  doc = 'Magic attribute generated for "%s" proto field.' % cdescriptor.name
+  return property(Getter, Setter, doc=doc)
+
+
+class RepeatedCompositeContainer(object):
+  """Container for repeated composite fields."""
+
+  __slots__ = ['_message', '_subclass', '_cfield_descriptor', '_cmsg']
+
+  def __init__(self, msg, cfield_descriptor, subclass):
+    self._message = msg
+    self._cmsg = msg._cmsg
+    self._subclass = subclass
+    self._cfield_descriptor = cfield_descriptor
+
+  def add(self, **kwargs):
+    cmessage = self._cmsg.AddMessage(self._cfield_descriptor)
+    return self._subclass(__cmessage=cmessage, __owner=self._message, **kwargs)
+
+  def extend(self, elem_seq):
+    """Extends by appending the given sequence of elements of the same type
+    as this one, copying each individual message.
+    """
+    for message in elem_seq:
+      self.add().MergeFrom(message)
+
+  def MergeFrom(self, other):
+    for message in other[:]:
+      self.add().MergeFrom(message)
+
+  def __getitem__(self, key):
+    cmessages = self._cmsg.GetRepeatedMessage(
+        self._cfield_descriptor, key)
+    subclass = self._subclass
+    if not isinstance(cmessages, list):
+      return subclass(__cmessage=cmessages, __owner=self._message)
+
+    return [subclass(__cmessage=m, __owner=self._message) for m in cmessages]
+
+  def __delitem__(self, key):
+    self._cmsg.DeleteRepeatedField(
+        self._cfield_descriptor, key)
+
+  def __len__(self):
+    return self._cmsg.FieldLength(self._cfield_descriptor)
+
+  def __eq__(self, other):
+    """Compares the current instance with another one."""
+    if self is other:
+      return True
+    if not isinstance(other, self.__class__):
+      raise TypeError('Can only compare repeated composite fields against '
+                      'other repeated composite fields.')
+    messages = self[slice(None, None, None)]
+    other_messages = other[slice(None, None, None)]
+    return messages == other_messages
+
+  def __hash__(self):
+    raise TypeError('unhashable object')
+
+  def sort(self, sort_function=cmp):
+    messages = []
+    for index in range(len(self)):
+      # messages[i][0] is where the i-th element of the new array has to come
+      # from.
+      # messages[i][1] is where the i-th element of the old array has to go.
+      messages.append([index, 0, self[index]])
+    messages.sort(lambda x,y: sort_function(x[2], y[2]))
+
+    # Remember which position each elements has to move to.
+    for i in range(len(messages)):
+      messages[messages[i][0]][1] = i
+
+    # Apply the transposition.
+    for i in range(len(messages)):
+      from_position = messages[i][0]
+      if i == from_position:
+        continue
+      self._cmsg.SwapRepeatedFieldElements(
+          self._cfield_descriptor, i, from_position)
+      messages[messages[i][1]][0] = from_position
+
+
+def RepeatedCompositeProperty(cdescriptor, message_type):
+  """Returns a Python property for the given repeated composite field."""
+
+  def Getter(self):
+    container = self._composite_fields.get(cdescriptor.name, None)
+    if container is None:
+      container = RepeatedCompositeContainer(
+          self, cdescriptor, message_type._concrete_class)
+      self._composite_fields[cdescriptor.name] = container
+    return container
+
+  def Setter(self, new_value):
+    raise AttributeError('Assignment not allowed to repeated field '
+                         '"%s" in protocol message object.' % cdescriptor.name)
+
+  doc = 'Magic attribute generated for "%s" proto field.' % cdescriptor.name
+  return property(Getter, Setter, doc=doc)
+
+
+class ExtensionDict(object):
+  """Extension dictionary added to each protocol message."""
+
+  def __init__(self, msg):
+    self._message = msg
+    self._cmsg = msg._cmsg
+    self._values = {}
+
+  def __setitem__(self, extension, value):
+    from google.protobuf import descriptor
+    if not isinstance(extension, descriptor.FieldDescriptor):
+      raise KeyError('Bad extension %r.' % (extension,))
+    cdescriptor = extension._cdescriptor
+    if (cdescriptor.label != _LABEL_OPTIONAL or
+        cdescriptor.cpp_type == _CPPTYPE_MESSAGE):
+      raise TypeError('Extension %r is repeated and/or a composite type.' % (
+          extension.full_name,))
+    self._cmsg.SetScalar(cdescriptor, value)
+    self._values[extension] = value
+
+  def __getitem__(self, extension):
+    from google.protobuf import descriptor
+    if not isinstance(extension, descriptor.FieldDescriptor):
+      raise KeyError('Bad extension %r.' % (extension,))
+
+    cdescriptor = extension._cdescriptor
+    if (cdescriptor.label != _LABEL_REPEATED and
+        cdescriptor.cpp_type != _CPPTYPE_MESSAGE):
+      return self._cmsg.GetScalar(cdescriptor)
+
+    ext = self._values.get(extension, None)
+    if ext is not None:
+      return ext
+
+    ext = self._CreateNewHandle(extension)
+    self._values[extension] = ext
+    return ext
+
+  def ClearExtension(self, extension):
+    from google.protobuf import descriptor
+    if not isinstance(extension, descriptor.FieldDescriptor):
+      raise KeyError('Bad extension %r.' % (extension,))
+    self._cmsg.ClearFieldByDescriptor(extension._cdescriptor)
+    if extension in self._values:
+      del self._values[extension]
+
+  def HasExtension(self, extension):
+    from google.protobuf import descriptor
+    if not isinstance(extension, descriptor.FieldDescriptor):
+      raise KeyError('Bad extension %r.' % (extension,))
+    return self._cmsg.HasFieldByDescriptor(extension._cdescriptor)
+
+  def _FindExtensionByName(self, name):
+    """Tries to find a known extension with the specified name.
+
+    Args:
+      name: Extension full name.
+
+    Returns:
+      Extension field descriptor.
+    """
+    return self._message._extensions_by_name.get(name, None)
+
+  def _CreateNewHandle(self, extension):
+    cdescriptor = extension._cdescriptor
+    if (cdescriptor.label != _LABEL_REPEATED and
+        cdescriptor.cpp_type == _CPPTYPE_MESSAGE):
+      cmessage = self._cmsg.NewSubMessage(cdescriptor)
+      return extension.message_type._concrete_class(__cmessage=cmessage)
+
+    if cdescriptor.label == _LABEL_REPEATED:
+      if cdescriptor.cpp_type == _CPPTYPE_MESSAGE:
+        return RepeatedCompositeContainer(
+            self._message, cdescriptor, extension.message_type._concrete_class)
+      else:
+        return RepeatedScalarContainer(self._message, cdescriptor)
+    # This shouldn't happen!
+    assert False
+    return None
+
+
+def NewMessage(message_descriptor, dictionary):
+  """Creates a new protocol message *class*."""
+  _AddClassAttributesForNestedExtensions(message_descriptor, dictionary)
+  _AddEnumValues(message_descriptor, dictionary)
+  _AddDescriptors(message_descriptor, dictionary)
+
+
+def InitMessage(message_descriptor, cls):
+  """Constructs a new message instance (called before instance's __init__)."""
+  cls._extensions_by_name = {}
+  _AddInitMethod(message_descriptor, cls)
+  _AddMessageMethods(message_descriptor, cls)
+  _AddPropertiesForExtensions(message_descriptor, cls)
+
+
+def _AddDescriptors(message_descriptor, dictionary):
+  """Sets up a new protocol message class dictionary.
+
+  Args:
+    message_descriptor: A Descriptor instance describing this message type.
+    dictionary: Class dictionary to which we'll add a '__slots__' entry.
+  """
+  dictionary['__descriptors'] = {}
+  for field in message_descriptor.fields:
+    dictionary['__descriptors'][field.name] = GetFieldDescriptor(
+        field.full_name)
+
+  dictionary['__slots__'] = list(dictionary['__descriptors'].iterkeys()) + [
+      '_cmsg', '_owner', '_composite_fields', 'Extensions']
+
+
+def _AddEnumValues(message_descriptor, dictionary):
+  """Sets class-level attributes for all enum fields defined in this message.
+
+  Args:
+    message_descriptor: Descriptor object for this message type.
+    dictionary: Class dictionary that should be populated.
+  """
+  for enum_type in message_descriptor.enum_types:
+    for enum_value in enum_type.values:
+      dictionary[enum_value.name] = enum_value.number
+
+
+def _AddClassAttributesForNestedExtensions(message_descriptor, dictionary):
+  """Adds class attributes for the nested extensions."""
+  extension_dict = message_descriptor.extensions_by_name
+  for extension_name, extension_field in extension_dict.iteritems():
+    assert extension_name not in dictionary
+    dictionary[extension_name] = extension_field
+
+
+def _AddInitMethod(message_descriptor, cls):
+  """Adds an __init__ method to cls."""
+
+  # Create and attach message field properties to the message class.
+  # This can be done just once per message class, since property setters and
+  # getters are passed the message instance.
+  # This makes message instantiation extremely fast, and at the same time it
+  # doesn't require the creation of property objects for each message instance,
+  # which saves a lot of memory.
+  for field in message_descriptor.fields:
+    field_cdescriptor = cls.__descriptors[field.name]
+    if field.label == _LABEL_REPEATED:
+      if field.cpp_type == _CPPTYPE_MESSAGE:
+        value = RepeatedCompositeProperty(field_cdescriptor, field.message_type)
+      else:
+        value = RepeatedScalarProperty(field_cdescriptor)
+    elif field.cpp_type == _CPPTYPE_MESSAGE:
+      value = CompositeProperty(field_cdescriptor, field.message_type)
+    else:
+      value = ScalarProperty(field_cdescriptor)
+    setattr(cls, field.name, value)
+
+    # Attach a constant with the field number.
+    constant_name = field.name.upper() + '_FIELD_NUMBER'
+    setattr(cls, constant_name, field.number)
+
+  def Init(self, **kwargs):
+    """Message constructor."""
+    cmessage = kwargs.pop('__cmessage', None)
+    if cmessage is None:
+      self._cmsg = NewCMessage(message_descriptor.full_name)
+    else:
+      self._cmsg = cmessage
+
+    # Keep a reference to the owner, as the owner keeps a reference to the
+    # underlying protocol buffer message.
+    owner = kwargs.pop('__owner', None)
+    if owner is not None:
+      self._owner = owner
+
+    self.Extensions = ExtensionDict(self)
+    self._composite_fields = {}
+
+    for field_name, field_value in kwargs.iteritems():
+      field_cdescriptor = self.__descriptors.get(field_name, None)
+      if field_cdescriptor is None:
+        raise ValueError('Protocol message has no "%s" field.' % field_name)
+      if field_cdescriptor.label == _LABEL_REPEATED:
+        if field_cdescriptor.cpp_type == _CPPTYPE_MESSAGE:
+          for val in field_value:
+            getattr(self, field_name).add().MergeFrom(val)
+        else:
+          getattr(self, field_name).extend(field_value)
+      elif field_cdescriptor.cpp_type == _CPPTYPE_MESSAGE:
+        getattr(self, field_name).MergeFrom(field_value)
+      else:
+        setattr(self, field_name, field_value)
+
+  Init.__module__ = None
+  Init.__doc__ = None
+  cls.__init__ = Init
+
+
+def _IsMessageSetExtension(field):
+  """Checks if a field is a message set extension."""
+  return (field.is_extension and
+          field.containing_type.has_options and
+          field.containing_type.GetOptions().message_set_wire_format and
+          field.type == _TYPE_MESSAGE and
+          field.message_type == field.extension_scope and
+          field.label == _LABEL_OPTIONAL)
+
+
+def _AddMessageMethods(message_descriptor, cls):
+  """Adds the methods to a protocol message class."""
+  if message_descriptor.is_extendable:
+
+    def ClearExtension(self, extension):
+      self.Extensions.ClearExtension(extension)
+
+    def HasExtension(self, extension):
+      return self.Extensions.HasExtension(extension)
+
+  def HasField(self, field_name):
+    return self._cmsg.HasField(field_name)
+
+  def ClearField(self, field_name):
+    if field_name in self._composite_fields:
+      del self._composite_fields[field_name]
+    self._cmsg.ClearField(field_name)
+
+  def Clear(self):
+    return self._cmsg.Clear()
+
+  def IsInitialized(self, errors=None):
+    if self._cmsg.IsInitialized():
+      return True
+    if errors is not None:
+      errors.extend(self.FindInitializationErrors());
+    return False
+
+  def SerializeToString(self):
+    if not self.IsInitialized():
+      raise message.EncodeError(
+          'Message is missing required fields: ' +
+          ','.join(self.FindInitializationErrors()))
+    return self._cmsg.SerializeToString()
+
+  def SerializePartialToString(self):
+    return self._cmsg.SerializePartialToString()
+
+  def ParseFromString(self, serialized):
+    self.Clear()
+    self.MergeFromString(serialized)
+
+  def MergeFromString(self, serialized):
+    byte_size = self._cmsg.MergeFromString(serialized)
+    if byte_size < 0:
+      raise message.DecodeError('Unable to merge from string.')
+    return byte_size
+
+  def MergeFrom(self, msg):
+    if not isinstance(msg, cls):
+      raise TypeError(
+          "Parameter to MergeFrom() must be instance of same class.")
+    self._cmsg.MergeFrom(msg._cmsg)
+
+  def CopyFrom(self, msg):
+    self._cmsg.CopyFrom(msg._cmsg)
+
+  def ByteSize(self):
+    return self._cmsg.ByteSize()
+
+  def SetInParent(self):
+    return self._cmsg.SetInParent()
+
+  def ListFields(self):
+    all_fields = []
+    field_list = self._cmsg.ListFields()
+    fields_by_name = cls.DESCRIPTOR.fields_by_name
+    for is_extension, field_name in field_list:
+      if is_extension:
+        extension = cls._extensions_by_name[field_name]
+        all_fields.append((extension, self.Extensions[extension]))
+      else:
+        field_descriptor = fields_by_name[field_name]
+        all_fields.append(
+            (field_descriptor, getattr(self, field_name)))
+    all_fields.sort(key=lambda item: item[0].number)
+    return all_fields
+
+  def FindInitializationErrors(self):
+    return self._cmsg.FindInitializationErrors()
+
+  def __str__(self):
+    return self._cmsg.DebugString()
+
+  def __eq__(self, other):
+    if self is other:
+      return True
+    if not isinstance(other, self.__class__):
+      return False
+    return self.ListFields() == other.ListFields()
+
+  def __ne__(self, other):
+    return not self == other
+
+  def __hash__(self):
+    raise TypeError('unhashable object')
+
+  def __unicode__(self):
+    return text_format.MessageToString(self, as_utf8=True).decode('utf-8')
+
+  # Attach the local methods to the message class.
+  for key, value in locals().copy().iteritems():
+    if key not in ('key', 'value', '__builtins__', '__name__', '__doc__'):
+      setattr(cls, key, value)
+
+  # Static methods:
+
+  def RegisterExtension(extension_handle):
+    extension_handle.containing_type = cls.DESCRIPTOR
+    cls._extensions_by_name[extension_handle.full_name] = extension_handle
+
+    if _IsMessageSetExtension(extension_handle):
+      # MessageSet extension.  Also register under type name.
+      cls._extensions_by_name[
+          extension_handle.message_type.full_name] = extension_handle
+  cls.RegisterExtension = staticmethod(RegisterExtension)
+
+  def FromString(string):
+    msg = cls()
+    msg.MergeFromString(string)
+    return msg
+  cls.FromString = staticmethod(FromString)
+
+
+
+def _AddPropertiesForExtensions(message_descriptor, cls):
+  """Adds properties for all fields in this protocol message type."""
+  extension_dict = message_descriptor.extensions_by_name
+  for extension_name, extension_field in extension_dict.iteritems():
+    constant_name = extension_name.upper() + '_FIELD_NUMBER'
+    setattr(cls, constant_name, extension_field.number)
diff --git a/python/google/protobuf/internal/decoder.py b/python/google/protobuf/internal/decoder.py
index 461a30c..55f746f 100755
--- a/python/google/protobuf/internal/decoder.py
+++ b/python/google/protobuf/internal/decoder.py
@@ -86,6 +86,13 @@
 from google.protobuf import message
 
 
+# This will overflow and thus become IEEE-754 "infinity".  We would use
+# "float('inf')" but it doesn't work on Windows pre-Python-2.6.
+_POS_INF = 1e10000
+_NEG_INF = -_POS_INF
+_NAN = _POS_INF * 0
+
+
 # This is not for optimization, but rather to avoid conflicts with local
 # variables named "message".
 _DecodeError = message.DecodeError
@@ -269,6 +276,72 @@
   return _SimpleDecoder(wire_type, InnerDecode)
 
 
+def _FloatDecoder():
+  """Returns a decoder for a float field.
+
+  This code works around a bug in struct.unpack for non-finite 32-bit
+  floating-point values.
+  """
+
+  local_unpack = struct.unpack
+
+  def InnerDecode(buffer, pos):
+    # We expect a 32-bit value in little-endian byte order.  Bit 1 is the sign
+    # bit, bits 2-9 represent the exponent, and bits 10-32 are the significand.
+    new_pos = pos + 4
+    float_bytes = buffer[pos:new_pos]
+
+    # If this value has all its exponent bits set, then it's non-finite.
+    # In Python 2.4, struct.unpack will convert it to a finite 64-bit value.
+    # To avoid that, we parse it specially.
+    if ((float_bytes[3] in '\x7F\xFF')
+        and (float_bytes[2] >= '\x80')):
+      # If at least one significand bit is set...
+      if float_bytes[0:3] != '\x00\x00\x80':
+        return (_NAN, new_pos)
+      # If sign bit is set...
+      if float_bytes[3] == '\xFF':
+        return (_NEG_INF, new_pos)
+      return (_POS_INF, new_pos)
+
+    # Note that we expect someone up-stack to catch struct.error and convert
+    # it to _DecodeError -- this way we don't have to set up exception-
+    # handling blocks every time we parse one value.
+    result = local_unpack('<f', float_bytes)[0]
+    return (result, new_pos)
+  return _SimpleDecoder(wire_format.WIRETYPE_FIXED32, InnerDecode)
+
+
+def _DoubleDecoder():
+  """Returns a decoder for a double field.
+
+  This code works around a bug in struct.unpack for not-a-number.
+  """
+
+  local_unpack = struct.unpack
+
+  def InnerDecode(buffer, pos):
+    # We expect a 64-bit value in little-endian byte order.  Bit 1 is the sign
+    # bit, bits 2-12 represent the exponent, and bits 13-64 are the significand.
+    new_pos = pos + 8
+    double_bytes = buffer[pos:new_pos]
+
+    # If this value has all its exponent bits set and at least one significand
+    # bit set, it's not a number.  In Python 2.4, struct.unpack will treat it
+    # as inf or -inf.  To avoid that, we treat it specially.
+    if ((double_bytes[7] in '\x7F\xFF')
+        and (double_bytes[6] >= '\xF0')
+        and (double_bytes[0:7] != '\x00\x00\x00\x00\x00\x00\xF0')):
+      return (_NAN, new_pos)
+
+    # Note that we expect someone up-stack to catch struct.error and convert
+    # it to _DecodeError -- this way we don't have to set up exception-
+    # handling blocks every time we parse one value.
+    result = local_unpack('<d', double_bytes)[0]
+    return (result, new_pos)
+  return _SimpleDecoder(wire_format.WIRETYPE_FIXED64, InnerDecode)
+
+
 # --------------------------------------------------------------------
 
 
@@ -294,8 +367,8 @@
 Fixed64Decoder  = _StructPackDecoder(wire_format.WIRETYPE_FIXED64, '<Q')
 SFixed32Decoder = _StructPackDecoder(wire_format.WIRETYPE_FIXED32, '<i')
 SFixed64Decoder = _StructPackDecoder(wire_format.WIRETYPE_FIXED64, '<q')
-FloatDecoder    = _StructPackDecoder(wire_format.WIRETYPE_FIXED32, '<f')
-DoubleDecoder   = _StructPackDecoder(wire_format.WIRETYPE_FIXED64, '<d')
+FloatDecoder = _FloatDecoder()
+DoubleDecoder = _DoubleDecoder()
 
 BoolDecoder = _ModifiedDecoder(
     wire_format.WIRETYPE_VARINT, _DecodeVarint, bool)
diff --git a/python/google/protobuf/internal/encoder.py b/python/google/protobuf/internal/encoder.py
index aa05d5b..777975e 100755
--- a/python/google/protobuf/internal/encoder.py
+++ b/python/google/protobuf/internal/encoder.py
@@ -70,6 +70,12 @@
 from google.protobuf.internal import wire_format
 
 
+# This will overflow and thus become IEEE-754 "infinity".  We would use
+# "float('inf')" but it doesn't work on Windows pre-Python-2.6.
+_POS_INF = 1e10000
+_NEG_INF = -_POS_INF
+
+
 def _VarintSize(value):
   """Compute the size of a varint value."""
   if value <= 0x7f: return 1
@@ -502,6 +508,83 @@
   return SpecificEncoder
 
 
+def _FloatingPointEncoder(wire_type, format):
+  """Return a constructor for an encoder for float fields.
+
+  This is like StructPackEncoder, but catches errors that may be due to
+  passing non-finite floating-point values to struct.pack, and makes a
+  second attempt to encode those values.
+
+  Args:
+      wire_type:  The field's wire type, for encoding tags.
+      format:  The format string to pass to struct.pack().
+  """
+
+  value_size = struct.calcsize(format)
+  if value_size == 4:
+    def EncodeNonFiniteOrRaise(write, value):
+      # Remember that the serialized form uses little-endian byte order.
+      if value == _POS_INF:
+        write('\x00\x00\x80\x7F')
+      elif value == _NEG_INF:
+        write('\x00\x00\x80\xFF')
+      elif value != value:           # NaN
+        write('\x00\x00\xC0\x7F')
+      else:
+        raise
+  elif value_size == 8:
+    def EncodeNonFiniteOrRaise(write, value):
+      if value == _POS_INF:
+        write('\x00\x00\x00\x00\x00\x00\xF0\x7F')
+      elif value == _NEG_INF:
+        write('\x00\x00\x00\x00\x00\x00\xF0\xFF')
+      elif value != value:                         # NaN
+        write('\x00\x00\x00\x00\x00\x00\xF8\x7F')
+      else:
+        raise
+  else:
+    raise ValueError('Can\'t encode floating-point values that are '
+                     '%d bytes long (only 4 or 8)' % value_size)
+
+  def SpecificEncoder(field_number, is_repeated, is_packed):
+    local_struct_pack = struct.pack
+    if is_packed:
+      tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
+      local_EncodeVarint = _EncodeVarint
+      def EncodePackedField(write, value):
+        write(tag_bytes)
+        local_EncodeVarint(write, len(value) * value_size)
+        for element in value:
+          # This try/except block is going to be faster than any code that
+          # we could write to check whether element is finite.
+          try:
+            write(local_struct_pack(format, element))
+          except SystemError:
+            EncodeNonFiniteOrRaise(write, element)
+      return EncodePackedField
+    elif is_repeated:
+      tag_bytes = TagBytes(field_number, wire_type)
+      def EncodeRepeatedField(write, value):
+        for element in value:
+          write(tag_bytes)
+          try:
+            write(local_struct_pack(format, element))
+          except SystemError:
+            EncodeNonFiniteOrRaise(write, element)
+      return EncodeRepeatedField
+    else:
+      tag_bytes = TagBytes(field_number, wire_type)
+      def EncodeField(write, value):
+        write(tag_bytes)
+        try:
+          write(local_struct_pack(format, value))
+        except SystemError:
+          EncodeNonFiniteOrRaise(write, value)
+      return EncodeField
+
+  return SpecificEncoder
+
+
 # ====================================================================
 # Here we declare an encoder constructor for each field type.  These work
 # very similarly to sizer constructors, described earlier.
@@ -525,8 +608,8 @@
 Fixed64Encoder  = _StructPackEncoder(wire_format.WIRETYPE_FIXED64, '<Q')
 SFixed32Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED32, '<i')
 SFixed64Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED64, '<q')
-FloatEncoder    = _StructPackEncoder(wire_format.WIRETYPE_FIXED32, '<f')
-DoubleEncoder   = _StructPackEncoder(wire_format.WIRETYPE_FIXED64, '<d')
+FloatEncoder    = _FloatingPointEncoder(wire_format.WIRETYPE_FIXED32, '<f')
+DoubleEncoder   = _FloatingPointEncoder(wire_format.WIRETYPE_FIXED64, '<d')
 
 
 def BoolEncoder(field_number, is_repeated, is_packed):
diff --git a/python/google/protobuf/internal/generator_test.py b/python/google/protobuf/internal/generator_test.py
index 78360b5..e4387c8 100755
--- a/python/google/protobuf/internal/generator_test.py
+++ b/python/google/protobuf/internal/generator_test.py
@@ -42,11 +42,12 @@
 __author__ = 'robinson@google.com (Will Robinson)'
 
 import unittest
+from google.protobuf import unittest_custom_options_pb2
 from google.protobuf import unittest_import_pb2
 from google.protobuf import unittest_mset_pb2
 from google.protobuf import unittest_pb2
 from google.protobuf import unittest_no_generic_services_pb2
-
+from google.protobuf import service
 
 MAX_EXTENSION = 536870912
 
@@ -140,6 +141,13 @@
     proto = unittest_mset_pb2.TestMessageSet()
     self.assertTrue(proto.DESCRIPTOR.GetOptions().message_set_wire_format)
 
+  def testMessageWithCustomOptions(self):
+    proto = unittest_custom_options_pb2.TestMessageWithCustomOptions()
+    enum_options = proto.DESCRIPTOR.enum_types_by_name['AnEnum'].GetOptions()
+    self.assertTrue(enum_options is not None)
+    # TODO(gps): We really should test for the presense of the enum_opt1
+    # extension and for its value to be set to -789.
+
   def testNestedTypes(self):
     self.assertEquals(
         set(unittest_pb2.TestAllTypes.DESCRIPTOR.nested_types),
@@ -208,12 +216,27 @@
     self.assertFalse(unittest_pb2.DESCRIPTOR.serialized_pb is None)
 
   def testNoGenericServices(self):
-    # unittest_no_generic_services.proto should contain defs for everything
-    # except services.
     self.assertTrue(hasattr(unittest_no_generic_services_pb2, "TestMessage"))
     self.assertTrue(hasattr(unittest_no_generic_services_pb2, "FOO"))
     self.assertTrue(hasattr(unittest_no_generic_services_pb2, "test_extension"))
-    self.assertFalse(hasattr(unittest_no_generic_services_pb2, "TestService"))
+
+    # Make sure unittest_no_generic_services_pb2 has no services subclassing
+    # Proto2 Service class.
+    if hasattr(unittest_no_generic_services_pb2, "TestService"):
+      self.assertFalse(issubclass(unittest_no_generic_services_pb2.TestService,
+                                  service.Service))
+
+  def testMessageTypesByName(self):
+    file_type = unittest_pb2.DESCRIPTOR
+    self.assertEqual(
+        unittest_pb2._TESTALLTYPES,
+        file_type.message_types_by_name[unittest_pb2._TESTALLTYPES.name])
+
+    # Nested messages shouldn't be included in the message_types_by_name
+    # dictionary (like in the C++ API).
+    self.assertFalse(
+        unittest_pb2._TESTALLTYPES_NESTEDMESSAGE.name in
+        file_type.message_types_by_name)
 
 
 if __name__ == '__main__':
diff --git a/python/google/protobuf/internal/message_test.py b/python/google/protobuf/internal/message_test.py
index 73a9a3a..6517437 100755
--- a/python/google/protobuf/internal/message_test.py
+++ b/python/google/protobuf/internal/message_test.py
@@ -43,11 +43,25 @@
 
 __author__ = 'gps@google.com (Gregory P. Smith)'
 
+import copy
+import math
 import unittest
 from google.protobuf import unittest_import_pb2
 from google.protobuf import unittest_pb2
 from google.protobuf.internal import test_util
 
+# Python pre-2.6 does not have isinf() or isnan() functions, so we have
+# to provide our own.
+def isnan(val):
+  # NaN is never equal to itself.
+  return val != val
+def isinf(val):
+  # Infinity times zero equals NaN.
+  return not isnan(val) and isnan(val * 0)
+def IsPosInf(val):
+  return isinf(val) and (val > 0)
+def IsNegInf(val):
+  return isinf(val) and (val < 0)
 
 class MessageTest(unittest.TestCase):
 
@@ -57,6 +71,8 @@
     golden_message.ParseFromString(golden_data)
     test_util.ExpectAllFieldsSet(self, golden_message)
     self.assertTrue(golden_message.SerializeToString() == golden_data)
+    golden_copy = copy.deepcopy(golden_message)
+    self.assertTrue(golden_copy.SerializeToString() == golden_data)
 
   def testGoldenExtensions(self):
     golden_data = test_util.GoldenFile('golden_message').read()
@@ -66,6 +82,8 @@
     test_util.SetAllExtensions(all_set)
     self.assertEquals(all_set, golden_message)
     self.assertTrue(golden_message.SerializeToString() == golden_data)
+    golden_copy = copy.deepcopy(golden_message)
+    self.assertTrue(golden_copy.SerializeToString() == golden_data)
 
   def testGoldenPackedMessage(self):
     golden_data = test_util.GoldenFile('golden_packed_fields_message').read()
@@ -75,6 +93,8 @@
     test_util.SetAllPackedFields(all_set)
     self.assertEquals(all_set, golden_message)
     self.assertTrue(all_set.SerializeToString() == golden_data)
+    golden_copy = copy.deepcopy(golden_message)
+    self.assertTrue(golden_copy.SerializeToString() == golden_data)
 
   def testGoldenPackedExtensions(self):
     golden_data = test_util.GoldenFile('golden_packed_fields_message').read()
@@ -84,6 +104,240 @@
     test_util.SetAllPackedExtensions(all_set)
     self.assertEquals(all_set, golden_message)
     self.assertTrue(all_set.SerializeToString() == golden_data)
+    golden_copy = copy.deepcopy(golden_message)
+    self.assertTrue(golden_copy.SerializeToString() == golden_data)
+
+  def testPositiveInfinity(self):
+    golden_data = ('\x5D\x00\x00\x80\x7F'
+                   '\x61\x00\x00\x00\x00\x00\x00\xF0\x7F'
+                   '\xCD\x02\x00\x00\x80\x7F'
+                   '\xD1\x02\x00\x00\x00\x00\x00\x00\xF0\x7F')
+    golden_message = unittest_pb2.TestAllTypes()
+    golden_message.ParseFromString(golden_data)
+    self.assertTrue(IsPosInf(golden_message.optional_float))
+    self.assertTrue(IsPosInf(golden_message.optional_double))
+    self.assertTrue(IsPosInf(golden_message.repeated_float[0]))
+    self.assertTrue(IsPosInf(golden_message.repeated_double[0]))
+    self.assertTrue(golden_message.SerializeToString() == golden_data)
+
+  def testNegativeInfinity(self):
+    golden_data = ('\x5D\x00\x00\x80\xFF'
+                   '\x61\x00\x00\x00\x00\x00\x00\xF0\xFF'
+                   '\xCD\x02\x00\x00\x80\xFF'
+                   '\xD1\x02\x00\x00\x00\x00\x00\x00\xF0\xFF')
+    golden_message = unittest_pb2.TestAllTypes()
+    golden_message.ParseFromString(golden_data)
+    self.assertTrue(IsNegInf(golden_message.optional_float))
+    self.assertTrue(IsNegInf(golden_message.optional_double))
+    self.assertTrue(IsNegInf(golden_message.repeated_float[0]))
+    self.assertTrue(IsNegInf(golden_message.repeated_double[0]))
+    self.assertTrue(golden_message.SerializeToString() == golden_data)
+
+  def testNotANumber(self):
+    golden_data = ('\x5D\x00\x00\xC0\x7F'
+                   '\x61\x00\x00\x00\x00\x00\x00\xF8\x7F'
+                   '\xCD\x02\x00\x00\xC0\x7F'
+                   '\xD1\x02\x00\x00\x00\x00\x00\x00\xF8\x7F')
+    golden_message = unittest_pb2.TestAllTypes()
+    golden_message.ParseFromString(golden_data)
+    self.assertTrue(isnan(golden_message.optional_float))
+    self.assertTrue(isnan(golden_message.optional_double))
+    self.assertTrue(isnan(golden_message.repeated_float[0]))
+    self.assertTrue(isnan(golden_message.repeated_double[0]))
+    self.assertTrue(golden_message.SerializeToString() == golden_data)
+
+  def testPositiveInfinityPacked(self):
+    golden_data = ('\xA2\x06\x04\x00\x00\x80\x7F'
+                   '\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF0\x7F')
+    golden_message = unittest_pb2.TestPackedTypes()
+    golden_message.ParseFromString(golden_data)
+    self.assertTrue(IsPosInf(golden_message.packed_float[0]))
+    self.assertTrue(IsPosInf(golden_message.packed_double[0]))
+    self.assertTrue(golden_message.SerializeToString() == golden_data)
+
+  def testNegativeInfinityPacked(self):
+    golden_data = ('\xA2\x06\x04\x00\x00\x80\xFF'
+                   '\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF0\xFF')
+    golden_message = unittest_pb2.TestPackedTypes()
+    golden_message.ParseFromString(golden_data)
+    self.assertTrue(IsNegInf(golden_message.packed_float[0]))
+    self.assertTrue(IsNegInf(golden_message.packed_double[0]))
+    self.assertTrue(golden_message.SerializeToString() == golden_data)
+
+  def testNotANumberPacked(self):
+    golden_data = ('\xA2\x06\x04\x00\x00\xC0\x7F'
+                   '\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF8\x7F')
+    golden_message = unittest_pb2.TestPackedTypes()
+    golden_message.ParseFromString(golden_data)
+    self.assertTrue(isnan(golden_message.packed_float[0]))
+    self.assertTrue(isnan(golden_message.packed_double[0]))
+    self.assertTrue(golden_message.SerializeToString() == golden_data)
+
+  def testExtremeFloatValues(self):
+    message = unittest_pb2.TestAllTypes()
+
+    # Most positive exponent, no significand bits set.
+    kMostPosExponentNoSigBits = math.pow(2, 127)
+    message.optional_float = kMostPosExponentNoSigBits
+    message.ParseFromString(message.SerializeToString())
+    self.assertTrue(message.optional_float == kMostPosExponentNoSigBits)
+
+    # Most positive exponent, one significand bit set.
+    kMostPosExponentOneSigBit = 1.5 * math.pow(2, 127)
+    message.optional_float = kMostPosExponentOneSigBit
+    message.ParseFromString(message.SerializeToString())
+    self.assertTrue(message.optional_float == kMostPosExponentOneSigBit)
+
+    # Repeat last two cases with values of same magnitude, but negative.
+    message.optional_float = -kMostPosExponentNoSigBits
+    message.ParseFromString(message.SerializeToString())
+    self.assertTrue(message.optional_float == -kMostPosExponentNoSigBits)
+
+    message.optional_float = -kMostPosExponentOneSigBit
+    message.ParseFromString(message.SerializeToString())
+    self.assertTrue(message.optional_float == -kMostPosExponentOneSigBit)
+
+    # Most negative exponent, no significand bits set.
+    kMostNegExponentNoSigBits = math.pow(2, -127)
+    message.optional_float = kMostNegExponentNoSigBits
+    message.ParseFromString(message.SerializeToString())
+    self.assertTrue(message.optional_float == kMostNegExponentNoSigBits)
+
+    # Most negative exponent, one significand bit set.
+    kMostNegExponentOneSigBit = 1.5 * math.pow(2, -127)
+    message.optional_float = kMostNegExponentOneSigBit
+    message.ParseFromString(message.SerializeToString())
+    self.assertTrue(message.optional_float == kMostNegExponentOneSigBit)
+
+    # Repeat last two cases with values of the same magnitude, but negative.
+    message.optional_float = -kMostNegExponentNoSigBits
+    message.ParseFromString(message.SerializeToString())
+    self.assertTrue(message.optional_float == -kMostNegExponentNoSigBits)
+
+    message.optional_float = -kMostNegExponentOneSigBit
+    message.ParseFromString(message.SerializeToString())
+    self.assertTrue(message.optional_float == -kMostNegExponentOneSigBit)
+
+  def testExtremeFloatValues(self):
+    message = unittest_pb2.TestAllTypes()
+
+    # Most positive exponent, no significand bits set.
+    kMostPosExponentNoSigBits = math.pow(2, 1023)
+    message.optional_double = kMostPosExponentNoSigBits
+    message.ParseFromString(message.SerializeToString())
+    self.assertTrue(message.optional_double == kMostPosExponentNoSigBits)
+
+    # Most positive exponent, one significand bit set.
+    kMostPosExponentOneSigBit = 1.5 * math.pow(2, 1023)
+    message.optional_double = kMostPosExponentOneSigBit
+    message.ParseFromString(message.SerializeToString())
+    self.assertTrue(message.optional_double == kMostPosExponentOneSigBit)
+
+    # Repeat last two cases with values of same magnitude, but negative.
+    message.optional_double = -kMostPosExponentNoSigBits
+    message.ParseFromString(message.SerializeToString())
+    self.assertTrue(message.optional_double == -kMostPosExponentNoSigBits)
+
+    message.optional_double = -kMostPosExponentOneSigBit
+    message.ParseFromString(message.SerializeToString())
+    self.assertTrue(message.optional_double == -kMostPosExponentOneSigBit)
+
+    # Most negative exponent, no significand bits set.
+    kMostNegExponentNoSigBits = math.pow(2, -1023)
+    message.optional_double = kMostNegExponentNoSigBits
+    message.ParseFromString(message.SerializeToString())
+    self.assertTrue(message.optional_double == kMostNegExponentNoSigBits)
+
+    # Most negative exponent, one significand bit set.
+    kMostNegExponentOneSigBit = 1.5 * math.pow(2, -1023)
+    message.optional_double = kMostNegExponentOneSigBit
+    message.ParseFromString(message.SerializeToString())
+    self.assertTrue(message.optional_double == kMostNegExponentOneSigBit)
+
+    # Repeat last two cases with values of the same magnitude, but negative.
+    message.optional_double = -kMostNegExponentNoSigBits
+    message.ParseFromString(message.SerializeToString())
+    self.assertTrue(message.optional_double == -kMostNegExponentNoSigBits)
+
+    message.optional_double = -kMostNegExponentOneSigBit
+    message.ParseFromString(message.SerializeToString())
+    self.assertTrue(message.optional_double == -kMostNegExponentOneSigBit)
+
+  def testSortingRepeatedScalarFieldsDefaultComparator(self):
+    """Check some different types with the default comparator."""
+    message = unittest_pb2.TestAllTypes()
+
+    # TODO(mattp): would testing more scalar types strengthen test?
+    message.repeated_int32.append(1)
+    message.repeated_int32.append(3)
+    message.repeated_int32.append(2)
+    message.repeated_int32.sort()
+    self.assertEqual(message.repeated_int32[0], 1)
+    self.assertEqual(message.repeated_int32[1], 2)
+    self.assertEqual(message.repeated_int32[2], 3)
+
+    message.repeated_float.append(1.1)
+    message.repeated_float.append(1.3)
+    message.repeated_float.append(1.2)
+    message.repeated_float.sort()
+    self.assertAlmostEqual(message.repeated_float[0], 1.1)
+    self.assertAlmostEqual(message.repeated_float[1], 1.2)
+    self.assertAlmostEqual(message.repeated_float[2], 1.3)
+
+    message.repeated_string.append('a')
+    message.repeated_string.append('c')
+    message.repeated_string.append('b')
+    message.repeated_string.sort()
+    self.assertEqual(message.repeated_string[0], 'a')
+    self.assertEqual(message.repeated_string[1], 'b')
+    self.assertEqual(message.repeated_string[2], 'c')
+
+    message.repeated_bytes.append('a')
+    message.repeated_bytes.append('c')
+    message.repeated_bytes.append('b')
+    message.repeated_bytes.sort()
+    self.assertEqual(message.repeated_bytes[0], 'a')
+    self.assertEqual(message.repeated_bytes[1], 'b')
+    self.assertEqual(message.repeated_bytes[2], 'c')
+
+  def testSortingRepeatedScalarFieldsCustomComparator(self):
+    """Check some different types with custom comparator."""
+    message = unittest_pb2.TestAllTypes()
+
+    message.repeated_int32.append(-3)
+    message.repeated_int32.append(-2)
+    message.repeated_int32.append(-1)
+    message.repeated_int32.sort(lambda x,y: cmp(abs(x), abs(y)))
+    self.assertEqual(message.repeated_int32[0], -1)
+    self.assertEqual(message.repeated_int32[1], -2)
+    self.assertEqual(message.repeated_int32[2], -3)
+
+    message.repeated_string.append('aaa')
+    message.repeated_string.append('bb')
+    message.repeated_string.append('c')
+    message.repeated_string.sort(lambda x,y: cmp(len(x), len(y)))
+    self.assertEqual(message.repeated_string[0], 'c')
+    self.assertEqual(message.repeated_string[1], 'bb')
+    self.assertEqual(message.repeated_string[2], 'aaa')
+
+  def testSortingRepeatedCompositeFieldsCustomComparator(self):
+    """Check passing a custom comparator to sort a repeated composite field."""
+    message = unittest_pb2.TestAllTypes()
+
+    message.repeated_nested_message.add().bb = 1
+    message.repeated_nested_message.add().bb = 3
+    message.repeated_nested_message.add().bb = 2
+    message.repeated_nested_message.add().bb = 6
+    message.repeated_nested_message.add().bb = 5
+    message.repeated_nested_message.add().bb = 4
+    message.repeated_nested_message.sort(lambda x,y: cmp(x.bb, y.bb))
+    self.assertEqual(message.repeated_nested_message[0].bb, 1)
+    self.assertEqual(message.repeated_nested_message[1].bb, 2)
+    self.assertEqual(message.repeated_nested_message[2].bb, 3)
+    self.assertEqual(message.repeated_nested_message[3].bb, 4)
+    self.assertEqual(message.repeated_nested_message[4].bb, 5)
+    self.assertEqual(message.repeated_nested_message[5].bb, 6)
+
 
 if __name__ == '__main__':
   unittest.main()
diff --git a/python/google/protobuf/internal/python_message.py b/python/google/protobuf/internal/python_message.py
new file mode 100755
index 0000000..66fca91
--- /dev/null
+++ b/python/google/protobuf/internal/python_message.py
@@ -0,0 +1,1098 @@
+# Protocol Buffers - Google's data interchange format
+# Copyright 2008 Google Inc.  All rights reserved.
+# http://code.google.com/p/protobuf/
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# This code is meant to work on Python 2.4 and above only.
+#
+# TODO(robinson): Helpers for verbose, common checks like seeing if a
+# descriptor's cpp_type is CPPTYPE_MESSAGE.
+
+"""Contains a metaclass and helper functions used to create
+protocol message classes from Descriptor objects at runtime.
+
+Recall that a metaclass is the "type" of a class.
+(A class is to a metaclass what an instance is to a class.)
+
+In this case, we use the GeneratedProtocolMessageType metaclass
+to inject all the useful functionality into the classes
+output by the protocol compiler at compile-time.
+
+The upshot of all this is that the real implementation
+details for ALL pure-Python protocol buffers are *here in
+this file*.
+"""
+
+__author__ = 'robinson@google.com (Will Robinson)'
+
+try:
+  from cStringIO import StringIO
+except ImportError:
+  from StringIO import StringIO
+import struct
+import weakref
+
+# We use "as" to avoid name collisions with variables.
+from google.protobuf.internal import containers
+from google.protobuf.internal import decoder
+from google.protobuf.internal import encoder
+from google.protobuf.internal import message_listener as message_listener_mod
+from google.protobuf.internal import type_checkers
+from google.protobuf.internal import wire_format
+from google.protobuf import descriptor as descriptor_mod
+from google.protobuf import message as message_mod
+from google.protobuf import text_format
+
+_FieldDescriptor = descriptor_mod.FieldDescriptor
+
+
+def NewMessage(descriptor, dictionary):
+  _AddClassAttributesForNestedExtensions(descriptor, dictionary)
+  _AddSlots(descriptor, dictionary)
+
+
+def InitMessage(descriptor, cls):
+  cls._decoders_by_tag = {}
+  cls._extensions_by_name = {}
+  cls._extensions_by_number = {}
+  if (descriptor.has_options and
+      descriptor.GetOptions().message_set_wire_format):
+    cls._decoders_by_tag[decoder.MESSAGE_SET_ITEM_TAG] = (
+        decoder.MessageSetItemDecoder(cls._extensions_by_number))
+
+  # Attach stuff to each FieldDescriptor for quick lookup later on.
+  for field in descriptor.fields:
+    _AttachFieldHelpers(cls, field)
+
+  _AddEnumValues(descriptor, cls)
+  _AddInitMethod(descriptor, cls)
+  _AddPropertiesForFields(descriptor, cls)
+  _AddPropertiesForExtensions(descriptor, cls)
+  _AddStaticMethods(cls)
+  _AddMessageMethods(descriptor, cls)
+  _AddPrivateHelperMethods(cls)
+
+
+# Stateless helpers for GeneratedProtocolMessageType below.
+# Outside clients should not access these directly.
+#
+# I opted not to make any of these methods on the metaclass, to make it more
+# clear that I'm not really using any state there and to keep clients from
+# thinking that they have direct access to these construction helpers.
+
+
+def _PropertyName(proto_field_name):
+  """Returns the name of the public property attribute which
+  clients can use to get and (in some cases) set the value
+  of a protocol message field.
+
+  Args:
+    proto_field_name: The protocol message field name, exactly
+      as it appears (or would appear) in a .proto file.
+  """
+  # TODO(robinson): Escape Python keywords (e.g., yield), and test this support.
+  # nnorwitz makes my day by writing:
+  # """
+  # FYI.  See the keyword module in the stdlib. This could be as simple as:
+  #
+  # if keyword.iskeyword(proto_field_name):
+  #   return proto_field_name + "_"
+  # return proto_field_name
+  # """
+  # Kenton says:  The above is a BAD IDEA.  People rely on being able to use
+  #   getattr() and setattr() to reflectively manipulate field values.  If we
+  #   rename the properties, then every such user has to also make sure to apply
+  #   the same transformation.  Note that currently if you name a field "yield",
+  #   you can still access it just fine using getattr/setattr -- it's not even
+  #   that cumbersome to do so.
+  # TODO(kenton):  Remove this method entirely if/when everyone agrees with my
+  #   position.
+  return proto_field_name
+
+
+def _VerifyExtensionHandle(message, extension_handle):
+  """Verify that the given extension handle is valid."""
+
+  if not isinstance(extension_handle, _FieldDescriptor):
+    raise KeyError('HasExtension() expects an extension handle, got: %s' %
+                   extension_handle)
+
+  if not extension_handle.is_extension:
+    raise KeyError('"%s" is not an extension.' % extension_handle.full_name)
+
+  if extension_handle.containing_type is not message.DESCRIPTOR:
+    raise KeyError('Extension "%s" extends message type "%s", but this '
+                   'message is of type "%s".' %
+                   (extension_handle.full_name,
+                    extension_handle.containing_type.full_name,
+                    message.DESCRIPTOR.full_name))
+
+
+def _AddSlots(message_descriptor, dictionary):
+  """Adds a __slots__ entry to dictionary, containing the names of all valid
+  attributes for this message type.
+
+  Args:
+    message_descriptor: A Descriptor instance describing this message type.
+    dictionary: Class dictionary to which we'll add a '__slots__' entry.
+  """
+  dictionary['__slots__'] = ['_cached_byte_size',
+                             '_cached_byte_size_dirty',
+                             '_fields',
+                             '_is_present_in_parent',
+                             '_listener',
+                             '_listener_for_children',
+                             '__weakref__']
+
+
+def _IsMessageSetExtension(field):
+  return (field.is_extension and
+          field.containing_type.has_options and
+          field.containing_type.GetOptions().message_set_wire_format and
+          field.type == _FieldDescriptor.TYPE_MESSAGE and
+          field.message_type == field.extension_scope and
+          field.label == _FieldDescriptor.LABEL_OPTIONAL)
+
+
+def _AttachFieldHelpers(cls, field_descriptor):
+  is_repeated = (field_descriptor.label == _FieldDescriptor.LABEL_REPEATED)
+  is_packed = (field_descriptor.has_options and
+               field_descriptor.GetOptions().packed)
+
+  if _IsMessageSetExtension(field_descriptor):
+    field_encoder = encoder.MessageSetItemEncoder(field_descriptor.number)
+    sizer = encoder.MessageSetItemSizer(field_descriptor.number)
+  else:
+    field_encoder = type_checkers.TYPE_TO_ENCODER[field_descriptor.type](
+        field_descriptor.number, is_repeated, is_packed)
+    sizer = type_checkers.TYPE_TO_SIZER[field_descriptor.type](
+        field_descriptor.number, is_repeated, is_packed)
+
+  field_descriptor._encoder = field_encoder
+  field_descriptor._sizer = sizer
+  field_descriptor._default_constructor = _DefaultValueConstructorForField(
+      field_descriptor)
+
+  def AddDecoder(wiretype, is_packed):
+    tag_bytes = encoder.TagBytes(field_descriptor.number, wiretype)
+    cls._decoders_by_tag[tag_bytes] = (
+        type_checkers.TYPE_TO_DECODER[field_descriptor.type](
+            field_descriptor.number, is_repeated, is_packed,
+            field_descriptor, field_descriptor._default_constructor))
+
+  AddDecoder(type_checkers.FIELD_TYPE_TO_WIRE_TYPE[field_descriptor.type],
+             False)
+
+  if is_repeated and wire_format.IsTypePackable(field_descriptor.type):
+    # To support wire compatibility of adding packed = true, add a decoder for
+    # packed values regardless of the field's options.
+    AddDecoder(wire_format.WIRETYPE_LENGTH_DELIMITED, True)
+
+
+def _AddClassAttributesForNestedExtensions(descriptor, dictionary):
+  extension_dict = descriptor.extensions_by_name
+  for extension_name, extension_field in extension_dict.iteritems():
+    assert extension_name not in dictionary
+    dictionary[extension_name] = extension_field
+
+
+def _AddEnumValues(descriptor, cls):
+  """Sets class-level attributes for all enum fields defined in this message.
+
+  Args:
+    descriptor: Descriptor object for this message type.
+    cls: Class we're constructing for this message type.
+  """
+  for enum_type in descriptor.enum_types:
+    for enum_value in enum_type.values:
+      setattr(cls, enum_value.name, enum_value.number)
+
+
+def _DefaultValueConstructorForField(field):
+  """Returns a function which returns a default value for a field.
+
+  Args:
+    field: FieldDescriptor object for this field.
+
+  The returned function has one argument:
+    message: Message instance containing this field, or a weakref proxy
+      of same.
+
+  That function in turn returns a default value for this field.  The default
+    value may refer back to |message| via a weak reference.
+  """
+
+  if field.label == _FieldDescriptor.LABEL_REPEATED:
+    if field.default_value != []:
+      raise ValueError('Repeated field default value not empty list: %s' % (
+          field.default_value))
+    if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
+      # We can't look at _concrete_class yet since it might not have
+      # been set.  (Depends on order in which we initialize the classes).
+      message_type = field.message_type
+      def MakeRepeatedMessageDefault(message):
+        return containers.RepeatedCompositeFieldContainer(
+            message._listener_for_children, field.message_type)
+      return MakeRepeatedMessageDefault
+    else:
+      type_checker = type_checkers.GetTypeChecker(field.cpp_type, field.type)
+      def MakeRepeatedScalarDefault(message):
+        return containers.RepeatedScalarFieldContainer(
+            message._listener_for_children, type_checker)
+      return MakeRepeatedScalarDefault
+
+  if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
+    # _concrete_class may not yet be initialized.
+    message_type = field.message_type
+    def MakeSubMessageDefault(message):
+      result = message_type._concrete_class()
+      result._SetListener(message._listener_for_children)
+      return result
+    return MakeSubMessageDefault
+
+  def MakeScalarDefault(message):
+    return field.default_value
+  return MakeScalarDefault
+
+
+def _AddInitMethod(message_descriptor, cls):
+  """Adds an __init__ method to cls."""
+  fields = message_descriptor.fields
+  def init(self, **kwargs):
+    self._cached_byte_size = 0
+    self._cached_byte_size_dirty = len(kwargs) > 0
+    self._fields = {}
+    self._is_present_in_parent = False
+    self._listener = message_listener_mod.NullMessageListener()
+    self._listener_for_children = _Listener(self)
+    for field_name, field_value in kwargs.iteritems():
+      field = _GetFieldByName(message_descriptor, field_name)
+      if field is None:
+        raise TypeError("%s() got an unexpected keyword argument '%s'" %
+                        (message_descriptor.name, field_name))
+      if field.label == _FieldDescriptor.LABEL_REPEATED:
+        copy = field._default_constructor(self)
+        if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:  # Composite
+          for val in field_value:
+            copy.add().MergeFrom(val)
+        else:  # Scalar
+          copy.extend(field_value)
+        self._fields[field] = copy
+      elif field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
+        copy = field._default_constructor(self)
+        copy.MergeFrom(field_value)
+        self._fields[field] = copy
+      else:
+        setattr(self, field_name, field_value)
+
+  init.__module__ = None
+  init.__doc__ = None
+  cls.__init__ = init
+
+
+def _GetFieldByName(message_descriptor, field_name):
+  """Returns a field descriptor by field name.
+
+  Args:
+    message_descriptor: A Descriptor describing all fields in message.
+    field_name: The name of the field to retrieve.
+  Returns:
+    The field descriptor associated with the field name.
+  """
+  try:
+    return message_descriptor.fields_by_name[field_name]
+  except KeyError:
+    raise ValueError('Protocol message has no "%s" field.' % field_name)
+
+
+def _AddPropertiesForFields(descriptor, cls):
+  """Adds properties for all fields in this protocol message type."""
+  for field in descriptor.fields:
+    _AddPropertiesForField(field, cls)
+
+  if descriptor.is_extendable:
+    # _ExtensionDict is just an adaptor with no state so we allocate a new one
+    # every time it is accessed.
+    cls.Extensions = property(lambda self: _ExtensionDict(self))
+
+
+def _AddPropertiesForField(field, cls):
+  """Adds a public property for a protocol message field.
+  Clients can use this property to get and (in the case
+  of non-repeated scalar fields) directly set the value
+  of a protocol message field.
+
+  Args:
+    field: A FieldDescriptor for this field.
+    cls: The class we're constructing.
+  """
+  # Catch it if we add other types that we should
+  # handle specially here.
+  assert _FieldDescriptor.MAX_CPPTYPE == 10
+
+  constant_name = field.name.upper() + "_FIELD_NUMBER"
+  setattr(cls, constant_name, field.number)
+
+  if field.label == _FieldDescriptor.LABEL_REPEATED:
+    _AddPropertiesForRepeatedField(field, cls)
+  elif field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
+    _AddPropertiesForNonRepeatedCompositeField(field, cls)
+  else:
+    _AddPropertiesForNonRepeatedScalarField(field, cls)
+
+
+def _AddPropertiesForRepeatedField(field, cls):
+  """Adds a public property for a "repeated" protocol message field.  Clients
+  can use this property to get the value of the field, which will be either a
+  _RepeatedScalarFieldContainer or _RepeatedCompositeFieldContainer (see
+  below).
+
+  Note that when clients add values to these containers, we perform
+  type-checking in the case of repeated scalar fields, and we also set any
+  necessary "has" bits as a side-effect.
+
+  Args:
+    field: A FieldDescriptor for this field.
+    cls: The class we're constructing.
+  """
+  proto_field_name = field.name
+  property_name = _PropertyName(proto_field_name)
+
+  def getter(self):
+    field_value = self._fields.get(field)
+    if field_value is None:
+      # Construct a new object to represent this field.
+      field_value = field._default_constructor(self)
+
+      # Atomically check if another thread has preempted us and, if not, swap
+      # in the new object we just created.  If someone has preempted us, we
+      # take that object and discard ours.
+      # WARNING:  We are relying on setdefault() being atomic.  This is true
+      #   in CPython but we haven't investigated others.  This warning appears
+      #   in several other locations in this file.
+      field_value = self._fields.setdefault(field, field_value)
+    return field_value
+  getter.__module__ = None
+  getter.__doc__ = 'Getter for %s.' % proto_field_name
+
+  # We define a setter just so we can throw an exception with a more
+  # helpful error message.
+  def setter(self, new_value):
+    raise AttributeError('Assignment not allowed to repeated field '
+                         '"%s" in protocol message object.' % proto_field_name)
+
+  doc = 'Magic attribute generated for "%s" proto field.' % proto_field_name
+  setattr(cls, property_name, property(getter, setter, doc=doc))
+
+
+def _AddPropertiesForNonRepeatedScalarField(field, cls):
+  """Adds a public property for a nonrepeated, scalar protocol message field.
+  Clients can use this property to get and directly set the value of the field.
+  Note that when the client sets the value of a field by using this property,
+  all necessary "has" bits are set as a side-effect, and we also perform
+  type-checking.
+
+  Args:
+    field: A FieldDescriptor for this field.
+    cls: The class we're constructing.
+  """
+  proto_field_name = field.name
+  property_name = _PropertyName(proto_field_name)
+  type_checker = type_checkers.GetTypeChecker(field.cpp_type, field.type)
+  default_value = field.default_value
+  valid_values = set()
+
+  def getter(self):
+    return self._fields.get(field, default_value)
+  getter.__module__ = None
+  getter.__doc__ = 'Getter for %s.' % proto_field_name
+  def setter(self, new_value):
+    type_checker.CheckValue(new_value)
+    self._fields[field] = new_value
+    # Check _cached_byte_size_dirty inline to improve performance, since scalar
+    # setters are called frequently.
+    if not self._cached_byte_size_dirty:
+      self._Modified()
+
+  setter.__module__ = None
+  setter.__doc__ = 'Setter for %s.' % proto_field_name
+
+  # Add a property to encapsulate the getter/setter.
+  doc = 'Magic attribute generated for "%s" proto field.' % proto_field_name
+  setattr(cls, property_name, property(getter, setter, doc=doc))
+
+
+def _AddPropertiesForNonRepeatedCompositeField(field, cls):
+  """Adds a public property for a nonrepeated, composite protocol message field.
+  A composite field is a "group" or "message" field.
+
+  Clients can use this property to get the value of the field, but cannot
+  assign to the property directly.
+
+  Args:
+    field: A FieldDescriptor for this field.
+    cls: The class we're constructing.
+  """
+  # TODO(robinson): Remove duplication with similar method
+  # for non-repeated scalars.
+  proto_field_name = field.name
+  property_name = _PropertyName(proto_field_name)
+  message_type = field.message_type
+
+  def getter(self):
+    field_value = self._fields.get(field)
+    if field_value is None:
+      # Construct a new object to represent this field.
+      field_value = message_type._concrete_class()
+      field_value._SetListener(self._listener_for_children)
+
+      # Atomically check if another thread has preempted us and, if not, swap
+      # in the new object we just created.  If someone has preempted us, we
+      # take that object and discard ours.
+      # WARNING:  We are relying on setdefault() being atomic.  This is true
+      #   in CPython but we haven't investigated others.  This warning appears
+      #   in several other locations in this file.
+      field_value = self._fields.setdefault(field, field_value)
+    return field_value
+  getter.__module__ = None
+  getter.__doc__ = 'Getter for %s.' % proto_field_name
+
+  # We define a setter just so we can throw an exception with a more
+  # helpful error message.
+  def setter(self, new_value):
+    raise AttributeError('Assignment not allowed to composite field '
+                         '"%s" in protocol message object.' % proto_field_name)
+
+  # Add a property to encapsulate the getter.
+  doc = 'Magic attribute generated for "%s" proto field.' % proto_field_name
+  setattr(cls, property_name, property(getter, setter, doc=doc))
+
+
+def _AddPropertiesForExtensions(descriptor, cls):
+  """Adds properties for all fields in this protocol message type."""
+  extension_dict = descriptor.extensions_by_name
+  for extension_name, extension_field in extension_dict.iteritems():
+    constant_name = extension_name.upper() + "_FIELD_NUMBER"
+    setattr(cls, constant_name, extension_field.number)
+
+
+def _AddStaticMethods(cls):
+  # TODO(robinson): This probably needs to be thread-safe(?)
+  def RegisterExtension(extension_handle):
+    extension_handle.containing_type = cls.DESCRIPTOR
+    _AttachFieldHelpers(cls, extension_handle)
+
+    # Try to insert our extension, failing if an extension with the same number
+    # already exists.
+    actual_handle = cls._extensions_by_number.setdefault(
+        extension_handle.number, extension_handle)
+    if actual_handle is not extension_handle:
+      raise AssertionError(
+          'Extensions "%s" and "%s" both try to extend message type "%s" with '
+          'field number %d.' %
+          (extension_handle.full_name, actual_handle.full_name,
+           cls.DESCRIPTOR.full_name, extension_handle.number))
+
+    cls._extensions_by_name[extension_handle.full_name] = extension_handle
+
+    handle = extension_handle  # avoid line wrapping
+    if _IsMessageSetExtension(handle):
+      # MessageSet extension.  Also register under type name.
+      cls._extensions_by_name[
+          extension_handle.message_type.full_name] = extension_handle
+
+  cls.RegisterExtension = staticmethod(RegisterExtension)
+
+  def FromString(s):
+    message = cls()
+    message.MergeFromString(s)
+    return message
+  cls.FromString = staticmethod(FromString)
+
+
+def _IsPresent(item):
+  """Given a (FieldDescriptor, value) tuple from _fields, return true if the
+  value should be included in the list returned by ListFields()."""
+
+  if item[0].label == _FieldDescriptor.LABEL_REPEATED:
+    return bool(item[1])
+  elif item[0].cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
+    return item[1]._is_present_in_parent
+  else:
+    return True
+
+
+def _AddListFieldsMethod(message_descriptor, cls):
+  """Helper for _AddMessageMethods()."""
+
+  def ListFields(self):
+    all_fields = [item for item in self._fields.iteritems() if _IsPresent(item)]
+    all_fields.sort(key = lambda item: item[0].number)
+    return all_fields
+
+  cls.ListFields = ListFields
+
+
+def _AddHasFieldMethod(message_descriptor, cls):
+  """Helper for _AddMessageMethods()."""
+
+  singular_fields = {}
+  for field in message_descriptor.fields:
+    if field.label != _FieldDescriptor.LABEL_REPEATED:
+      singular_fields[field.name] = field
+
+  def HasField(self, field_name):
+    try:
+      field = singular_fields[field_name]
+    except KeyError:
+      raise ValueError(
+          'Protocol message has no singular "%s" field.' % field_name)
+
+    if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
+      value = self._fields.get(field)
+      return value is not None and value._is_present_in_parent
+    else:
+      return field in self._fields
+  cls.HasField = HasField
+
+
+def _AddClearFieldMethod(message_descriptor, cls):
+  """Helper for _AddMessageMethods()."""
+  def ClearField(self, field_name):
+    try:
+      field = message_descriptor.fields_by_name[field_name]
+    except KeyError:
+      raise ValueError('Protocol message has no "%s" field.' % field_name)
+
+    if field in self._fields:
+      # Note:  If the field is a sub-message, its listener will still point
+      #   at us.  That's fine, because the worst than can happen is that it
+      #   will call _Modified() and invalidate our byte size.  Big deal.
+      del self._fields[field]
+
+    # Always call _Modified() -- even if nothing was changed, this is
+    # a mutating method, and thus calling it should cause the field to become
+    # present in the parent message.
+    self._Modified()
+
+  cls.ClearField = ClearField
+
+
+def _AddClearExtensionMethod(cls):
+  """Helper for _AddMessageMethods()."""
+  def ClearExtension(self, extension_handle):
+    _VerifyExtensionHandle(self, extension_handle)
+
+    # Similar to ClearField(), above.
+    if extension_handle in self._fields:
+      del self._fields[extension_handle]
+    self._Modified()
+  cls.ClearExtension = ClearExtension
+
+
+def _AddClearMethod(message_descriptor, cls):
+  """Helper for _AddMessageMethods()."""
+  def Clear(self):
+    # Clear fields.
+    self._fields = {}
+    self._Modified()
+  cls.Clear = Clear
+
+
+def _AddHasExtensionMethod(cls):
+  """Helper for _AddMessageMethods()."""
+  def HasExtension(self, extension_handle):
+    _VerifyExtensionHandle(self, extension_handle)
+    if extension_handle.label == _FieldDescriptor.LABEL_REPEATED:
+      raise KeyError('"%s" is repeated.' % extension_handle.full_name)
+
+    if extension_handle.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
+      value = self._fields.get(extension_handle)
+      return value is not None and value._is_present_in_parent
+    else:
+      return extension_handle in self._fields
+  cls.HasExtension = HasExtension
+
+
+def _AddEqualsMethod(message_descriptor, cls):
+  """Helper for _AddMessageMethods()."""
+  def __eq__(self, other):
+    if (not isinstance(other, message_mod.Message) or
+        other.DESCRIPTOR != self.DESCRIPTOR):
+      return False
+
+    if self is other:
+      return True
+
+    return self.ListFields() == other.ListFields()
+
+  cls.__eq__ = __eq__
+
+
+def _AddStrMethod(message_descriptor, cls):
+  """Helper for _AddMessageMethods()."""
+  def __str__(self):
+    return text_format.MessageToString(self)
+  cls.__str__ = __str__
+
+
+def _AddUnicodeMethod(unused_message_descriptor, cls):
+  """Helper for _AddMessageMethods()."""
+
+  def __unicode__(self):
+    return text_format.MessageToString(self, as_utf8=True).decode('utf-8')
+  cls.__unicode__ = __unicode__
+
+
+def _AddSetListenerMethod(cls):
+  """Helper for _AddMessageMethods()."""
+  def SetListener(self, listener):
+    if listener is None:
+      self._listener = message_listener_mod.NullMessageListener()
+    else:
+      self._listener = listener
+  cls._SetListener = SetListener
+
+
+def _BytesForNonRepeatedElement(value, field_number, field_type):
+  """Returns the number of bytes needed to serialize a non-repeated element.
+  The returned byte count includes space for tag information and any
+  other additional space associated with serializing value.
+
+  Args:
+    value: Value we're serializing.
+    field_number: Field number of this value.  (Since the field number
+      is stored as part of a varint-encoded tag, this has an impact
+      on the total bytes required to serialize the value).
+    field_type: The type of the field.  One of the TYPE_* constants
+      within FieldDescriptor.
+  """
+  try:
+    fn = type_checkers.TYPE_TO_BYTE_SIZE_FN[field_type]
+    return fn(field_number, value)
+  except KeyError:
+    raise message_mod.EncodeError('Unrecognized field type: %d' % field_type)
+
+
+def _AddByteSizeMethod(message_descriptor, cls):
+  """Helper for _AddMessageMethods()."""
+
+  def ByteSize(self):
+    if not self._cached_byte_size_dirty:
+      return self._cached_byte_size
+
+    size = 0
+    for field_descriptor, field_value in self.ListFields():
+      size += field_descriptor._sizer(field_value)
+
+    self._cached_byte_size = size
+    self._cached_byte_size_dirty = False
+    self._listener_for_children.dirty = False
+    return size
+
+  cls.ByteSize = ByteSize
+
+
+def _AddSerializeToStringMethod(message_descriptor, cls):
+  """Helper for _AddMessageMethods()."""
+
+  def SerializeToString(self):
+    # Check if the message has all of its required fields set.
+    errors = []
+    if not self.IsInitialized():
+      raise message_mod.EncodeError(
+          'Message is missing required fields: ' +
+          ','.join(self.FindInitializationErrors()))
+    return self.SerializePartialToString()
+  cls.SerializeToString = SerializeToString
+
+
+def _AddSerializePartialToStringMethod(message_descriptor, cls):
+  """Helper for _AddMessageMethods()."""
+
+  def SerializePartialToString(self):
+    out = StringIO()
+    self._InternalSerialize(out.write)
+    return out.getvalue()
+  cls.SerializePartialToString = SerializePartialToString
+
+  def InternalSerialize(self, write_bytes):
+    for field_descriptor, field_value in self.ListFields():
+      field_descriptor._encoder(write_bytes, field_value)
+  cls._InternalSerialize = InternalSerialize
+
+
+def _AddMergeFromStringMethod(message_descriptor, cls):
+  """Helper for _AddMessageMethods()."""
+  def MergeFromString(self, serialized):
+    length = len(serialized)
+    try:
+      if self._InternalParse(serialized, 0, length) != length:
+        # The only reason _InternalParse would return early is if it
+        # encountered an end-group tag.
+        raise message_mod.DecodeError('Unexpected end-group tag.')
+    except IndexError:
+      raise message_mod.DecodeError('Truncated message.')
+    except struct.error, e:
+      raise message_mod.DecodeError(e)
+    return length   # Return this for legacy reasons.
+  cls.MergeFromString = MergeFromString
+
+  local_ReadTag = decoder.ReadTag
+  local_SkipField = decoder.SkipField
+  decoders_by_tag = cls._decoders_by_tag
+
+  def InternalParse(self, buffer, pos, end):
+    self._Modified()
+    field_dict = self._fields
+    while pos != end:
+      (tag_bytes, new_pos) = local_ReadTag(buffer, pos)
+      field_decoder = decoders_by_tag.get(tag_bytes)
+      if field_decoder is None:
+        new_pos = local_SkipField(buffer, new_pos, end, tag_bytes)
+        if new_pos == -1:
+          return pos
+        pos = new_pos
+      else:
+        pos = field_decoder(buffer, new_pos, end, self, field_dict)
+    return pos
+  cls._InternalParse = InternalParse
+
+
+def _AddIsInitializedMethod(message_descriptor, cls):
+  """Adds the IsInitialized and FindInitializationError methods to the
+  protocol message class."""
+
+  required_fields = [field for field in message_descriptor.fields
+                           if field.label == _FieldDescriptor.LABEL_REQUIRED]
+
+  def IsInitialized(self, errors=None):
+    """Checks if all required fields of a message are set.
+
+    Args:
+      errors:  A list which, if provided, will be populated with the field
+               paths of all missing required fields.
+
+    Returns:
+      True iff the specified message has all required fields set.
+    """
+
+    # Performance is critical so we avoid HasField() and ListFields().
+
+    for field in required_fields:
+      if (field not in self._fields or
+          (field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE and
+           not self._fields[field]._is_present_in_parent)):
+        if errors is not None:
+          errors.extend(self.FindInitializationErrors())
+        return False
+
+    for field, value in self._fields.iteritems():
+      if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
+        if field.label == _FieldDescriptor.LABEL_REPEATED:
+          for element in value:
+            if not element.IsInitialized():
+              if errors is not None:
+                errors.extend(self.FindInitializationErrors())
+              return False
+        elif value._is_present_in_parent and not value.IsInitialized():
+          if errors is not None:
+            errors.extend(self.FindInitializationErrors())
+          return False
+
+    return True
+
+  cls.IsInitialized = IsInitialized
+
+  def FindInitializationErrors(self):
+    """Finds required fields which are not initialized.
+
+    Returns:
+      A list of strings.  Each string is a path to an uninitialized field from
+      the top-level message, e.g. "foo.bar[5].baz".
+    """
+
+    errors = []  # simplify things
+
+    for field in required_fields:
+      if not self.HasField(field.name):
+        errors.append(field.name)
+
+    for field, value in self.ListFields():
+      if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
+        if field.is_extension:
+          name = "(%s)" % field.full_name
+        else:
+          name = field.name
+
+        if field.label == _FieldDescriptor.LABEL_REPEATED:
+          for i in xrange(len(value)):
+            element = value[i]
+            prefix = "%s[%d]." % (name, i)
+            sub_errors = element.FindInitializationErrors()
+            errors += [ prefix + error for error in sub_errors ]
+        else:
+          prefix = name + "."
+          sub_errors = value.FindInitializationErrors()
+          errors += [ prefix + error for error in sub_errors ]
+
+    return errors
+
+  cls.FindInitializationErrors = FindInitializationErrors
+
+
+def _AddMergeFromMethod(cls):
+  LABEL_REPEATED = _FieldDescriptor.LABEL_REPEATED
+  CPPTYPE_MESSAGE = _FieldDescriptor.CPPTYPE_MESSAGE
+
+  def MergeFrom(self, msg):
+    if not isinstance(msg, cls):
+      raise TypeError(
+          "Parameter to MergeFrom() must be instance of same class.")
+
+    assert msg is not self
+    self._Modified()
+
+    fields = self._fields
+
+    for field, value in msg._fields.iteritems():
+      if field.label == LABEL_REPEATED:
+        field_value = fields.get(field)
+        if field_value is None:
+          # Construct a new object to represent this field.
+          field_value = field._default_constructor(self)
+          fields[field] = field_value
+        field_value.MergeFrom(value)
+      elif field.cpp_type == CPPTYPE_MESSAGE:
+        if value._is_present_in_parent:
+          field_value = fields.get(field)
+          if field_value is None:
+            # Construct a new object to represent this field.
+            field_value = field._default_constructor(self)
+            fields[field] = field_value
+          field_value.MergeFrom(value)
+      else:
+        self._fields[field] = value
+  cls.MergeFrom = MergeFrom
+
+
+def _AddMessageMethods(message_descriptor, cls):
+  """Adds implementations of all Message methods to cls."""
+  _AddListFieldsMethod(message_descriptor, cls)
+  _AddHasFieldMethod(message_descriptor, cls)
+  _AddClearFieldMethod(message_descriptor, cls)
+  if message_descriptor.is_extendable:
+    _AddClearExtensionMethod(cls)
+    _AddHasExtensionMethod(cls)
+  _AddClearMethod(message_descriptor, cls)
+  _AddEqualsMethod(message_descriptor, cls)
+  _AddStrMethod(message_descriptor, cls)
+  _AddUnicodeMethod(message_descriptor, cls)
+  _AddSetListenerMethod(cls)
+  _AddByteSizeMethod(message_descriptor, cls)
+  _AddSerializeToStringMethod(message_descriptor, cls)
+  _AddSerializePartialToStringMethod(message_descriptor, cls)
+  _AddMergeFromStringMethod(message_descriptor, cls)
+  _AddIsInitializedMethod(message_descriptor, cls)
+  _AddMergeFromMethod(cls)
+
+
+def _AddPrivateHelperMethods(cls):
+  """Adds implementation of private helper methods to cls."""
+
+  def Modified(self):
+    """Sets the _cached_byte_size_dirty bit to true,
+    and propagates this to our listener iff this was a state change.
+    """
+
+    # Note:  Some callers check _cached_byte_size_dirty before calling
+    #   _Modified() as an extra optimization.  So, if this method is ever
+    #   changed such that it does stuff even when _cached_byte_size_dirty is
+    #   already true, the callers need to be updated.
+    if not self._cached_byte_size_dirty:
+      self._cached_byte_size_dirty = True
+      self._listener_for_children.dirty = True
+      self._is_present_in_parent = True
+      self._listener.Modified()
+
+  cls._Modified = Modified
+  cls.SetInParent = Modified
+
+
+class _Listener(object):
+
+  """MessageListener implementation that a parent message registers with its
+  child message.
+
+  In order to support semantics like:
+
+    foo.bar.baz.qux = 23
+    assert foo.HasField('bar')
+
+  ...child objects must have back references to their parents.
+  This helper class is at the heart of this support.
+  """
+
+  def __init__(self, parent_message):
+    """Args:
+      parent_message: The message whose _Modified() method we should call when
+        we receive Modified() messages.
+    """
+    # This listener establishes a back reference from a child (contained) object
+    # to its parent (containing) object.  We make this a weak reference to avoid
+    # creating cyclic garbage when the client finishes with the 'parent' object
+    # in the tree.
+    if isinstance(parent_message, weakref.ProxyType):
+      self._parent_message_weakref = parent_message
+    else:
+      self._parent_message_weakref = weakref.proxy(parent_message)
+
+    # As an optimization, we also indicate directly on the listener whether
+    # or not the parent message is dirty.  This way we can avoid traversing
+    # up the tree in the common case.
+    self.dirty = False
+
+  def Modified(self):
+    if self.dirty:
+      return
+    try:
+      # Propagate the signal to our parents iff this is the first field set.
+      self._parent_message_weakref._Modified()
+    except ReferenceError:
+      # We can get here if a client has kept a reference to a child object,
+      # and is now setting a field on it, but the child's parent has been
+      # garbage-collected.  This is not an error.
+      pass
+
+
+# TODO(robinson): Move elsewhere?  This file is getting pretty ridiculous...
+# TODO(robinson): Unify error handling of "unknown extension" crap.
+# TODO(robinson): Support iteritems()-style iteration over all
+# extensions with the "has" bits turned on?
+class _ExtensionDict(object):
+
+  """Dict-like container for supporting an indexable "Extensions"
+  field on proto instances.
+
+  Note that in all cases we expect extension handles to be
+  FieldDescriptors.
+  """
+
+  def __init__(self, extended_message):
+    """extended_message: Message instance for which we are the Extensions dict.
+    """
+
+    self._extended_message = extended_message
+
+  def __getitem__(self, extension_handle):
+    """Returns the current value of the given extension handle."""
+
+    _VerifyExtensionHandle(self._extended_message, extension_handle)
+
+    result = self._extended_message._fields.get(extension_handle)
+    if result is not None:
+      return result
+
+    if extension_handle.label == _FieldDescriptor.LABEL_REPEATED:
+      result = extension_handle._default_constructor(self._extended_message)
+    elif extension_handle.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
+      result = extension_handle.message_type._concrete_class()
+      try:
+        result._SetListener(self._extended_message._listener_for_children)
+      except ReferenceError:
+        pass
+    else:
+      # Singular scalar -- just return the default without inserting into the
+      # dict.
+      return extension_handle.default_value
+
+    # Atomically check if another thread has preempted us and, if not, swap
+    # in the new object we just created.  If someone has preempted us, we
+    # take that object and discard ours.
+    # WARNING:  We are relying on setdefault() being atomic.  This is true
+    #   in CPython but we haven't investigated others.  This warning appears
+    #   in several other locations in this file.
+    result = self._extended_message._fields.setdefault(
+        extension_handle, result)
+
+    return result
+
+  def __eq__(self, other):
+    if not isinstance(other, self.__class__):
+      return False
+
+    my_fields = self._extended_message.ListFields()
+    other_fields = other._extended_message.ListFields()
+
+    # Get rid of non-extension fields.
+    my_fields    = [ field for field in my_fields    if field.is_extension ]
+    other_fields = [ field for field in other_fields if field.is_extension ]
+
+    return my_fields == other_fields
+
+  def __ne__(self, other):
+    return not self == other
+
+  def __hash__(self):
+    raise TypeError('unhashable object')
+
+  # Note that this is only meaningful for non-repeated, scalar extension
+  # fields.  Note also that we may have to call _Modified() when we do
+  # successfully set a field this way, to set any necssary "has" bits in the
+  # ancestors of the extended message.
+  def __setitem__(self, extension_handle, value):
+    """If extension_handle specifies a non-repeated, scalar extension
+    field, sets the value of that field.
+    """
+
+    _VerifyExtensionHandle(self._extended_message, extension_handle)
+
+    if (extension_handle.label == _FieldDescriptor.LABEL_REPEATED or
+        extension_handle.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE):
+      raise TypeError(
+          'Cannot assign to extension "%s" because it is a repeated or '
+          'composite type.' % extension_handle.full_name)
+
+    # It's slightly wasteful to lookup the type checker each time,
+    # but we expect this to be a vanishingly uncommon case anyway.
+    type_checker = type_checkers.GetTypeChecker(
+        extension_handle.cpp_type, extension_handle.type)
+    type_checker.CheckValue(value)
+    self._extended_message._fields[extension_handle] = value
+    self._extended_message._Modified()
+
+  def _FindExtensionByName(self, name):
+    """Tries to find a known extension with the specified name.
+
+    Args:
+      name: Extension full name.
+
+    Returns:
+      Extension field descriptor.
+    """
+    return self._extended_message._extensions_by_name.get(name, None)
diff --git a/python/google/protobuf/internal/reflection_test.py b/python/google/protobuf/internal/reflection_test.py
index 54eeebe..7b9d339 100755
--- a/python/google/protobuf/internal/reflection_test.py
+++ b/python/google/protobuf/internal/reflection_test.py
@@ -41,8 +41,6 @@
 import struct
 
 import unittest
-# TODO(robinson): When we split this test in two, only some of these imports
-# will be necessary in each test.
 from google.protobuf import unittest_import_pb2
 from google.protobuf import unittest_mset_pb2
 from google.protobuf import unittest_pb2
@@ -50,6 +48,7 @@
 from google.protobuf import descriptor
 from google.protobuf import message
 from google.protobuf import reflection
+from google.protobuf.internal import api_implementation
 from google.protobuf.internal import more_extensions_pb2
 from google.protobuf.internal import more_messages_pb2
 from google.protobuf.internal import wire_format
@@ -104,10 +103,10 @@
 
 class ReflectionTest(unittest.TestCase):
 
-  def assertIs(self, values, others):
+  def assertListsEqual(self, values, others):
     self.assertEqual(len(values), len(others))
     for i in range(len(values)):
-      self.assertTrue(values[i] is others[i])
+      self.assertEqual(values[i], others[i])
 
   def testScalarConstructor(self):
     # Constructor with only scalar types should succeed.
@@ -201,15 +200,24 @@
         list(proto.repeated_foreign_message))
 
   def testConstructorTypeError(self):
-    self.assertRaises(TypeError, unittest_pb2.TestAllTypes, optional_int32="foo")
-    self.assertRaises(TypeError, unittest_pb2.TestAllTypes, optional_string=1234)
-    self.assertRaises(TypeError, unittest_pb2.TestAllTypes, optional_nested_message=1234)
-    self.assertRaises(TypeError, unittest_pb2.TestAllTypes, repeated_int32=1234)
-    self.assertRaises(TypeError, unittest_pb2.TestAllTypes, repeated_int32=["foo"])
-    self.assertRaises(TypeError, unittest_pb2.TestAllTypes, repeated_string=1234)
-    self.assertRaises(TypeError, unittest_pb2.TestAllTypes, repeated_string=[1234])
-    self.assertRaises(TypeError, unittest_pb2.TestAllTypes, repeated_nested_message=1234)
-    self.assertRaises(TypeError, unittest_pb2.TestAllTypes, repeated_nested_message=[1234])
+    self.assertRaises(
+        TypeError, unittest_pb2.TestAllTypes, optional_int32="foo")
+    self.assertRaises(
+        TypeError, unittest_pb2.TestAllTypes, optional_string=1234)
+    self.assertRaises(
+        TypeError, unittest_pb2.TestAllTypes, optional_nested_message=1234)
+    self.assertRaises(
+        TypeError, unittest_pb2.TestAllTypes, repeated_int32=1234)
+    self.assertRaises(
+        TypeError, unittest_pb2.TestAllTypes, repeated_int32=["foo"])
+    self.assertRaises(
+        TypeError, unittest_pb2.TestAllTypes, repeated_string=1234)
+    self.assertRaises(
+        TypeError, unittest_pb2.TestAllTypes, repeated_string=[1234])
+    self.assertRaises(
+        TypeError, unittest_pb2.TestAllTypes, repeated_nested_message=1234)
+    self.assertRaises(
+        TypeError, unittest_pb2.TestAllTypes, repeated_nested_message=[1234])
 
   def testConstructorInvalidatesCachedByteSize(self):
     message = unittest_pb2.TestAllTypes(optional_int32 = 12)
@@ -311,11 +319,14 @@
       self.assertEqual(0, getattr(composite_field, scalar_field_name))
 
       # Finally, ensure that modifications to the old composite field object
-      # don't have any effect on the parent.
+      # don't have any effect on the parent. Possible only with the pure-python
+      # implementation of the API.
       #
       # (NOTE that when we clear the composite field in the parent, we actually
       # don't recursively clear down the tree.  Instead, we just disconnect the
       # cleared composite from the tree.)
+      if api_implementation.Type() != 'python':
+        return
       self.assertTrue(old_composite_field is not composite_field)
       setattr(old_composite_field, scalar_field_name, new_val)
       self.assertTrue(not composite_field.HasField(scalar_field_name))
@@ -337,6 +348,8 @@
     nested.bb = 23
 
   def testDisconnectingNestedMessageBeforeSettingField(self):
+    if api_implementation.Type() != 'python':
+      return
     proto = unittest_pb2.TestAllTypes()
     nested = proto.optional_nested_message
     proto.ClearField('optional_nested_message')  # Should disconnect from parent
@@ -526,7 +539,6 @@
     # proto.nonexistent_field = 23 should fail as well.
     self.assertRaises(AttributeError, setattr, proto, 'nonexistent_field', 23)
 
-  # TODO(robinson): Add type-safety check for enums.
   def testSingleScalarTypeSafety(self):
     proto = unittest_pb2.TestAllTypes()
     self.assertRaises(TypeError, setattr, proto, 'optional_int32', 1.1)
@@ -538,7 +550,9 @@
     def TestMinAndMaxIntegers(field_name, expected_min, expected_max):
       pb = unittest_pb2.TestAllTypes()
       setattr(pb, field_name, expected_min)
+      self.assertEqual(expected_min, getattr(pb, field_name))
       setattr(pb, field_name, expected_max)
+      self.assertEqual(expected_max, getattr(pb, field_name))
       self.assertRaises(ValueError, setattr, pb, field_name, expected_min - 1)
       self.assertRaises(ValueError, setattr, pb, field_name, expected_max + 1)
 
@@ -546,7 +560,33 @@
     TestMinAndMaxIntegers('optional_uint32', 0, 0xffffffff)
     TestMinAndMaxIntegers('optional_int64', -(1 << 63), (1 << 63) - 1)
     TestMinAndMaxIntegers('optional_uint64', 0, 0xffffffffffffffff)
-    TestMinAndMaxIntegers('optional_nested_enum', -(1 << 31), (1 << 31) - 1)
+
+    pb = unittest_pb2.TestAllTypes()
+    pb.optional_nested_enum = 1
+    self.assertEqual(1, pb.optional_nested_enum)
+
+    # Invalid enum values.
+    pb.optional_nested_enum = 0
+    self.assertEqual(0, pb.optional_nested_enum)
+
+    bytes_size_before = pb.ByteSize()
+
+    pb.optional_nested_enum = 4
+    self.assertEqual(4, pb.optional_nested_enum)
+
+    pb.optional_nested_enum = 0
+    self.assertEqual(0, pb.optional_nested_enum)
+
+    # Make sure that setting the same enum field doesn't just add unknown
+    # fields (but overwrites them).
+    self.assertEqual(bytes_size_before, pb.ByteSize())
+
+    # Is the invalid value preserved after serialization?
+    serialized = pb.SerializeToString()
+    pb2 = unittest_pb2.TestAllTypes()
+    pb2.ParseFromString(serialized)
+    self.assertEqual(0, pb2.optional_nested_enum)
+    self.assertEqual(pb, pb2)
 
   def testRepeatedScalarTypeSafety(self):
     proto = unittest_pb2.TestAllTypes()
@@ -560,11 +600,19 @@
     self.assertRaises(IndexError, proto.repeated_int32.__setitem__, 500, 23)
     self.assertRaises(TypeError, proto.repeated_int32.__setitem__, 0, 'abc')
 
+    # Repeated enums tests.
+    #proto.repeated_nested_enum.append(0)
+
   def testSingleScalarGettersAndSetters(self):
     proto = unittest_pb2.TestAllTypes()
     self.assertEqual(0, proto.optional_int32)
     proto.optional_int32 = 1
     self.assertEqual(1, proto.optional_int32)
+
+    proto.optional_uint64 = 0xffffffffffff
+    self.assertEqual(0xffffffffffff, proto.optional_uint64)
+    proto.optional_uint64 = 0xffffffffffffffff
+    self.assertEqual(0xffffffffffffffff, proto.optional_uint64)
     # TODO(robinson): Test all other scalar field types.
 
   def testSingleScalarClearField(self):
@@ -645,11 +693,38 @@
     del proto.repeated_int32[2:]
     self.assertEqual([5, 35], proto.repeated_int32)
 
+    # Test extending.
+    proto.repeated_int32.extend([3, 13])
+    self.assertEqual([5, 35, 3, 13], proto.repeated_int32)
+
     # Test clearing.
     proto.ClearField('repeated_int32')
     self.assertTrue(not proto.repeated_int32)
     self.assertEqual(0, len(proto.repeated_int32))
 
+    proto.repeated_int32.append(1)
+    self.assertEqual(1, proto.repeated_int32[-1])
+    # Test assignment to a negative index.
+    proto.repeated_int32[-1] = 2
+    self.assertEqual(2, proto.repeated_int32[-1])
+
+    # Test deletion at negative indices.
+    proto.repeated_int32[:] = [0, 1, 2, 3]
+    del proto.repeated_int32[-1]
+    self.assertEqual([0, 1, 2], proto.repeated_int32)
+
+    del proto.repeated_int32[-2]
+    self.assertEqual([0, 2], proto.repeated_int32)
+
+    self.assertRaises(IndexError, proto.repeated_int32.__delitem__, -3)
+    self.assertRaises(IndexError, proto.repeated_int32.__delitem__, 300)
+
+    del proto.repeated_int32[-2:-1]
+    self.assertEqual([2], proto.repeated_int32)
+
+    del proto.repeated_int32[100:10000]
+    self.assertEqual([2], proto.repeated_int32)
+
   def testRepeatedScalarsRemove(self):
     proto = unittest_pb2.TestAllTypes()
 
@@ -687,7 +762,7 @@
     m1 = proto.repeated_nested_message.add()
     self.assertTrue(proto.repeated_nested_message)
     self.assertEqual(2, len(proto.repeated_nested_message))
-    self.assertIs([m0, m1], proto.repeated_nested_message)
+    self.assertListsEqual([m0, m1], proto.repeated_nested_message)
     self.assertTrue(isinstance(m0, unittest_pb2.TestAllTypes.NestedMessage))
 
     # Test out-of-bounds indices.
@@ -706,32 +781,57 @@
     m2 = proto.repeated_nested_message.add()
     m3 = proto.repeated_nested_message.add()
     m4 = proto.repeated_nested_message.add()
-    self.assertIs([m1, m2, m3], proto.repeated_nested_message[1:4])
-    self.assertIs([m0, m1, m2, m3, m4], proto.repeated_nested_message[:])
+    self.assertListsEqual(
+        [m1, m2, m3], proto.repeated_nested_message[1:4])
+    self.assertListsEqual(
+        [m0, m1, m2, m3, m4], proto.repeated_nested_message[:])
+    self.assertListsEqual(
+        [m0, m1], proto.repeated_nested_message[:2])
+    self.assertListsEqual(
+        [m2, m3, m4], proto.repeated_nested_message[2:])
+    self.assertEqual(
+        m0, proto.repeated_nested_message[0])
+    self.assertListsEqual(
+        [m0], proto.repeated_nested_message[:1])
 
     # Test that we can use the field as an iterator.
     result = []
     for i in proto.repeated_nested_message:
       result.append(i)
-    self.assertIs([m0, m1, m2, m3, m4], result)
+    self.assertListsEqual([m0, m1, m2, m3, m4], result)
 
     # Test single deletion.
     del proto.repeated_nested_message[2]
-    self.assertIs([m0, m1, m3, m4], proto.repeated_nested_message)
+    self.assertListsEqual([m0, m1, m3, m4], proto.repeated_nested_message)
 
     # Test slice deletion.
     del proto.repeated_nested_message[2:]
-    self.assertIs([m0, m1], proto.repeated_nested_message)
+    self.assertListsEqual([m0, m1], proto.repeated_nested_message)
+
+    # Test extending.
+    n1 = unittest_pb2.TestAllTypes.NestedMessage(bb=1)
+    n2 = unittest_pb2.TestAllTypes.NestedMessage(bb=2)
+    proto.repeated_nested_message.extend([n1,n2])
+    self.assertEqual(4, len(proto.repeated_nested_message))
+    self.assertEqual(n1, proto.repeated_nested_message[2])
+    self.assertEqual(n2, proto.repeated_nested_message[3])
 
     # Test clearing.
     proto.ClearField('repeated_nested_message')
     self.assertTrue(not proto.repeated_nested_message)
     self.assertEqual(0, len(proto.repeated_nested_message))
 
+    # Test constructing an element while adding it.
+    proto.repeated_nested_message.add(bb=23)
+    self.assertEqual(1, len(proto.repeated_nested_message))
+    self.assertEqual(23, proto.repeated_nested_message[0].bb)
+
   def testHandWrittenReflection(self):
-    # TODO(robinson): We probably need a better way to specify
-    # protocol types by hand.  But then again, this isn't something
-    # we expect many people to do.  Hmm.
+    # Hand written extensions are only supported by the pure-Python
+    # implementation of the API.
+    if api_implementation.Type() != 'python':
+      return
+
     FieldDescriptor = descriptor.FieldDescriptor
     foo_field_descriptor = FieldDescriptor(
         name='foo_field', full_name='MyProto.foo_field',
@@ -894,7 +994,7 @@
     self.assertTrue(not toplevel.HasField('submessage'))
     foreign = toplevel.submessage.Extensions[
         more_extensions_pb2.repeated_message_extension].add()
-    self.assertTrue(foreign is toplevel.submessage.Extensions[
+    self.assertEqual(foreign, toplevel.submessage.Extensions[
         more_extensions_pb2.repeated_message_extension][0])
     self.assertTrue(toplevel.HasField('submessage'))
 
@@ -997,6 +1097,12 @@
     self.assertEqual(123, proto2.repeated_nested_message[1].bb)
     self.assertEqual(321, proto2.repeated_nested_message[2].bb)
 
+    proto3 = unittest_pb2.TestAllTypes()
+    proto3.repeated_nested_message.MergeFrom(proto2.repeated_nested_message)
+    self.assertEqual(999, proto3.repeated_nested_message[0].bb)
+    self.assertEqual(123, proto3.repeated_nested_message[1].bb)
+    self.assertEqual(321, proto3.repeated_nested_message[2].bb)
+
   def testMergeFromAllFields(self):
     # With all fields set.
     proto1 = unittest_pb2.TestAllTypes()
@@ -1126,6 +1232,15 @@
     self.assertEqual(2, proto1.optional_int32)
     self.assertEqual('important-text', proto1.optional_string)
 
+  def testCopyFromBadType(self):
+    # The python implementation doesn't raise an exception in this
+    # case. In theory it should.
+    if api_implementation.Type() == 'python':
+      return
+    proto1 = unittest_pb2.TestAllTypes()
+    proto2 = unittest_pb2.TestAllExtensions()
+    self.assertRaises(TypeError, proto1.CopyFrom, proto2)
+
   def testClear(self):
     proto = unittest_pb2.TestAllTypes()
     test_util.SetAllFields(proto)
@@ -1231,9 +1346,10 @@
     proto.optional_string = str('Testing')
     self.assertEqual(proto.optional_string, unicode('Testing'))
 
-    # Values of type 'str' are also accepted as long as they can be encoded in
-    # UTF-8.
-    self.assertEqual(type(proto.optional_string), str)
+    if api_implementation.Type() == 'python':
+      # Values of type 'str' are also accepted as long as they can be
+      # encoded in UTF-8.
+      self.assertEqual(type(proto.optional_string), str)
 
     # Try to assign a 'str' value which contains bytes that aren't 7-bit ASCII.
     self.assertRaises(ValueError,
@@ -1271,7 +1387,7 @@
     # Check that the type_id is the same as the tag ID in the .proto file.
     self.assertEqual(raw.item[0].type_id, 1547769)
 
-    # Check the actually bytes on the wire.
+    # Check the actual bytes on the wire.
     self.assertTrue(
         raw.item[0].message.endswith(test_utf8_bytes))
     message2.MergeFromString(raw.item[0].message)
@@ -1279,10 +1395,23 @@
     self.assertEqual(type(message2.str), unicode)
     self.assertEqual(message2.str, test_utf8)
 
-    # How about if the bytes on the wire aren't a valid UTF-8 encoded string.
+    # The pure Python API throws an exception on MergeFromString(),
+    # if any of the string fields of the message can't be UTF-8 decoded.
+    # The C++ implementation of the API has no way to check that on
+    # MergeFromString and thus has no way to throw the exception.
+    #
+    # The pure Python API always returns objects of type 'unicode' (UTF-8
+    # encoded), or 'str' (in 7 bit ASCII).
     bytes = raw.item[0].message.replace(
         test_utf8_bytes, len(test_utf8_bytes) * '\xff')
-    self.assertRaises(UnicodeDecodeError, message2.MergeFromString, bytes)
+
+    unicode_decode_failed = False
+    try:
+      message2.MergeFromString(bytes)
+    except UnicodeDecodeError, e:
+      unicode_decode_failed = True
+    string_field = message2.str
+    self.assertTrue(unicode_decode_failed or type(string_field) == str)
 
   def testEmptyNestedMessage(self):
     proto = unittest_pb2.TestAllTypes()
@@ -1325,6 +1454,9 @@
     self.first_proto = unittest_pb2.TestAllTypes()
     self.second_proto = unittest_pb2.TestAllTypes()
 
+  def testNotHashable(self):
+    self.assertRaises(TypeError, hash, self.first_proto)
+
   def testSelfEquality(self):
     self.assertEqual(self.first_proto, self.first_proto)
 
@@ -1342,6 +1474,9 @@
     test_util.SetAllFields(self.first_proto)
     test_util.SetAllFields(self.second_proto)
 
+  def testNotHashable(self):
+    self.assertRaises(TypeError, hash, self.first_proto)
+
   def testNoneNotEqual(self):
     self.assertNotEqual(self.first_proto, None)
     self.assertNotEqual(None, self.second_proto)
@@ -1410,9 +1545,6 @@
     self.first_proto.ClearField('optional_nested_message')
     self.second_proto.optional_nested_message.ClearField('bb')
     self.assertNotEqual(self.first_proto, self.second_proto)
-    # TODO(robinson): Replace next two lines with method
-    # to set the "has" bit without changing the value,
-    # if/when such a method exists.
     self.first_proto.optional_nested_message.bb = 0
     self.first_proto.optional_nested_message.ClearField('bb')
     self.assertEqual(self.first_proto, self.second_proto)
@@ -1477,6 +1609,14 @@
   def testEmptyMessage(self):
     self.assertEqual(0, self.proto.ByteSize())
 
+  def testSizedOnKwargs(self):
+    # Use a separate message to ensure testing right after creation.
+    proto = unittest_pb2.TestAllTypes()
+    self.assertEqual(0, proto.ByteSize())
+    proto_kwargs = unittest_pb2.TestAllTypes(optional_int64 = 1)
+    # One byte for the tag, one to encode varint 1.
+    self.assertEqual(2, proto_kwargs.ByteSize())
+
   def testVarints(self):
     def Test(i, expected_varint_size):
       self.proto.Clear()
@@ -1668,10 +1808,13 @@
     self.assertEqual(3, self.proto.ByteSize())
     self.proto.ClearField('optional_foreign_message')
     self.assertEqual(0, self.proto.ByteSize())
-    child = self.proto.optional_foreign_message
-    self.proto.ClearField('optional_foreign_message')
-    child.c = 128
-    self.assertEqual(0, self.proto.ByteSize())
+
+    if api_implementation.Type() == 'python':
+      # This is only possible in pure-Python implementation of the API.
+      child = self.proto.optional_foreign_message
+      self.proto.ClearField('optional_foreign_message')
+      child.c = 128
+      self.assertEqual(0, self.proto.ByteSize())
 
     # Test within extension.
     extension = more_extensions_pb2.optional_message_extension
@@ -1737,7 +1880,6 @@
     self.assertEqual(19, self.packed_extended_proto.ByteSize())
 
 
-# TODO(robinson): We need cross-language serialization consistency tests.
 # Issues to be sure to cover include:
 #   * Handling of unrecognized tags ("uninterpreted_bytes").
 #   * Handling of MessageSets.
@@ -1792,6 +1934,10 @@
     self.assertEqual(first_proto, second_proto)
 
   def testParseTruncated(self):
+    # This test is only applicable for the Python implementation of the API.
+    if api_implementation.Type() != 'python':
+      return
+
     first_proto = unittest_pb2.TestAllTypes()
     test_util.SetAllFields(first_proto)
     serialized = first_proto.SerializeToString()
diff --git a/python/google/protobuf/internal/text_format_test.py b/python/google/protobuf/internal/text_format_test.py
index e0991cb..a354778 100755
--- a/python/google/protobuf/internal/text_format_test.py
+++ b/python/google/protobuf/internal/text_format_test.py
@@ -35,6 +35,7 @@
 __author__ = 'kenton@google.com (Kenton Varda)'
 
 import difflib
+import re
 
 import unittest
 from google.protobuf import text_format
@@ -95,12 +96,13 @@
 
   def testPrintExotic(self):
     message = unittest_pb2.TestAllTypes()
-    message.repeated_int64.append(-9223372036854775808);
-    message.repeated_uint64.append(18446744073709551615);
-    message.repeated_double.append(123.456);
-    message.repeated_double.append(1.23e22);
-    message.repeated_double.append(1.23e-18);
-    message.repeated_string.append('\000\001\a\b\f\n\r\t\v\\\'\"');
+    message.repeated_int64.append(-9223372036854775808)
+    message.repeated_uint64.append(18446744073709551615)
+    message.repeated_double.append(123.456)
+    message.repeated_double.append(1.23e22)
+    message.repeated_double.append(1.23e-18)
+    message.repeated_string.append('\000\001\a\b\f\n\r\t\v\\\'"')
+    message.repeated_string.append(u'\u00fc\ua71f')
     self.CompareToGoldenText(
       self.RemoveRedundantZeros(text_format.MessageToString(message)),
       'repeated_int64: -9223372036854775808\n'
@@ -109,7 +111,95 @@
       'repeated_double: 1.23e+22\n'
       'repeated_double: 1.23e-18\n'
       'repeated_string: '
-        '\"\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\\'\\\"\"\n')
+        '"\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\\'\\""\n'
+      'repeated_string: "\\303\\274\\352\\234\\237"\n')
+
+  def testPrintNestedMessageAsOneLine(self):
+    message = unittest_pb2.TestAllTypes()
+    msg = message.repeated_nested_message.add()
+    msg.bb = 42;
+    self.CompareToGoldenText(
+        text_format.MessageToString(message, as_one_line=True),
+        'repeated_nested_message { bb: 42 }')
+
+  def testPrintRepeatedFieldsAsOneLine(self):
+    message = unittest_pb2.TestAllTypes()
+    message.repeated_int32.append(1)
+    message.repeated_int32.append(1)
+    message.repeated_int32.append(3)
+    message.repeated_string.append("Google")
+    message.repeated_string.append("Zurich")
+    self.CompareToGoldenText(
+        text_format.MessageToString(message, as_one_line=True),
+        'repeated_int32: 1 repeated_int32: 1 repeated_int32: 3 '
+        'repeated_string: "Google" repeated_string: "Zurich"')
+
+  def testPrintNestedNewLineInStringAsOneLine(self):
+    message = unittest_pb2.TestAllTypes()
+    message.optional_string = "a\nnew\nline"
+    self.CompareToGoldenText(
+        text_format.MessageToString(message, as_one_line=True),
+        'optional_string: "a\\nnew\\nline"')
+
+  def testPrintMessageSetAsOneLine(self):
+    message = unittest_mset_pb2.TestMessageSetContainer()
+    ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
+    ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
+    message.message_set.Extensions[ext1].i = 23
+    message.message_set.Extensions[ext2].str = 'foo'
+    self.CompareToGoldenText(
+        text_format.MessageToString(message, as_one_line=True),
+        'message_set {'
+        ' [protobuf_unittest.TestMessageSetExtension1] {'
+        ' i: 23'
+        ' }'
+        ' [protobuf_unittest.TestMessageSetExtension2] {'
+        ' str: \"foo\"'
+        ' }'
+        ' }')
+
+  def testPrintExoticAsOneLine(self):
+    message = unittest_pb2.TestAllTypes()
+    message.repeated_int64.append(-9223372036854775808)
+    message.repeated_uint64.append(18446744073709551615)
+    message.repeated_double.append(123.456)
+    message.repeated_double.append(1.23e22)
+    message.repeated_double.append(1.23e-18)
+    message.repeated_string.append('\000\001\a\b\f\n\r\t\v\\\'"')
+    message.repeated_string.append(u'\u00fc\ua71f')
+    self.CompareToGoldenText(
+      self.RemoveRedundantZeros(
+          text_format.MessageToString(message, as_one_line=True)),
+      'repeated_int64: -9223372036854775808'
+      ' repeated_uint64: 18446744073709551615'
+      ' repeated_double: 123.456'
+      ' repeated_double: 1.23e+22'
+      ' repeated_double: 1.23e-18'
+      ' repeated_string: '
+      '"\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\\'\\""'
+      ' repeated_string: "\\303\\274\\352\\234\\237"')
+
+  def testRoundTripExoticAsOneLine(self):
+    message = unittest_pb2.TestAllTypes()
+    message.repeated_int64.append(-9223372036854775808)
+    message.repeated_uint64.append(18446744073709551615)
+    message.repeated_double.append(123.456)
+    message.repeated_double.append(1.23e22)
+    message.repeated_double.append(1.23e-18)
+    message.repeated_string.append('\000\001\a\b\f\n\r\t\v\\\'"')
+    message.repeated_string.append(u'\u00fc\ua71f')
+
+    wire_text = text_format.MessageToString(message, as_one_line=True)
+    parsed_message = unittest_pb2.TestAllTypes()
+    text_format.Merge(wire_text, parsed_message)
+    self.assertEquals(message, parsed_message)
+
+  def testPrintRawUtf8String(self):
+    message = unittest_pb2.TestAllTypes()
+    message.repeated_string.append(u'\u00fc\ua71f')
+    self.CompareToGoldenText(
+        text_format.MessageToString(message, as_utf8 = True),
+        'repeated_string: "\303\274\352\234\237"\n')
 
   def testMessageToString(self):
     message = unittest_pb2.ForeignMessage()
@@ -119,8 +209,12 @@
   def RemoveRedundantZeros(self, text):
     # Some platforms print 1e+5 as 1e+005.  This is fine, but we need to remove
     # these zeros in order to match the golden file.
-    return text.replace('e+0','e+').replace('e+0','e+') \
+    text = text.replace('e+0','e+').replace('e+0','e+') \
                .replace('e-0','e-').replace('e-0','e-')
+    # Floating point fields are printed with .0 suffix even if they are
+    # actualy integer numbers.
+    text = re.compile('\.0$', re.MULTILINE).sub('', text)
+    return text
 
   def testMergeGolden(self):
     golden_text = '\n'.join(self.ReadGolden('text_format_unittest_data.txt'))
@@ -191,8 +285,11 @@
             'repeated_double: 1.23e+22\n'
             'repeated_double: 1.23e-18\n'
             'repeated_string: \n'
-            '\"\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\\'\\\"\"\n'
-            'repeated_string: "foo" \'corge\' "grault"')
+            '"\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\\'\\""\n'
+            'repeated_string: "foo" \'corge\' "grault"\n'
+            'repeated_string: "\\303\\274\\352\\234\\237"\n'
+            'repeated_string: "\\xc3\\xbc"\n'
+            'repeated_string: "\xc3\xbc"\n')
     text_format.Merge(text, message)
 
     self.assertEqual(-9223372036854775808, message.repeated_int64[0])
@@ -201,8 +298,30 @@
     self.assertEqual(1.23e22, message.repeated_double[1])
     self.assertEqual(1.23e-18, message.repeated_double[2])
     self.assertEqual(
-        '\000\001\a\b\f\n\r\t\v\\\'\"', message.repeated_string[0])
+        '\000\001\a\b\f\n\r\t\v\\\'"', message.repeated_string[0])
     self.assertEqual('foocorgegrault', message.repeated_string[1])
+    self.assertEqual(u'\u00fc\ua71f', message.repeated_string[2])
+    self.assertEqual(u'\u00fc', message.repeated_string[3])
+
+  def testMergeEmptyText(self):
+    message = unittest_pb2.TestAllTypes()
+    text = ''
+    text_format.Merge(text, message)
+    self.assertEquals(unittest_pb2.TestAllTypes(), message)
+
+  def testMergeInvalidUtf8(self):
+    message = unittest_pb2.TestAllTypes()
+    text = 'repeated_string: "\\xc3\\xc3"'
+    self.assertRaises(text_format.ParseError, text_format.Merge, text, message)
+
+  def testMergeSingleWord(self):
+    message = unittest_pb2.TestAllTypes()
+    text = 'foo'
+    self.assertRaisesWithMessage(
+        text_format.ParseError,
+        ('1:1 : Message type "protobuf_unittest.TestAllTypes" has no field named '
+         '"foo".'),
+        text_format.Merge, text, message)
 
   def testMergeUnknownField(self):
     message = unittest_pb2.TestAllTypes()
@@ -297,7 +416,8 @@
             'identifiER_4 : 1.1e+2 ID5:-0.23 ID6:\'aaaa\\\'bbbb\'\n'
             'ID7 : "aa\\"bb"\n\n\n\n ID8: {A:inf B:-inf C:true D:false}\n'
             'ID9: 22 ID10: -111111111111111111 ID11: -22\n'
-            'ID12: 2222222222222222222')
+            'ID12: 2222222222222222222 '
+            'false_bool:  0 true_BOOL:t \n true_bool1:  1 false_BOOL1:f ' )
     tokenizer = text_format._Tokenizer(text)
     methods = [(tokenizer.ConsumeIdentifier, 'identifier1'),
                ':',
@@ -347,7 +467,19 @@
                (tokenizer.ConsumeInt32, -22),
                (tokenizer.ConsumeIdentifier, 'ID12'),
                ':',
-               (tokenizer.ConsumeUint64, 2222222222222222222)]
+               (tokenizer.ConsumeUint64, 2222222222222222222),
+               (tokenizer.ConsumeIdentifier, 'false_bool'),
+               ':',
+               (tokenizer.ConsumeBool, False),
+               (tokenizer.ConsumeIdentifier, 'true_BOOL'),
+               ':',
+               (tokenizer.ConsumeBool, True),
+               (tokenizer.ConsumeIdentifier, 'true_bool1'),
+               ':',
+               (tokenizer.ConsumeBool, True),
+               (tokenizer.ConsumeIdentifier, 'false_BOOL1'),
+               ':',
+               (tokenizer.ConsumeBool, False)]
 
     i = 0
     while not tokenizer.AtEnd():
diff --git a/python/google/protobuf/message.py b/python/google/protobuf/message.py
index f839847..54cf35e 100755
--- a/python/google/protobuf/message.py
+++ b/python/google/protobuf/message.py
@@ -67,6 +67,11 @@
 
   DESCRIPTOR = None
 
+  def __deepcopy__(self, memo=None):
+    clone = type(self)()
+    clone.MergeFrom(self)
+    return clone
+
   def __eq__(self, other_msg):
     raise NotImplementedError
 
@@ -74,9 +79,15 @@
     # Can't just say self != other_msg, since that would infinitely recurse. :)
     return not self == other_msg
 
+  def __hash__(self):
+    raise TypeError('unhashable object')
+
   def __str__(self):
     raise NotImplementedError
 
+  def __unicode__(self):
+    raise NotImplementedError
+
   def MergeFrom(self, other_msg):
     """Merges the contents of the specified message into current message.
 
diff --git a/python/google/protobuf/pyext/python-proto2.cc b/python/google/protobuf/pyext/python-proto2.cc
new file mode 100644
index 0000000..f2799e6
--- /dev/null
+++ b/python/google/protobuf/pyext/python-proto2.cc
@@ -0,0 +1,1658 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: petar@google.com (Petar Petrov)
+
+#include <Python.h>
+#include <map>
+#include <string>
+#include <vector>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/pyext/python_descriptor.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/unknown_field_set.h>
+#include <google/protobuf/pyext/python_protobuf.h>
+
+/* Is 64bit */
+#define IS_64BIT (SIZEOF_LONG == 8)
+
+#define FIELD_BELONGS_TO_MESSAGE(field_descriptor, message) \
+    ((message)->GetDescriptor() == (field_descriptor)->containing_type())
+
+#define FIELD_IS_REPEATED(field_descriptor)                 \
+    ((field_descriptor)->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED)
+
+#define GOOGLE_CHECK_GET_INT32(arg, value)                         \
+    int32 value;                                            \
+    if (!CheckAndGetInteger(arg, &value, kint32min_py, kint32max_py)) { \
+      return NULL;                                          \
+    }
+
+#define GOOGLE_CHECK_GET_INT64(arg, value)                         \
+    int64 value;                                            \
+    if (!CheckAndGetInteger(arg, &value, kint64min_py, kint64max_py)) { \
+      return NULL;                                          \
+    }
+
+#define GOOGLE_CHECK_GET_UINT32(arg, value)                        \
+    uint32 value;                                           \
+    if (!CheckAndGetInteger(arg, &value, kPythonZero, kuint32max_py)) { \
+      return NULL;                                          \
+    }
+
+#define GOOGLE_CHECK_GET_UINT64(arg, value)                        \
+    uint64 value;                                           \
+    if (!CheckAndGetInteger(arg, &value, kPythonZero, kuint64max_py)) { \
+      return NULL;                                          \
+    }
+
+#define GOOGLE_CHECK_GET_FLOAT(arg, value)                         \
+    float value;                                            \
+    if (!CheckAndGetFloat(arg, &value)) {                   \
+      return NULL;                                          \
+    }                                                       \
+
+#define GOOGLE_CHECK_GET_DOUBLE(arg, value)                        \
+    double value;                                           \
+    if (!CheckAndGetDouble(arg, &value)) {                  \
+      return NULL;                                          \
+    }
+
+#define GOOGLE_CHECK_GET_BOOL(arg, value)                          \
+    bool value;                                             \
+    if (!CheckAndGetBool(arg, &value)) {                    \
+      return NULL;                                          \
+    }
+
+#define C(str) const_cast<char*>(str)
+
+// --- Globals:
+
+// Constants used for integer type range checking.
+static PyObject* kPythonZero;
+static PyObject* kint32min_py;
+static PyObject* kint32max_py;
+static PyObject* kuint32max_py;
+static PyObject* kint64min_py;
+static PyObject* kint64max_py;
+static PyObject* kuint64max_py;
+
+namespace google {
+namespace protobuf {
+namespace python {
+
+// --- Support Routines:
+
+static void AddConstants(PyObject* module) {
+  struct NameValue {
+    char* name;
+    int32 value;
+  } constants[] = {
+    // Labels:
+    {"LABEL_OPTIONAL", google::protobuf::FieldDescriptor::LABEL_OPTIONAL},
+    {"LABEL_REQUIRED", google::protobuf::FieldDescriptor::LABEL_REQUIRED},
+    {"LABEL_REPEATED", google::protobuf::FieldDescriptor::LABEL_REPEATED},
+    // CPP types:
+    {"CPPTYPE_MESSAGE", google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE},
+    // Field Types:
+    {"TYPE_MESSAGE", google::protobuf::FieldDescriptor::TYPE_MESSAGE},
+    // End.
+    {NULL, 0}
+  };
+
+  for (NameValue* constant = constants;
+       constant->name != NULL; constant++) {
+    PyModule_AddIntConstant(module, constant->name, constant->value);
+  }
+}
+
+// --- CMessage Custom Type:
+
+// ------ Type Forward Declaration:
+
+struct CMessage;
+struct CMessage_Type;
+
+static void CMessageDealloc(CMessage* self);
+static int CMessageInit(CMessage* self, PyObject *args, PyObject *kwds);
+static PyObject* CMessageStr(CMessage* self);
+
+static PyObject* CMessage_AddMessage(CMessage* self, PyObject* args);
+static PyObject* CMessage_AddRepeatedScalar(CMessage* self, PyObject* args);
+static PyObject* CMessage_AssignRepeatedScalar(CMessage* self, PyObject* args);
+static PyObject* CMessage_ByteSize(CMessage* self, PyObject* args);
+static PyObject* CMessage_Clear(CMessage* self, PyObject* args);
+static PyObject* CMessage_ClearField(CMessage* self, PyObject* args);
+static PyObject* CMessage_ClearFieldByDescriptor(
+    CMessage* self, PyObject* args);
+static PyObject* CMessage_CopyFrom(CMessage* self, PyObject* args);
+static PyObject* CMessage_DebugString(CMessage* self, PyObject* args);
+static PyObject* CMessage_DeleteRepeatedField(CMessage* self, PyObject* args);
+static PyObject* CMessage_Equals(CMessage* self, PyObject* args);
+static PyObject* CMessage_FieldLength(CMessage* self, PyObject* args);
+static PyObject* CMessage_FindInitializationErrors(CMessage* self);
+static PyObject* CMessage_GetRepeatedMessage(CMessage* self, PyObject* args);
+static PyObject* CMessage_GetRepeatedScalar(CMessage* self, PyObject* args);
+static PyObject* CMessage_GetScalar(CMessage* self, PyObject* args);
+static PyObject* CMessage_HasField(CMessage* self, PyObject* args);
+static PyObject* CMessage_HasFieldByDescriptor(CMessage* self, PyObject* args);
+static PyObject* CMessage_IsInitialized(CMessage* self, PyObject* args);
+static PyObject* CMessage_ListFields(CMessage* self, PyObject* args);
+static PyObject* CMessage_MergeFrom(CMessage* self, PyObject* args);
+static PyObject* CMessage_MergeFromString(CMessage* self, PyObject* args);
+static PyObject* CMessage_MutableMessage(CMessage* self, PyObject* args);
+static PyObject* CMessage_NewSubMessage(CMessage* self, PyObject* args);
+static PyObject* CMessage_SetScalar(CMessage* self, PyObject* args);
+static PyObject* CMessage_SerializePartialToString(
+    CMessage* self, PyObject* args);
+static PyObject* CMessage_SerializeToString(CMessage* self, PyObject* args);
+static PyObject* CMessage_SetInParent(CMessage* self, PyObject* args);
+static PyObject* CMessage_SwapRepeatedFieldElements(
+    CMessage* self, PyObject* args);
+
+// ------ Object Definition:
+
+typedef struct CMessage {
+  PyObject_HEAD
+
+  struct CMessage* parent;  // NULL if wasn't created from another message.
+  CFieldDescriptor* parent_field;
+  const char* full_name;
+  google::protobuf::Message* message;
+  bool free_message;
+  bool read_only;
+} CMessage;
+
+// ------ Method Table:
+
+#define CMETHOD(name, args, doc)   \
+  { C(#name), (PyCFunction)CMessage_##name, args, C(doc) }
+static PyMethodDef CMessageMethods[] = {
+  CMETHOD(AddMessage, METH_O,
+          "Adds a new message to a repeated composite field."),
+  CMETHOD(AddRepeatedScalar, METH_VARARGS,
+          "Adds a scalar to a repeated scalar field."),
+  CMETHOD(AssignRepeatedScalar, METH_VARARGS,
+          "Clears and sets the values of a repeated scalar field."),
+  CMETHOD(ByteSize, METH_NOARGS,
+          "Returns the size of the message in bytes."),
+  CMETHOD(Clear, METH_NOARGS,
+          "Clears a protocol message."),
+  CMETHOD(ClearField, METH_O,
+          "Clears a protocol message field by name."),
+  CMETHOD(ClearFieldByDescriptor, METH_O,
+          "Clears a protocol message field by descriptor."),
+  CMETHOD(CopyFrom, METH_O,
+          "Copies a protocol message into the current message."),
+  CMETHOD(DebugString, METH_NOARGS,
+          "Returns the debug string of a protocol message."),
+  CMETHOD(DeleteRepeatedField, METH_VARARGS,
+          "Deletes a slice of values from a repeated field."),
+  CMETHOD(Equals, METH_O,
+          "Checks if two protocol messages are equal (by identity)."),
+  CMETHOD(FieldLength, METH_O,
+          "Returns the number of elements in a repeated field."),
+  CMETHOD(FindInitializationErrors, METH_NOARGS,
+          "Returns the initialization errors of a message."),
+  CMETHOD(GetRepeatedMessage, METH_VARARGS,
+          "Returns a message from a repeated composite field."),
+  CMETHOD(GetRepeatedScalar, METH_VARARGS,
+          "Returns a scalar value from a repeated scalar field."),
+  CMETHOD(GetScalar, METH_O,
+          "Returns the scalar value of a field."),
+  CMETHOD(HasField, METH_O,
+          "Checks if a message field is set."),
+  CMETHOD(HasFieldByDescriptor, METH_O,
+          "Checks if a message field is set by given its descriptor"),
+  CMETHOD(IsInitialized, METH_NOARGS,
+          "Checks if all required fields of a protocol message are set."),
+  CMETHOD(ListFields, METH_NOARGS,
+          "Lists all set fields of a message."),
+  CMETHOD(MergeFrom, METH_O,
+          "Merges a protocol message into the current message."),
+  CMETHOD(MergeFromString, METH_O,
+          "Merges a serialized message into the current message."),
+  CMETHOD(MutableMessage, METH_O,
+          "Returns a new instance of a nested protocol message."),
+  CMETHOD(NewSubMessage, METH_O,
+          "Creates and returns a python message given the descriptor of a "
+          "composite field of the current message."),
+  CMETHOD(SetScalar, METH_VARARGS,
+          "Sets the value of a singular scalar field."),
+  CMETHOD(SerializePartialToString, METH_VARARGS,
+          "Serializes the message to a string, even if it isn't initialized."),
+  CMETHOD(SerializeToString, METH_NOARGS,
+          "Serializes the message to a string, only for initialized messages."),
+  CMETHOD(SetInParent, METH_NOARGS,
+          "Sets the has bit of the given field in its parent message."),
+  CMETHOD(SwapRepeatedFieldElements, METH_VARARGS,
+          "Swaps the elements in two positions in a repeated field."),
+  { NULL, NULL }
+};
+#undef CMETHOD
+
+static PyMemberDef CMessageMembers[] = {
+  { C("full_name"), T_STRING, offsetof(CMessage, full_name), 0, "Full name" },
+  { NULL }
+};
+
+// ------ Type Definition:
+
+// The definition for the type object that captures the type of CMessage
+// in Python.
+PyTypeObject CMessage_Type = {
+  PyObject_HEAD_INIT(&PyType_Type)
+  0,
+  C("google3.net.google.protobuf.python.internal."
+    "_net_proto2___python."
+    "CMessage"),                       // tp_name
+  sizeof(CMessage),                    //  tp_basicsize
+  0,                                   //  tp_itemsize
+  (destructor)CMessageDealloc,         //  tp_dealloc
+  0,                                   //  tp_print
+  0,                                   //  tp_getattr
+  0,                                   //  tp_setattr
+  0,                                   //  tp_compare
+  0,                                   //  tp_repr
+  0,                                   //  tp_as_number
+  0,                                   //  tp_as_sequence
+  0,                                   //  tp_as_mapping
+  0,                                   //  tp_hash
+  0,                                   //  tp_call
+  (reprfunc)CMessageStr,               //  tp_str
+  0,                                   //  tp_getattro
+  0,                                   //  tp_setattro
+  0,                                   //  tp_as_buffer
+  Py_TPFLAGS_DEFAULT,                  //  tp_flags
+  C("A ProtocolMessage"),              //  tp_doc
+  0,                                   //  tp_traverse
+  0,                                   //  tp_clear
+  0,                                   //  tp_richcompare
+  0,                                   //  tp_weaklistoffset
+  0,                                   //  tp_iter
+  0,                                   //  tp_iternext
+  CMessageMethods,                     //  tp_methods
+  CMessageMembers,                     //  tp_members
+  0,                                   //  tp_getset
+  0,                                   //  tp_base
+  0,                                   //  tp_dict
+  0,                                   //  tp_descr_get
+  0,                                   //  tp_descr_set
+  0,                                   //  tp_dictoffset
+  (initproc)CMessageInit,              //  tp_init
+  PyType_GenericAlloc,                 //  tp_alloc
+  PyType_GenericNew,                   //  tp_new
+  PyObject_Del,                        //  tp_free
+};
+
+// ------ Helper Functions:
+
+static void FormatTypeError(PyObject* arg, char* expected_types) {
+  PyObject* s = PyObject_Str(PyObject_Type(arg));
+  PyObject* repr = PyObject_Repr(PyObject_Type(arg));
+  PyErr_Format(PyExc_TypeError,
+               "%.100s has type %.100s, but expected one of: %s",
+               PyString_AS_STRING(repr),
+               PyString_AS_STRING(s),
+               expected_types);
+  Py_DECREF(s);
+  Py_DECREF(repr);
+}
+
+template <class T>
+static bool CheckAndGetInteger(
+    PyObject* arg, T* value, PyObject* min, PyObject* max) {
+  bool is_long = PyLong_Check(arg);
+  if (!PyInt_Check(arg) && !is_long) {
+    FormatTypeError(arg, "int, long");
+    return false;
+  }
+
+  if (PyObject_Compare(min, arg) > 0 || PyObject_Compare(max, arg) < 0) {
+    PyObject* s = PyObject_Str(arg);
+    PyErr_Format(PyExc_ValueError,
+                 "Value out of range: %s",
+                 PyString_AS_STRING(s));
+    Py_DECREF(s);
+    return false;
+  }
+  if (is_long) {
+    if (min == kPythonZero) {
+      *value = static_cast<T>(PyLong_AsUnsignedLongLong(arg));
+    } else {
+      *value = static_cast<T>(PyLong_AsLongLong(arg));
+    }
+  } else {
+    *value = static_cast<T>(PyInt_AsLong(arg));
+  }
+  return true;
+}
+
+static bool CheckAndGetDouble(PyObject* arg, double* value) {
+  if (!PyInt_Check(arg) && !PyLong_Check(arg) &&
+      !PyFloat_Check(arg)) {
+    FormatTypeError(arg, "int, long, float");
+    return false;
+  }
+  *value = PyFloat_AsDouble(arg);
+  return true;
+}
+
+static bool CheckAndGetFloat(PyObject* arg, float* value) {
+  double double_value;
+  if (!CheckAndGetDouble(arg, &double_value)) {
+    return false;
+  }
+  *value = static_cast<float>(double_value);
+  return true;
+}
+
+static bool CheckAndGetBool(PyObject* arg, bool* value) {
+  if (!PyInt_Check(arg) && !PyBool_Check(arg) && !PyLong_Check(arg)) {
+    FormatTypeError(arg, "int, long, bool");
+    return false;
+  }
+  *value = static_cast<bool>(PyInt_AsLong(arg));
+  return true;
+}
+
+google::protobuf::DynamicMessageFactory* global_message_factory = NULL;
+static const google::protobuf::Message* CreateMessage(const char* message_type) {
+  string message_name(message_type);
+  const google::protobuf::Descriptor* descriptor =
+      GetDescriptorPool()->FindMessageTypeByName(message_name);
+  if (descriptor == NULL) {
+    return NULL;
+  }
+  return global_message_factory->GetPrototype(descriptor);
+}
+
+static bool CheckAndSetString(
+    PyObject* arg, google::protobuf::Message* message,
+    const google::protobuf::FieldDescriptor* descriptor,
+    const google::protobuf::Reflection* reflection,
+    bool append,
+    int index) {
+  GOOGLE_DCHECK(descriptor->type() == google::protobuf::FieldDescriptor::TYPE_STRING ||
+         descriptor->type() == google::protobuf::FieldDescriptor::TYPE_BYTES);
+  if (descriptor->type() == google::protobuf::FieldDescriptor::TYPE_STRING) {
+    if (!PyString_Check(arg) && !PyUnicode_Check(arg)) {
+      FormatTypeError(arg, "str, unicode");
+      return false;
+    }
+
+    if (PyString_Check(arg)) {
+      PyObject* unicode = PyUnicode_FromEncodedObject(arg, "ascii", NULL);
+      if (unicode == NULL) {
+        PyObject* repr = PyObject_Repr(arg);
+        PyErr_Format(PyExc_ValueError,
+                     "%s has type str, but isn't in 7-bit ASCII "
+                     "encoding. Non-ASCII strings must be converted to "
+                     "unicode objects before being added.",
+                     PyString_AS_STRING(repr));
+        Py_DECREF(repr);
+        return false;
+      } else {
+        Py_DECREF(unicode);
+      }
+    }
+  } else if (!PyString_Check(arg)) {
+    FormatTypeError(arg, "str");
+    return false;
+  }
+
+  PyObject* encoded_string = NULL;
+  if (descriptor->type() == google::protobuf::FieldDescriptor::TYPE_STRING) {
+    if (PyString_Check(arg)) {
+      encoded_string = PyString_AsEncodedObject(arg, "utf-8", NULL);
+    } else {
+      encoded_string = PyUnicode_AsEncodedObject(arg, "utf-8", NULL);
+    }
+  } else {
+    // In this case field type is "bytes".
+    encoded_string = arg;
+    Py_INCREF(encoded_string);
+  }
+
+  if (encoded_string == NULL) {
+    return false;
+  }
+
+  char* value;
+  Py_ssize_t value_len;
+  if (PyString_AsStringAndSize(encoded_string, &value, &value_len) < 0) {
+    Py_DECREF(encoded_string);
+    return false;
+  }
+
+  string value_string(value, value_len);
+  if (append) {
+    reflection->AddString(message, descriptor, value_string);
+  } else if (index < 0) {
+    reflection->SetString(message, descriptor, value_string);
+  } else {
+    reflection->SetRepeatedString(message, descriptor, index, value_string);
+  }
+  Py_DECREF(encoded_string);
+  return true;
+}
+
+static PyObject* ToStringObject(
+    const google::protobuf::FieldDescriptor* descriptor, string value) {
+  if (descriptor->type() != google::protobuf::FieldDescriptor::TYPE_STRING) {
+    return PyString_FromStringAndSize(value.c_str(), value.length());
+  }
+
+  PyObject* result = PyUnicode_DecodeUTF8(value.c_str(), value.length(), NULL);
+  // If the string can't be decoded in UTF-8, just return a string object that
+  // contains the raw bytes. This can't happen if the value was assigned using
+  // the members of the Python message object, but can happen if the values were
+  // parsed from the wire (binary).
+  if (result == NULL) {
+    PyErr_Clear();
+    result = PyString_FromStringAndSize(value.c_str(), value.length());
+  }
+  return result;
+}
+
+static void AssureWritable(CMessage* self) {
+  if (self == NULL ||
+      self->parent == NULL ||
+      self->parent_field == NULL) {
+    return;
+  }
+
+  if (!self->read_only) {
+    return;
+  }
+
+  AssureWritable(self->parent);
+
+  google::protobuf::Message* message = self->parent->message;
+  const google::protobuf::Reflection* reflection = message->GetReflection();
+  self->message = reflection->MutableMessage(
+      message, self->parent_field->descriptor, global_message_factory);
+  self->read_only = false;
+  self->parent = NULL;
+  self->parent_field = NULL;
+}
+
+static PyObject* InternalGetScalar(
+    google::protobuf::Message* message,
+    const google::protobuf::FieldDescriptor* field_descriptor) {
+  const google::protobuf::Reflection* reflection = message->GetReflection();
+
+  if (!FIELD_BELONGS_TO_MESSAGE(field_descriptor, message)) {
+    PyErr_SetString(
+        PyExc_KeyError, "Field does not belong to message!");
+    return NULL;
+  }
+
+  PyObject* result = NULL;
+  switch (field_descriptor->cpp_type()) {
+    case google::protobuf::FieldDescriptor::CPPTYPE_INT32: {
+      int32 value = reflection->GetInt32(*message, field_descriptor);
+      result = PyInt_FromLong(value);
+      break;
+    }
+    case google::protobuf::FieldDescriptor::CPPTYPE_INT64: {
+      int64 value = reflection->GetInt64(*message, field_descriptor);
+#if IS_64BIT
+      result = PyInt_FromLong(value);
+#else
+      result = PyLong_FromLongLong(value);
+#endif
+      break;
+    }
+    case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: {
+      uint32 value = reflection->GetUInt32(*message, field_descriptor);
+#if IS_64BIT
+      result = PyInt_FromLong(value);
+#else
+      result = PyLong_FromLongLong(value);
+#endif
+      break;
+    }
+    case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: {
+      uint64 value = reflection->GetUInt64(*message, field_descriptor);
+#if IS_64BIT
+      if (value <= static_cast<uint64>(kint64max)) {
+        result = PyInt_FromLong(static_cast<uint64>(value));
+      }
+#else
+      if (value <= static_cast<uint32>(kint32max)) {
+        result = PyInt_FromLong(static_cast<uint32>(value));
+      }
+#endif
+      else {  // NOLINT
+        result = PyLong_FromUnsignedLongLong(value);
+      }
+      break;
+    }
+    case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: {
+      float value = reflection->GetFloat(*message, field_descriptor);
+      result = PyFloat_FromDouble(value);
+      break;
+    }
+    case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: {
+      double value = reflection->GetDouble(*message, field_descriptor);
+      result = PyFloat_FromDouble(value);
+      break;
+    }
+    case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: {
+      bool value = reflection->GetBool(*message, field_descriptor);
+      result = PyBool_FromLong(value);
+      break;
+    }
+    case google::protobuf::FieldDescriptor::CPPTYPE_STRING: {
+      string value = reflection->GetString(*message, field_descriptor);
+      result = ToStringObject(field_descriptor, value);
+      break;
+    }
+    case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: {
+      if (!message->GetReflection()->HasField(*message, field_descriptor)) {
+        // Look for the value in the unknown fields.
+        google::protobuf::UnknownFieldSet* unknown_field_set =
+            message->GetReflection()->MutableUnknownFields(message);
+        for (int i = 0; i < unknown_field_set->field_count(); ++i) {
+          if (unknown_field_set->field(i).number() ==
+              field_descriptor->number()) {
+            result = PyInt_FromLong(unknown_field_set->field(i).varint());
+            break;
+          }
+        }
+      }
+
+      if (result == NULL) {
+        const google::protobuf::EnumValueDescriptor* enum_value =
+            message->GetReflection()->GetEnum(*message, field_descriptor);
+        result = PyInt_FromLong(enum_value->number());
+      }
+      break;
+    }
+    default:
+      PyErr_Format(
+          PyExc_SystemError, "Getting a value from a field of unknown type %d",
+          field_descriptor->cpp_type());
+  }
+
+  return result;
+}
+
+static PyObject* InternalSetScalar(
+    google::protobuf::Message* message, const google::protobuf::FieldDescriptor* field_descriptor,
+    PyObject* arg) {
+  const google::protobuf::Reflection* reflection = message->GetReflection();
+
+  if (!FIELD_BELONGS_TO_MESSAGE(field_descriptor, message)) {
+    PyErr_SetString(
+        PyExc_KeyError, "Field does not belong to message!");
+    return NULL;
+  }
+
+  switch (field_descriptor->cpp_type()) {
+    case google::protobuf::FieldDescriptor::CPPTYPE_INT32: {
+      GOOGLE_CHECK_GET_INT32(arg, value);
+      reflection->SetInt32(message, field_descriptor, value);
+      break;
+    }
+    case google::protobuf::FieldDescriptor::CPPTYPE_INT64: {
+      GOOGLE_CHECK_GET_INT64(arg, value);
+      reflection->SetInt64(message, field_descriptor, value);
+      break;
+    }
+    case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: {
+      GOOGLE_CHECK_GET_UINT32(arg, value);
+      reflection->SetUInt32(message, field_descriptor, value);
+      break;
+    }
+    case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: {
+      GOOGLE_CHECK_GET_UINT64(arg, value);
+      reflection->SetUInt64(message, field_descriptor, value);
+      break;
+    }
+    case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: {
+      GOOGLE_CHECK_GET_FLOAT(arg, value);
+      reflection->SetFloat(message, field_descriptor, value);
+      break;
+    }
+    case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: {
+      GOOGLE_CHECK_GET_DOUBLE(arg, value);
+      reflection->SetDouble(message, field_descriptor, value);
+      break;
+    }
+    case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: {
+      GOOGLE_CHECK_GET_BOOL(arg, value);
+      reflection->SetBool(message, field_descriptor, value);
+      break;
+    }
+    case google::protobuf::FieldDescriptor::CPPTYPE_STRING: {
+      if (!CheckAndSetString(
+          arg, message, field_descriptor, reflection, false, -1)) {
+        return NULL;
+      }
+      break;
+    }
+    case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: {
+      GOOGLE_CHECK_GET_INT32(arg, value);
+      const google::protobuf::EnumDescriptor* enum_descriptor =
+          field_descriptor->enum_type();
+      const google::protobuf::EnumValueDescriptor* enum_value =
+          enum_descriptor->FindValueByNumber(value);
+      if (enum_value != NULL) {
+        reflection->SetEnum(message, field_descriptor, enum_value);
+      } else {
+        bool added = false;
+        // Add the value to the unknown fields.
+        google::protobuf::UnknownFieldSet* unknown_field_set =
+            message->GetReflection()->MutableUnknownFields(message);
+        for (int i = 0; i < unknown_field_set->field_count(); ++i) {
+          if (unknown_field_set->field(i).number() ==
+              field_descriptor->number()) {
+            unknown_field_set->mutable_field(i)->set_varint(value);
+            added = true;
+            break;
+          }
+        }
+
+        if (!added) {
+          unknown_field_set->AddVarint(field_descriptor->number(), value);
+        }
+        reflection->ClearField(message, field_descriptor);
+      }
+      break;
+    }
+    default:
+      PyErr_Format(
+          PyExc_SystemError, "Setting value to a field of unknown type %d",
+          field_descriptor->cpp_type());
+  }
+
+  Py_RETURN_NONE;
+}
+
+static PyObject* InternalAddRepeatedScalar(
+    google::protobuf::Message* message, const google::protobuf::FieldDescriptor* field_descriptor,
+    PyObject* arg) {
+
+  if (!FIELD_BELONGS_TO_MESSAGE(field_descriptor, message)) {
+    PyErr_SetString(
+        PyExc_KeyError, "Field does not belong to message!");
+    return NULL;
+  }
+
+  const google::protobuf::Reflection* reflection = message->GetReflection();
+  switch (field_descriptor->cpp_type()) {
+    case google::protobuf::FieldDescriptor::CPPTYPE_INT32: {
+      GOOGLE_CHECK_GET_INT32(arg, value);
+      reflection->AddInt32(message, field_descriptor, value);
+      break;
+    }
+    case google::protobuf::FieldDescriptor::CPPTYPE_INT64: {
+      GOOGLE_CHECK_GET_INT64(arg, value);
+      reflection->AddInt64(message, field_descriptor, value);
+      break;
+    }
+    case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: {
+      GOOGLE_CHECK_GET_UINT32(arg, value);
+      reflection->AddUInt32(message, field_descriptor, value);
+      break;
+    }
+    case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: {
+      GOOGLE_CHECK_GET_UINT64(arg, value);
+      reflection->AddUInt64(message, field_descriptor, value);
+      break;
+    }
+    case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: {
+      GOOGLE_CHECK_GET_FLOAT(arg, value);
+      reflection->AddFloat(message, field_descriptor, value);
+      break;
+    }
+    case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: {
+      GOOGLE_CHECK_GET_DOUBLE(arg, value);
+      reflection->AddDouble(message, field_descriptor, value);
+      break;
+    }
+    case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: {
+      GOOGLE_CHECK_GET_BOOL(arg, value);
+      reflection->AddBool(message, field_descriptor, value);
+      break;
+    }
+    case google::protobuf::FieldDescriptor::CPPTYPE_STRING: {
+      if (!CheckAndSetString(
+          arg, message, field_descriptor, reflection, true, -1)) {
+        return NULL;
+      }
+      break;
+    }
+    case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: {
+      GOOGLE_CHECK_GET_INT32(arg, value);
+      const google::protobuf::EnumDescriptor* enum_descriptor =
+          field_descriptor->enum_type();
+      const google::protobuf::EnumValueDescriptor* enum_value =
+          enum_descriptor->FindValueByNumber(value);
+      if (enum_value != NULL) {
+        reflection->AddEnum(message, field_descriptor, enum_value);
+      } else {
+        PyObject* s = PyObject_Str(arg);
+        PyErr_Format(PyExc_ValueError, "Unknown enum value: %s",
+                     PyString_AS_STRING(s));
+        Py_DECREF(s);
+        return NULL;
+      }
+      break;
+    }
+    default:
+      PyErr_Format(
+          PyExc_SystemError, "Adding value to a field of unknown type %d",
+          field_descriptor->cpp_type());
+  }
+
+  Py_RETURN_NONE;
+}
+
+static PyObject* InternalGetRepeatedScalar(
+    CMessage* cmessage, const google::protobuf::FieldDescriptor* field_descriptor,
+    int index) {
+  google::protobuf::Message* message = cmessage->message;
+  const google::protobuf::Reflection* reflection = message->GetReflection();
+
+  int field_size = reflection->FieldSize(*message, field_descriptor);
+  if (index < 0) {
+    index = field_size + index;
+  }
+  if (index < 0 || index >= field_size) {
+    PyErr_Format(PyExc_IndexError,
+                 "list assignment index (%d) out of range", index);
+    return NULL;
+  }
+
+  PyObject* result = NULL;
+  switch (field_descriptor->cpp_type()) {
+    case google::protobuf::FieldDescriptor::CPPTYPE_INT32: {
+      int32 value = reflection->GetRepeatedInt32(
+          *message, field_descriptor, index);
+      result = PyInt_FromLong(value);
+      break;
+    }
+    case google::protobuf::FieldDescriptor::CPPTYPE_INT64: {
+      int64 value = reflection->GetRepeatedInt64(
+          *message, field_descriptor, index);
+      result = PyLong_FromLongLong(value);
+      break;
+    }
+    case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: {
+      uint32 value = reflection->GetRepeatedUInt32(
+          *message, field_descriptor, index);
+      result = PyLong_FromLongLong(value);
+      break;
+    }
+    case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: {
+      uint64 value = reflection->GetRepeatedUInt64(
+          *message, field_descriptor, index);
+      result = PyLong_FromUnsignedLongLong(value);
+      break;
+    }
+    case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: {
+      float value = reflection->GetRepeatedFloat(
+          *message, field_descriptor, index);
+      result = PyFloat_FromDouble(value);
+      break;
+    }
+    case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: {
+      double value = reflection->GetRepeatedDouble(
+          *message, field_descriptor, index);
+      result = PyFloat_FromDouble(value);
+      break;
+    }
+    case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: {
+      bool value = reflection->GetRepeatedBool(
+          *message, field_descriptor, index);
+      result = PyBool_FromLong(value ? 1 : 0);
+      break;
+    }
+    case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: {
+      const google::protobuf::EnumValueDescriptor* enum_value =
+          message->GetReflection()->GetRepeatedEnum(
+              *message, field_descriptor, index);
+      result = PyInt_FromLong(enum_value->number());
+      break;
+    }
+    case google::protobuf::FieldDescriptor::CPPTYPE_STRING: {
+      string value = reflection->GetRepeatedString(
+          *message, field_descriptor, index);
+      result = ToStringObject(field_descriptor, value);
+      break;
+    }
+    case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: {
+      CMessage* py_cmsg = PyObject_New(CMessage, &CMessage_Type);
+      if (py_cmsg == NULL) {
+        return NULL;
+      }
+      const google::protobuf::Message& msg = reflection->GetRepeatedMessage(
+          *message, field_descriptor, index);
+      py_cmsg->parent = cmessage;
+      py_cmsg->full_name = field_descriptor->full_name().c_str();
+      py_cmsg->message = const_cast<google::protobuf::Message*>(&msg);
+      py_cmsg->free_message = false;
+      py_cmsg->read_only = false;
+      result = reinterpret_cast<PyObject*>(py_cmsg);
+      break;
+    }
+    default:
+      PyErr_Format(
+          PyExc_SystemError,
+          "Getting value from a repeated field of unknown type %d",
+          field_descriptor->cpp_type());
+  }
+
+  return result;
+}
+
+static PyObject* InternalGetRepeatedScalarSlice(
+    CMessage* cmessage, const google::protobuf::FieldDescriptor* field_descriptor,
+    PyObject* slice) {
+  Py_ssize_t from;
+  Py_ssize_t to;
+  Py_ssize_t step;
+  Py_ssize_t length;
+  bool return_list = false;
+  google::protobuf::Message* message = cmessage->message;
+
+  if (PyInt_Check(slice)) {
+    from = to = PyInt_AsLong(slice);
+  } else if (PyLong_Check(slice)) {
+    from = to = PyLong_AsLong(slice);
+  } else if (PySlice_Check(slice)) {
+    const google::protobuf::Reflection* reflection = message->GetReflection();
+    length = reflection->FieldSize(*message, field_descriptor);
+    PySlice_GetIndices(
+        reinterpret_cast<PySliceObject*>(slice), length, &from, &to, &step);
+    return_list = true;
+  } else {
+    PyErr_SetString(PyExc_TypeError, "list indices must be integers");
+    return NULL;
+  }
+
+  if (!return_list) {
+    return InternalGetRepeatedScalar(cmessage, field_descriptor, from);
+  }
+
+  PyObject* list = PyList_New(0);
+  if (list == NULL) {
+    return NULL;
+  }
+
+  if (from <= to) {
+    if (step < 0) return list;
+    for (Py_ssize_t index = from; index < to; index += step) {
+      if (index < 0 || index >= length) break;
+      PyObject* s = InternalGetRepeatedScalar(
+          cmessage, field_descriptor, index);
+      PyList_Append(list, s);
+      Py_DECREF(s);
+    }
+  } else {
+    if (step > 0) return list;
+    for (Py_ssize_t index = from; index > to; index += step) {
+      if (index < 0 || index >= length) break;
+      PyObject* s = InternalGetRepeatedScalar(
+          cmessage, field_descriptor, index);
+      PyList_Append(list, s);
+      Py_DECREF(s);
+    }
+  }
+  return list;
+}
+
+// ------ C Constructor/Destructor:
+
+static int CMessageInit(CMessage* self, PyObject *args, PyObject *kwds) {
+  self->message = NULL;
+  return 0;
+}
+
+static void CMessageDealloc(CMessage* self) {
+  if (self->free_message) {
+    if (self->read_only) {
+      PyErr_WriteUnraisable(reinterpret_cast<PyObject*>(self));
+    }
+    delete self->message;
+  }
+  self->ob_type->tp_free(reinterpret_cast<PyObject*>(self));
+}
+
+// ------ Methods:
+
+static PyObject* CMessage_Clear(CMessage* self, PyObject* args) {
+  AssureWritable(self);
+  self->message->Clear();
+  Py_RETURN_NONE;
+}
+
+static PyObject* CMessage_IsInitialized(CMessage* self, PyObject* args) {
+  return PyBool_FromLong(self->message->IsInitialized() ? 1 : 0);
+}
+
+static PyObject* CMessage_HasField(CMessage* self, PyObject* arg) {
+  char* field_name;
+  if (PyString_AsStringAndSize(arg, &field_name, NULL) < 0) {
+    return NULL;
+  }
+
+  google::protobuf::Message* message = self->message;
+  const google::protobuf::Descriptor* descriptor = message->GetDescriptor();
+  const google::protobuf::FieldDescriptor* field_descriptor =
+      descriptor->FindFieldByName(field_name);
+  if (field_descriptor == NULL) {
+    PyErr_Format(PyExc_ValueError, "Unknown field %s.", field_name);
+    return NULL;
+  }
+
+  bool has_field =
+      message->GetReflection()->HasField(*message, field_descriptor);
+  return PyBool_FromLong(has_field ? 1 : 0);
+}
+
+static PyObject* CMessage_HasFieldByDescriptor(CMessage* self, PyObject* arg) {
+  CFieldDescriptor* cfield_descriptor = NULL;
+  if (!PyObject_TypeCheck(reinterpret_cast<PyObject *>(arg),
+                          &CFieldDescriptor_Type)) {
+    PyErr_SetString(PyExc_TypeError, "Must be a field descriptor");
+    return NULL;
+  }
+  cfield_descriptor = reinterpret_cast<CFieldDescriptor*>(arg);
+
+  google::protobuf::Message* message = self->message;
+  const google::protobuf::FieldDescriptor* field_descriptor =
+      cfield_descriptor->descriptor;
+
+  if (!FIELD_BELONGS_TO_MESSAGE(field_descriptor, message)) {
+    PyErr_SetString(PyExc_KeyError,
+                    "Field does not belong to message!");
+    return NULL;
+  }
+
+  if (FIELD_IS_REPEATED(field_descriptor)) {
+    PyErr_SetString(PyExc_KeyError,
+                    "Field is repeated. A singular method is required.");
+    return NULL;
+  }
+
+  bool has_field =
+      message->GetReflection()->HasField(*message, field_descriptor);
+  return PyBool_FromLong(has_field ? 1 : 0);
+}
+
+static PyObject* CMessage_ClearFieldByDescriptor(
+    CMessage* self, PyObject* arg) {
+  CFieldDescriptor* cfield_descriptor = NULL;
+  if (!PyObject_TypeCheck(reinterpret_cast<PyObject *>(arg),
+                          &CFieldDescriptor_Type)) {
+    PyErr_SetString(PyExc_TypeError, "Must be a field descriptor");
+    return NULL;
+  }
+  cfield_descriptor = reinterpret_cast<CFieldDescriptor*>(arg);
+
+  google::protobuf::Message* message = self->message;
+  const google::protobuf::FieldDescriptor* field_descriptor =
+      cfield_descriptor->descriptor;
+
+  if (!FIELD_BELONGS_TO_MESSAGE(field_descriptor, message)) {
+    PyErr_SetString(PyExc_KeyError,
+                    "Field does not belong to message!");
+    return NULL;
+  }
+
+  message->GetReflection()->ClearField(message, field_descriptor);
+  Py_RETURN_NONE;
+}
+
+static PyObject* CMessage_ClearField(CMessage* self, PyObject* arg) {
+  char* field_name;
+  if (PyString_AsStringAndSize(arg, &field_name, NULL) < 0) {
+    return NULL;
+  }
+
+  google::protobuf::Message* message = self->message;
+  const google::protobuf::Descriptor* descriptor = message->GetDescriptor();
+  const google::protobuf::FieldDescriptor* field_descriptor =
+      descriptor->FindFieldByName(field_name);
+  if (field_descriptor == NULL) {
+    PyErr_Format(PyExc_ValueError, "Unknown field %s.", field_name);
+    return NULL;
+  }
+
+  message->GetReflection()->ClearField(message, field_descriptor);
+  Py_RETURN_NONE;
+}
+
+static PyObject* CMessage_GetScalar(CMessage* self, PyObject* arg) {
+  CFieldDescriptor* cdescriptor = NULL;
+  if (!PyObject_TypeCheck(reinterpret_cast<PyObject *>(arg),
+                          &CFieldDescriptor_Type)) {
+    PyErr_SetString(PyExc_TypeError, "Must be a field descriptor");
+    return NULL;
+  }
+  cdescriptor = reinterpret_cast<CFieldDescriptor*>(arg);
+
+  google::protobuf::Message* message = self->message;
+  return InternalGetScalar(message, cdescriptor->descriptor);
+}
+
+static PyObject* CMessage_GetRepeatedScalar(CMessage* self, PyObject* args) {
+  CFieldDescriptor* cfield_descriptor;
+  PyObject* slice;
+  if (!PyArg_ParseTuple(args, C("O!O:GetRepeatedScalar"),
+                        &CFieldDescriptor_Type, &cfield_descriptor, &slice)) {
+    return NULL;
+  }
+
+  return InternalGetRepeatedScalarSlice(
+      self, cfield_descriptor->descriptor, slice);
+}
+
+static PyObject* CMessage_AssignRepeatedScalar(CMessage* self, PyObject* args) {
+  CFieldDescriptor* cfield_descriptor;
+  PyObject* slice;
+  if (!PyArg_ParseTuple(args, C("O!O:AssignRepeatedScalar"),
+                        &CFieldDescriptor_Type, &cfield_descriptor, &slice)) {
+    return NULL;
+  }
+
+  AssureWritable(self);
+  google::protobuf::Message* message = self->message;
+  message->GetReflection()->ClearField(message, cfield_descriptor->descriptor);
+
+  PyObject* iter = PyObject_GetIter(slice);
+  PyObject* next;
+  while ((next = PyIter_Next(iter)) != NULL) {
+    if (InternalAddRepeatedScalar(
+        message, cfield_descriptor->descriptor, next) == NULL) {
+      Py_DECREF(iter);
+      return NULL;
+    }
+  }
+  Py_DECREF(iter);
+  Py_RETURN_NONE;
+}
+
+static PyObject* CMessage_DeleteRepeatedField(CMessage* self, PyObject* args) {
+  CFieldDescriptor* cfield_descriptor;
+  PyObject* slice;
+  if (!PyArg_ParseTuple(args, C("O!O:DeleteRepeatedField"),
+                        &CFieldDescriptor_Type, &cfield_descriptor, &slice)) {
+    return NULL;
+  }
+  AssureWritable(self);
+
+  Py_ssize_t length, from, to, step, slice_length;
+  google::protobuf::Message* message = self->message;
+  const google::protobuf::FieldDescriptor* field_descriptor =
+      cfield_descriptor->descriptor;
+  const google::protobuf::Reflection* reflection = message->GetReflection();
+  int min, max;
+  length = reflection->FieldSize(*message, field_descriptor);
+
+  if (PyInt_Check(slice) || PyLong_Check(slice)) {
+    from = to = PyLong_AsLong(slice);
+    if (from < 0) {
+      from = to = length + from;
+    }
+    step = 1;
+    min = max = from;
+
+    // Range check.
+    if (from < 0 || from >= length) {
+      PyErr_Format(PyExc_IndexError, "list assignment index out of range");
+      return NULL;
+    }
+  } else if (PySlice_Check(slice)) {
+    from = to = step = slice_length = 0;
+    PySlice_GetIndicesEx(
+        reinterpret_cast<PySliceObject*>(slice),
+        length, &from, &to, &step, &slice_length);
+    if (from < to) {
+      min = from;
+      max = to - 1;
+    } else {
+      min = to + 1;
+      max = from;
+    }
+  } else {
+    PyErr_SetString(PyExc_TypeError, "list indices must be integers");
+    return NULL;
+  }
+
+  Py_ssize_t i = from;
+  std::vector<bool> to_delete(length, false);
+  while (i >= min && i <= max) {
+    to_delete[i] = true;
+    i += step;
+  }
+
+  to = 0;
+  for (i = 0; i < length; ++i) {
+    if (!to_delete[i]) {
+      if (i != to) {
+        reflection->SwapElements(message, field_descriptor, i, to);
+      }
+      ++to;
+    }
+  }
+
+  while (i > to) {
+    reflection->RemoveLast(message, field_descriptor);
+    --i;
+  }
+
+  Py_RETURN_NONE;
+}
+
+
+static PyObject* CMessage_SetScalar(CMessage* self, PyObject* args) {
+  CFieldDescriptor* cfield_descriptor;
+  PyObject* arg;
+  if (!PyArg_ParseTuple(args, C("O!O:SetScalar"),
+                        &CFieldDescriptor_Type, &cfield_descriptor, &arg)) {
+    return NULL;
+  }
+  AssureWritable(self);
+
+  return InternalSetScalar(self->message, cfield_descriptor->descriptor, arg);
+}
+
+static PyObject* CMessage_AddRepeatedScalar(CMessage* self, PyObject* args) {
+  CFieldDescriptor* cfield_descriptor;
+  PyObject* value;
+  if (!PyArg_ParseTuple(args, C("O!O:AddRepeatedScalar"),
+                        &CFieldDescriptor_Type, &cfield_descriptor, &value)) {
+    return NULL;
+  }
+  AssureWritable(self);
+
+  return InternalAddRepeatedScalar(
+      self->message, cfield_descriptor->descriptor, value);
+}
+
+static PyObject* CMessage_FieldLength(CMessage* self, PyObject* arg) {
+  CFieldDescriptor* cfield_descriptor;
+  if (!PyObject_TypeCheck(reinterpret_cast<PyObject *>(arg),
+                          &CFieldDescriptor_Type)) {
+    PyErr_SetString(PyExc_TypeError, "Must be a field descriptor");
+    return NULL;
+  }
+  cfield_descriptor = reinterpret_cast<CFieldDescriptor*>(arg);
+
+  google::protobuf::Message* message = self->message;
+  int length = message->GetReflection()->FieldSize(
+      *message, cfield_descriptor->descriptor);
+  return PyInt_FromLong(length);
+}
+
+static PyObject* CMessage_DebugString(CMessage* self, PyObject* args) {
+  return PyString_FromString(self->message->DebugString().c_str());
+}
+
+static PyObject* CMessage_SerializeToString(CMessage* self, PyObject* args) {
+  int size = self->message->ByteSize();
+  if (size <= 0) {
+    return PyString_FromString("");
+  }
+  PyObject* result = PyString_FromStringAndSize(NULL, size);
+  if (result == NULL) {
+    return NULL;
+  }
+  char* buffer = PyString_AS_STRING(result);
+  self->message->SerializeWithCachedSizesToArray(
+      reinterpret_cast<uint8*>(buffer));
+  return result;
+}
+
+static PyObject* CMessage_SerializePartialToString(
+    CMessage* self, PyObject* args) {
+  string contents;
+  self->message->SerializePartialToString(&contents);
+  return PyString_FromStringAndSize(contents.c_str(), contents.size());
+}
+
+static PyObject* CMessageStr(CMessage* self) {
+  char str[1024];
+  str[sizeof(str) - 1] = 0;
+  snprintf(str, sizeof(str) - 1, "CMessage: <%p>", self->message);
+  return PyString_FromString(str);
+}
+
+static PyObject* CMessage_MergeFrom(CMessage* self, PyObject* arg) {
+  CMessage* other_message;
+  if (!PyObject_TypeCheck(reinterpret_cast<PyObject *>(arg), &CMessage_Type)) {
+    PyErr_SetString(PyExc_TypeError, "Must be a message");
+    return NULL;
+  }
+
+  other_message = reinterpret_cast<CMessage*>(arg);
+  if (other_message->message->GetDescriptor() !=
+      self->message->GetDescriptor()) {
+    PyErr_Format(PyExc_TypeError,
+                 "Tried to merge from a message with a different type. "
+                 "to: %s, from: %s",
+                 self->message->GetDescriptor()->full_name().c_str(),
+                 other_message->message->GetDescriptor()->full_name().c_str());
+    return NULL;
+  }
+  AssureWritable(self);
+
+  self->message->MergeFrom(*other_message->message);
+  Py_RETURN_NONE;
+}
+
+static PyObject* CMessage_CopyFrom(CMessage* self, PyObject* arg) {
+  CMessage* other_message;
+  if (!PyObject_TypeCheck(reinterpret_cast<PyObject *>(arg), &CMessage_Type)) {
+    PyErr_SetString(PyExc_TypeError, "Must be a message");
+    return NULL;
+  }
+
+  other_message = reinterpret_cast<CMessage*>(arg);
+  if (other_message->message->GetDescriptor() !=
+      self->message->GetDescriptor()) {
+    PyErr_Format(PyExc_TypeError,
+                 "Tried to copy from a message with a different type. "
+                 "to: %s, from: %s",
+                 self->message->GetDescriptor()->full_name().c_str(),
+                 other_message->message->GetDescriptor()->full_name().c_str());
+    return NULL;
+  }
+
+  AssureWritable(self);
+
+  self->message->CopyFrom(*other_message->message);
+  Py_RETURN_NONE;
+}
+
+static PyObject* CMessage_MergeFromString(CMessage* self, PyObject* arg) {
+  const void* data;
+  Py_ssize_t data_length;
+  if (PyObject_AsReadBuffer(arg, &data, &data_length) < 0) {
+    return NULL;
+  }
+
+  AssureWritable(self);
+  google::protobuf::io::CodedInputStream input(
+      reinterpret_cast<const uint8*>(data), data_length);
+  bool success = self->message->MergePartialFromCodedStream(&input);
+  if (success) {
+    return PyInt_FromLong(self->message->ByteSize());
+  } else {
+    return PyInt_FromLong(-1);
+  }
+}
+
+static PyObject* CMessage_ByteSize(CMessage* self, PyObject* args) {
+  return PyLong_FromLong(self->message->ByteSize());
+}
+
+static PyObject* CMessage_SetInParent(CMessage* self, PyObject* args) {
+  AssureWritable(self);
+  Py_RETURN_NONE;
+}
+
+static PyObject* CMessage_SwapRepeatedFieldElements(
+    CMessage* self, PyObject* args) {
+  CFieldDescriptor* cfield_descriptor;
+  int index1, index2;
+  if (!PyArg_ParseTuple(args, C("O!ii:SwapRepeatedFieldElements"),
+                        &CFieldDescriptor_Type, &cfield_descriptor,
+                        &index1, &index2)) {
+    return NULL;
+  }
+
+  google::protobuf::Message* message = self->message;
+  const google::protobuf::Reflection* reflection = message->GetReflection();
+
+  reflection->SwapElements(
+      message, cfield_descriptor->descriptor, index1, index2);
+  Py_RETURN_NONE;
+}
+
+static PyObject* CMessage_AddMessage(CMessage* self, PyObject* arg) {
+  CFieldDescriptor* cfield_descriptor;
+  if (!PyObject_TypeCheck(reinterpret_cast<PyObject *>(arg),
+                          &CFieldDescriptor_Type)) {
+    PyErr_SetString(PyExc_TypeError, "Must be a field descriptor");
+    return NULL;
+  }
+  cfield_descriptor = reinterpret_cast<CFieldDescriptor*>(arg);
+  AssureWritable(self);
+
+  CMessage* py_cmsg = PyObject_New(CMessage, &CMessage_Type);
+  if (py_cmsg == NULL) {
+    return NULL;
+  }
+
+  google::protobuf::Message* message = self->message;
+  const google::protobuf::Reflection* reflection = message->GetReflection();
+  google::protobuf::Message* sub_message =
+      reflection->AddMessage(message, cfield_descriptor->descriptor);
+
+  py_cmsg->parent = NULL;
+  py_cmsg->full_name = sub_message->GetDescriptor()->full_name().c_str();
+  py_cmsg->message = sub_message;
+  py_cmsg->free_message = false;
+  py_cmsg->read_only = false;
+  return reinterpret_cast<PyObject*>(py_cmsg);
+}
+
+static PyObject* CMessage_GetRepeatedMessage(CMessage* self, PyObject* args) {
+  CFieldDescriptor* cfield_descriptor;
+  PyObject* slice;
+  if (!PyArg_ParseTuple(args, C("O!O:GetRepeatedMessage"),
+                        &CFieldDescriptor_Type, &cfield_descriptor, &slice)) {
+    return NULL;
+  }
+
+  return InternalGetRepeatedScalarSlice(
+      self, cfield_descriptor->descriptor, slice);
+}
+
+static PyObject* CMessage_NewSubMessage(CMessage* self, PyObject* arg) {
+  CFieldDescriptor* cfield_descriptor;
+  if (!PyObject_TypeCheck(reinterpret_cast<PyObject *>(arg),
+                          &CFieldDescriptor_Type)) {
+    PyErr_SetString(PyExc_TypeError, "Must be a field descriptor");
+    return NULL;
+  }
+  cfield_descriptor = reinterpret_cast<CFieldDescriptor*>(arg);
+
+  CMessage* py_cmsg = PyObject_New(CMessage, &CMessage_Type);
+  if (py_cmsg == NULL) {
+    return NULL;
+  }
+
+  google::protobuf::Message* message = self->message;
+  const google::protobuf::Reflection* reflection = message->GetReflection();
+  const google::protobuf::Message& sub_message =
+      reflection->GetMessage(*message, cfield_descriptor->descriptor,
+                             global_message_factory);
+
+  py_cmsg->full_name = sub_message.GetDescriptor()->full_name().c_str();
+  py_cmsg->parent = self;
+  py_cmsg->parent_field = cfield_descriptor;
+  py_cmsg->message = const_cast<google::protobuf::Message*>(&sub_message);
+  py_cmsg->free_message = false;
+  py_cmsg->read_only = true;
+  return reinterpret_cast<PyObject*>(py_cmsg);
+}
+
+static PyObject* CMessage_MutableMessage(CMessage* self, PyObject* arg) {
+  CFieldDescriptor* cfield_descriptor;
+  if (!PyObject_TypeCheck(reinterpret_cast<PyObject *>(arg),
+                          &CFieldDescriptor_Type)) {
+    PyErr_SetString(PyExc_TypeError, "Must be a field descriptor");
+    return NULL;
+  }
+  cfield_descriptor = reinterpret_cast<CFieldDescriptor*>(arg);
+  AssureWritable(self);
+
+  CMessage* py_cmsg = PyObject_New(CMessage, &CMessage_Type);
+  if (py_cmsg == NULL) {
+    return NULL;
+  }
+
+  google::protobuf::Message* message = self->message;
+  const google::protobuf::Reflection* reflection = message->GetReflection();
+  google::protobuf::Message* mutable_message =
+      reflection->MutableMessage(message, cfield_descriptor->descriptor,
+                                 global_message_factory);
+
+  py_cmsg->full_name = mutable_message->GetDescriptor()->full_name().c_str();
+  py_cmsg->message = mutable_message;
+  py_cmsg->free_message = false;
+  py_cmsg->read_only = false;
+  return reinterpret_cast<PyObject*>(py_cmsg);
+}
+
+static PyObject* CMessage_Equals(CMessage* self, PyObject* arg) {
+  CMessage* other_message;
+  if (!PyObject_TypeCheck(reinterpret_cast<PyObject *>(arg), &CMessage_Type)) {
+    PyErr_SetString(PyExc_TypeError, "Must be a message");
+    return NULL;
+  }
+  other_message = reinterpret_cast<CMessage*>(arg);
+
+  if (other_message->message == self->message) {
+    return PyBool_FromLong(1);
+  }
+
+  if (other_message->message->GetDescriptor() !=
+      self->message->GetDescriptor()) {
+    return PyBool_FromLong(0);
+  }
+
+  return PyBool_FromLong(1);
+}
+
+static PyObject* CMessage_ListFields(CMessage* self, PyObject* args) {
+  google::protobuf::Message* message = self->message;
+  const google::protobuf::Reflection* reflection = message->GetReflection();
+  vector<const google::protobuf::FieldDescriptor*> fields;
+  reflection->ListFields(*message, &fields);
+
+  PyObject* list = PyList_New(fields.size());
+  if (list == NULL) {
+    return NULL;
+  }
+
+  for (unsigned int i = 0; i < fields.size(); ++i) {
+    bool is_extension = fields[i]->is_extension();
+    PyObject* t = PyTuple_New(2);
+    if (t == NULL) {
+      Py_DECREF(list);
+      return NULL;
+    }
+
+    PyObject* is_extension_object = PyBool_FromLong(is_extension ? 1 : 0);
+
+    PyObject* field_name;
+    const string* s;
+    if (is_extension) {
+      s = &fields[i]->full_name();
+    } else {
+      s = &fields[i]->name();
+    }
+    field_name = PyString_FromStringAndSize(s->c_str(), s->length());
+    if (field_name == NULL) {
+      Py_DECREF(list);
+      Py_DECREF(t);
+      return NULL;
+    }
+
+    PyTuple_SET_ITEM(t, 0, is_extension_object);
+    PyTuple_SET_ITEM(t, 1, field_name);
+    PyList_SET_ITEM(list, i, t);
+  }
+
+  return list;
+}
+
+static PyObject* CMessage_FindInitializationErrors(CMessage* self) {
+  google::protobuf::Message* message = self->message;
+  vector<string> errors;
+  message->FindInitializationErrors(&errors);
+
+  PyObject* error_list = PyList_New(errors.size());
+  if (error_list == NULL) {
+    return NULL;
+  }
+  for (unsigned int i = 0; i < errors.size(); ++i) {
+    const string& error = errors[i];
+    PyObject* error_string = PyString_FromStringAndSize(
+        error.c_str(), error.length());
+    if (error_string == NULL) {
+      Py_DECREF(error_list);
+      return NULL;
+    }
+    PyList_SET_ITEM(error_list, i, error_string);
+  }
+  return error_list;
+}
+
+// ------ Python Constructor:
+
+PyObject* Python_NewCMessage(PyObject* ignored, PyObject* arg) {
+  const char* message_type = PyString_AsString(arg);
+  if (message_type == NULL) {
+    return NULL;
+  }
+
+  const google::protobuf::Message* message = CreateMessage(message_type);
+  if (message == NULL) {
+    PyErr_Format(PyExc_TypeError, "Couldn't create message of type %s!",
+                 message_type);
+    return NULL;
+  }
+
+  CMessage* py_cmsg = PyObject_New(CMessage, &CMessage_Type);
+  if (py_cmsg == NULL) {
+    return NULL;
+  }
+  py_cmsg->message = message->New();
+  py_cmsg->free_message = true;
+  py_cmsg->full_name = message->GetDescriptor()->full_name().c_str();
+  py_cmsg->read_only = false;
+  py_cmsg->parent = NULL;
+  py_cmsg->parent_field = NULL;
+  return reinterpret_cast<PyObject*>(py_cmsg);
+}
+
+// --- Module Functions (exposed to Python):
+
+PyMethodDef methods[] = {
+  { C("NewCMessage"), (PyCFunction)Python_NewCMessage,
+    METH_O,
+    C("Creates a new C++ protocol message, given its full name.") },
+  { C("NewCDescriptorPool"), (PyCFunction)Python_NewCDescriptorPool,
+    METH_NOARGS,
+    C("Creates a new C++ descriptor pool.") },
+  { C("BuildFile"), (PyCFunction)Python_BuildFile,
+    METH_O,
+    C("Registers a new protocol buffer file in the global C++ descriptor "
+      "pool.") },
+  {NULL}
+};
+
+// --- Exposing the C proto living inside Python proto to C code:
+
+extern const Message* (*GetCProtoInsidePyProtoPtr)(PyObject* msg);
+extern Message* (*MutableCProtoInsidePyProtoPtr)(PyObject* msg);
+
+static const google::protobuf::Message* GetCProtoInsidePyProtoImpl(PyObject* msg) {
+  PyObject* c_msg_obj = PyObject_GetAttrString(msg, "_cmsg");
+  if (c_msg_obj == NULL) {
+    PyErr_Clear();
+    return NULL;
+  }
+  Py_DECREF(c_msg_obj);
+  if (!PyObject_TypeCheck(c_msg_obj, &CMessage_Type)) {
+    return NULL;
+  }
+  CMessage* c_msg = reinterpret_cast<CMessage*>(c_msg_obj);
+  return c_msg->message;
+}
+
+static google::protobuf::Message* MutableCProtoInsidePyProtoImpl(PyObject* msg) {
+  PyObject* c_msg_obj = PyObject_GetAttrString(msg, "_cmsg");
+  if (c_msg_obj == NULL) {
+    PyErr_Clear();
+    return NULL;
+  }
+  Py_DECREF(c_msg_obj);
+  if (!PyObject_TypeCheck(c_msg_obj, &CMessage_Type)) {
+    return NULL;
+  }
+  CMessage* c_msg = reinterpret_cast<CMessage*>(c_msg_obj);
+  AssureWritable(c_msg);
+  return c_msg->message;
+}
+
+// --- Module Init Function:
+
+static const char module_docstring[] =
+"python-proto2 is a module that can be used to enhance proto2 Python API\n"
+"performance.\n"
+"\n"
+"It provides access to the protocol buffers C++ reflection API that\n"
+"implements the basic protocol buffer functions.";
+
+extern "C" {
+  void init_net_proto2___python() {
+    // Initialize constants.
+    kPythonZero = PyInt_FromLong(0);
+    kint32min_py = PyInt_FromLong(kint32min);
+    kint32max_py = PyInt_FromLong(kint32max);
+    kuint32max_py = PyLong_FromLongLong(kuint32max);
+    kint64min_py = PyLong_FromLongLong(kint64min);
+    kint64max_py = PyLong_FromLongLong(kint64max);
+    kuint64max_py = PyLong_FromUnsignedLongLong(kuint64max);
+
+    global_message_factory = new DynamicMessageFactory(GetDescriptorPool());
+    global_message_factory->SetDelegateToGeneratedFactory(true);
+
+    // Export our functions to Python.
+    PyObject *m;
+    m = Py_InitModule3(C("_net_proto2___python"), methods, C(module_docstring));
+    if (m == NULL) {
+      return;
+    }
+
+    AddConstants(m);
+
+    CMessage_Type.tp_new = PyType_GenericNew;
+    if (PyType_Ready(&CMessage_Type) < 0) {
+      return;
+    }
+
+    if (!InitDescriptor()) {
+      return;
+    }
+
+    // Override {Get,Mutable}CProtoInsidePyProto.
+    GetCProtoInsidePyProtoPtr = GetCProtoInsidePyProtoImpl;
+    MutableCProtoInsidePyProtoPtr = MutableCProtoInsidePyProtoImpl;
+  }
+}
+
+}  // namespace python
+}  // namespace protobuf
+}  // namespace google
diff --git a/python/google/protobuf/pyext/python_descriptor.cc b/python/google/protobuf/pyext/python_descriptor.cc
new file mode 100644
index 0000000..fb87bad
--- /dev/null
+++ b/python/google/protobuf/pyext/python_descriptor.cc
@@ -0,0 +1,334 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: petar@google.com (Petar Petrov)
+
+#include <Python.h>
+
+#include <google/protobuf/pyext/python_descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+
+#define C(str) const_cast<char*>(str)
+
+namespace google {
+namespace protobuf {
+namespace python {
+
+static void CFieldDescriptorDealloc(CFieldDescriptor* self);
+
+static google::protobuf::DescriptorPool* g_descriptor_pool = NULL;
+
+static PyObject* CFieldDescriptor_GetFullName(
+    CFieldDescriptor* self, void *closure) {
+  Py_XINCREF(self->full_name);
+  return self->full_name;
+}
+
+static PyObject* CFieldDescriptor_GetName(
+    CFieldDescriptor *self, void *closure) {
+  Py_XINCREF(self->name);
+  return self->name;
+}
+
+static PyObject* CFieldDescriptor_GetCppType(
+    CFieldDescriptor *self, void *closure) {
+  Py_XINCREF(self->cpp_type);
+  return self->cpp_type;
+}
+
+static PyObject* CFieldDescriptor_GetLabel(
+    CFieldDescriptor *self, void *closure) {
+  Py_XINCREF(self->label);
+  return self->label;
+}
+
+static PyObject* CFieldDescriptor_GetID(
+    CFieldDescriptor *self, void *closure) {
+  Py_XINCREF(self->id);
+  return self->id;
+}
+
+
+static PyGetSetDef CFieldDescriptorGetters[] = {
+  { C("full_name"),
+    (getter)CFieldDescriptor_GetFullName, NULL, "Full name", NULL},
+  { C("name"),
+    (getter)CFieldDescriptor_GetName, NULL, "last name", NULL},
+  { C("cpp_type"),
+    (getter)CFieldDescriptor_GetCppType, NULL, "C++ Type", NULL},
+  { C("label"),
+    (getter)CFieldDescriptor_GetLabel, NULL, "Label", NULL},
+  { C("id"),
+    (getter)CFieldDescriptor_GetID, NULL, "ID", NULL},
+  {NULL}
+};
+
+PyTypeObject CFieldDescriptor_Type = {
+  PyObject_HEAD_INIT(&PyType_Type)
+  0,
+  C("google3.net.google.protobuf.python.internal."
+    "_net_proto2___python."
+    "CFieldDescriptor"),                // tp_name
+  sizeof(CFieldDescriptor),             // tp_basicsize
+  0,                                    // tp_itemsize
+  (destructor)CFieldDescriptorDealloc,  // tp_dealloc
+  0,                                    // tp_print
+  0,                                    // tp_getattr
+  0,                                    // tp_setattr
+  0,                                    // tp_compare
+  0,                                    // tp_repr
+  0,                                    // tp_as_number
+  0,                                    // tp_as_sequence
+  0,                                    // tp_as_mapping
+  0,                                    // tp_hash
+  0,                                    // tp_call
+  0,                                    // tp_str
+  0,                                    // tp_getattro
+  0,                                    // tp_setattro
+  0,                                    // tp_as_buffer
+  Py_TPFLAGS_DEFAULT,                   // tp_flags
+  C("A Field Descriptor"),              // tp_doc
+  0,                                    // tp_traverse
+  0,                                    // tp_clear
+  0,                                    // tp_richcompare
+  0,                                    // tp_weaklistoffset
+  0,                                    // tp_iter
+  0,                                    // tp_iternext
+  0,                                    // tp_methods
+  0,                                    // tp_members
+  CFieldDescriptorGetters,              // tp_getset
+  0,                                    // tp_base
+  0,                                    // tp_dict
+  0,                                    // tp_descr_get
+  0,                                    // tp_descr_set
+  0,                                    // tp_dictoffset
+  0,                                    // tp_init
+  PyType_GenericAlloc,                  // tp_alloc
+  PyType_GenericNew,                    // tp_new
+  PyObject_Del,                         // tp_free
+};
+
+static void CFieldDescriptorDealloc(CFieldDescriptor* self) {
+  Py_DECREF(self->full_name);
+  Py_DECREF(self->name);
+  Py_DECREF(self->cpp_type);
+  Py_DECREF(self->label);
+  Py_DECREF(self->id);
+  self->ob_type->tp_free(reinterpret_cast<PyObject*>(self));
+}
+
+typedef struct {
+  PyObject_HEAD
+
+  const google::protobuf::DescriptorPool* pool;
+} CDescriptorPool;
+
+static void CDescriptorPoolDealloc(CDescriptorPool* self);
+
+static PyObject* CDescriptorPool_NewCDescriptor(
+    const google::protobuf::FieldDescriptor* field_descriptor) {
+  CFieldDescriptor* cfield_descriptor = PyObject_New(
+      CFieldDescriptor, &CFieldDescriptor_Type);
+  if (cfield_descriptor == NULL) {
+    return NULL;
+  }
+  cfield_descriptor->descriptor = field_descriptor;
+
+  cfield_descriptor->full_name = PyString_FromString(
+      field_descriptor->full_name().c_str());
+  cfield_descriptor->name = PyString_FromString(
+      field_descriptor->name().c_str());
+  cfield_descriptor->cpp_type = PyLong_FromLong(field_descriptor->cpp_type());
+  cfield_descriptor->label = PyLong_FromLong(field_descriptor->label());
+  cfield_descriptor->id = PyLong_FromVoidPtr(cfield_descriptor);
+  return reinterpret_cast<PyObject*>(cfield_descriptor);
+}
+
+static PyObject* CDescriptorPool_FindFieldByName(
+    CDescriptorPool* self, PyObject* arg) {
+  const char* full_field_name = PyString_AsString(arg);
+  if (full_field_name == NULL) {
+    return NULL;
+  }
+
+  const google::protobuf::FieldDescriptor* field_descriptor = NULL;
+
+  field_descriptor = self->pool->FindFieldByName(full_field_name);
+  if (field_descriptor == NULL) {
+    PyErr_Format(PyExc_TypeError, "Couldn't find field %.200s",
+                 full_field_name);
+    return NULL;
+  }
+
+  return CDescriptorPool_NewCDescriptor(field_descriptor);
+}
+
+static PyObject* CDescriptorPool_FindExtensionByName(
+    CDescriptorPool* self, PyObject* arg) {
+  const char* full_field_name = PyString_AsString(arg);
+  if (full_field_name == NULL) {
+    return NULL;
+  }
+
+  const google::protobuf::FieldDescriptor* field_descriptor =
+      self->pool->FindExtensionByName(full_field_name);
+  if (field_descriptor == NULL) {
+    PyErr_Format(PyExc_TypeError, "Couldn't find field %.200s",
+                 full_field_name);
+    return NULL;
+  }
+
+  return CDescriptorPool_NewCDescriptor(field_descriptor);
+}
+
+static PyMethodDef CDescriptorPoolMethods[] = {
+  { C("FindFieldByName"),
+    (PyCFunction)CDescriptorPool_FindFieldByName,
+    METH_O,
+    C("Searches for a field descriptor by full name.") },
+  { C("FindExtensionByName"),
+    (PyCFunction)CDescriptorPool_FindExtensionByName,
+    METH_O,
+    C("Searches for extension descriptor by full name.") },
+  {NULL}
+};
+
+PyTypeObject CDescriptorPool_Type = {
+  PyObject_HEAD_INIT(&PyType_Type)
+  0,
+  C("google3.net.google.protobuf.python.internal."
+    "_net_proto2___python."
+    "CFieldDescriptor"),               // tp_name
+  sizeof(CDescriptorPool),             // tp_basicsize
+  0,                                   // tp_itemsize
+  (destructor)CDescriptorPoolDealloc,  // tp_dealloc
+  0,                                   // tp_print
+  0,                                   // tp_getattr
+  0,                                   // tp_setattr
+  0,                                   // tp_compare
+  0,                                   // tp_repr
+  0,                                   // tp_as_number
+  0,                                   // tp_as_sequence
+  0,                                   // tp_as_mapping
+  0,                                   // tp_hash
+  0,                                   // tp_call
+  0,                                   // tp_str
+  0,                                   // tp_getattro
+  0,                                   // tp_setattro
+  0,                                   // tp_as_buffer
+  Py_TPFLAGS_DEFAULT,                  // tp_flags
+  C("A Descriptor Pool"),              // tp_doc
+  0,                                   // tp_traverse
+  0,                                   // tp_clear
+  0,                                   // tp_richcompare
+  0,                                   // tp_weaklistoffset
+  0,                                   // tp_iter
+  0,                                   // tp_iternext
+  CDescriptorPoolMethods,              // tp_methods
+  0,                                   // tp_members
+  0,                                   // tp_getset
+  0,                                   // tp_base
+  0,                                   // tp_dict
+  0,                                   // tp_descr_get
+  0,                                   // tp_descr_set
+  0,                                   // tp_dictoffset
+  0,                                   // tp_init
+  PyType_GenericAlloc,                 // tp_alloc
+  PyType_GenericNew,                   // tp_new
+  PyObject_Del,                        // tp_free
+};
+
+static void CDescriptorPoolDealloc(CDescriptorPool* self) {
+  self->ob_type->tp_free(reinterpret_cast<PyObject*>(self));
+}
+
+google::protobuf::DescriptorPool* GetDescriptorPool() {
+  if (g_descriptor_pool == NULL) {
+    g_descriptor_pool = new google::protobuf::DescriptorPool(
+        google::protobuf::DescriptorPool::generated_pool());
+  }
+  return g_descriptor_pool;
+}
+
+PyObject* Python_NewCDescriptorPool(PyObject* ignored, PyObject* args) {
+  CDescriptorPool* cdescriptor_pool = PyObject_New(
+      CDescriptorPool, &CDescriptorPool_Type);
+  if (cdescriptor_pool == NULL) {
+    return NULL;
+  }
+  cdescriptor_pool->pool = GetDescriptorPool();
+  return reinterpret_cast<PyObject*>(cdescriptor_pool);
+}
+
+PyObject* Python_BuildFile(PyObject* ignored, PyObject* arg) {
+  char* message_type;
+  Py_ssize_t message_len;
+
+  if (PyString_AsStringAndSize(arg, &message_type, &message_len) < 0) {
+    return NULL;
+  }
+
+  google::protobuf::FileDescriptorProto file_proto;
+  if (!file_proto.ParseFromArray(message_type, message_len)) {
+    PyErr_SetString(PyExc_TypeError, "Couldn't parse file content!");
+    return NULL;
+  }
+
+  // If this file is already in the generated pool, don't add it again.
+  if (google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
+      file_proto.name()) != NULL) {
+    Py_RETURN_NONE;
+  }
+
+  const google::protobuf::FileDescriptor* descriptor = GetDescriptorPool()->BuildFile(
+      file_proto);
+  if (descriptor == NULL) {
+    PyErr_SetString(PyExc_TypeError,
+                    "Couldn't build proto file into descriptor pool!");
+    return NULL;
+  }
+
+  Py_RETURN_NONE;
+}
+
+bool InitDescriptor() {
+  CFieldDescriptor_Type.tp_new = PyType_GenericNew;
+  if (PyType_Ready(&CFieldDescriptor_Type) < 0)
+    return false;
+
+  CDescriptorPool_Type.tp_new = PyType_GenericNew;
+  if (PyType_Ready(&CDescriptorPool_Type) < 0)
+    return false;
+  return true;
+}
+
+}  // namespace python
+}  // namespace protobuf
+}  // namespace google
diff --git a/python/google/protobuf/pyext/python_descriptor.h b/python/google/protobuf/pyext/python_descriptor.h
new file mode 100644
index 0000000..5232680
--- /dev/null
+++ b/python/google/protobuf/pyext/python_descriptor.h
@@ -0,0 +1,87 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: petar@google.com (Petar Petrov)
+
+#ifndef GOOGLE_PROTOBUF_PYTHON_DESCRIPTOR_H__
+#define GOOGLE_PROTOBUF_PYTHON_DESCRIPTOR_H__
+
+#include <Python.h>
+#include <structmember.h>
+
+#include <google/protobuf/descriptor.h>
+
+#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
+typedef int Py_ssize_t;
+#define PY_SSIZE_T_MAX INT_MAX
+#define PY_SSIZE_T_MIN INT_MIN
+#endif
+
+namespace google {
+namespace protobuf {
+namespace python {
+
+typedef struct {
+  PyObject_HEAD
+
+  // The proto2 descriptor that this object represents.
+  const google::protobuf::FieldDescriptor* descriptor;
+
+  // Full name of the field (PyString).
+  PyObject* full_name;
+
+  // Name of the field (PyString).
+  PyObject* name;
+
+  // C++ type of the field (PyLong).
+  PyObject* cpp_type;
+
+  // Name of the field (PyLong).
+  PyObject* label;
+
+  // Identity of the descriptor (PyLong used as a poiner).
+  PyObject* id;
+} CFieldDescriptor;
+
+extern PyTypeObject CFieldDescriptor_Type;
+
+extern PyTypeObject CDescriptorPool_Type;
+
+
+PyObject* Python_NewCDescriptorPool(PyObject* ignored, PyObject* args);
+PyObject* Python_BuildFile(PyObject* ignored, PyObject* args);
+bool InitDescriptor();
+google::protobuf::DescriptorPool* GetDescriptorPool();
+
+}  // namespace python
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_PYTHON_DESCRIPTOR_H__
diff --git a/python/google/protobuf/pyext/python_protobuf.cc b/python/google/protobuf/pyext/python_protobuf.cc
new file mode 100644
index 0000000..1b1ab5d
--- /dev/null
+++ b/python/google/protobuf/pyext/python_protobuf.cc
@@ -0,0 +1,63 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: qrczak@google.com (Marcin Kowalczyk)
+
+#include <google/protobuf/pyext/python_protobuf.h>
+
+namespace google {
+namespace protobuf {
+namespace python {
+
+static const Message* GetCProtoInsidePyProtoStub(PyObject* msg) {
+  return NULL;
+}
+static Message* MutableCProtoInsidePyProtoStub(PyObject* msg) {
+  return NULL;
+}
+
+// This is initialized with a default, stub implementation.
+// If python-google.protobuf.cc is loaded, the function pointer is overridden
+// with a full implementation.
+const Message* (*GetCProtoInsidePyProtoPtr)(PyObject* msg) =
+    GetCProtoInsidePyProtoStub;
+Message* (*MutableCProtoInsidePyProtoPtr)(PyObject* msg) =
+    MutableCProtoInsidePyProtoStub;
+
+const Message* GetCProtoInsidePyProto(PyObject* msg) {
+  return GetCProtoInsidePyProtoPtr(msg);
+}
+Message* MutableCProtoInsidePyProto(PyObject* msg) {
+  return MutableCProtoInsidePyProtoPtr(msg);
+}
+
+}  // namespace python
+}  // namespace protobuf
+}  // namespace google
diff --git a/python/google/protobuf/pyext/python_protobuf.h b/python/google/protobuf/pyext/python_protobuf.h
new file mode 100644
index 0000000..c5b0b1c
--- /dev/null
+++ b/python/google/protobuf/pyext/python_protobuf.h
@@ -0,0 +1,57 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: qrczak@google.com (Marcin Kowalczyk)
+//
+// This module exposes the C proto inside the given Python proto, in
+// case the Python proto is implemented with a C proto.
+
+#ifndef GOOGLE_PROTOBUF_PYTHON_PYTHON_PROTOBUF_H__
+#define GOOGLE_PROTOBUF_PYTHON_PYTHON_PROTOBUF_H__
+
+#include <Python.h>
+
+namespace google {
+namespace protobuf {
+
+class Message;
+
+namespace python {
+
+// Return the pointer to the C proto inside the given Python proto,
+// or NULL when this is not a Python proto implemented with a C proto.
+const Message* GetCProtoInsidePyProto(PyObject* msg);
+Message* MutableCProtoInsidePyProto(PyObject* msg);
+
+}  // namespace python
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_PYTHON_PYTHON_PROTOBUF_H__
diff --git a/python/google/protobuf/reflection.py b/python/google/protobuf/reflection.py
index 45e5ba8..1373c88 100755
--- a/python/google/protobuf/reflection.py
+++ b/python/google/protobuf/reflection.py
@@ -29,9 +29,6 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 # This code is meant to work on Python 2.4 and above only.
-#
-# TODO(robinson): Helpers for verbose, common checks like seeing if a
-# descriptor's cpp_type is CPPTYPE_MESSAGE.
 
 """Contains a metaclass and helper functions used to create
 protocol message classes from Descriptor objects at runtime.
@@ -50,27 +47,22 @@
 
 __author__ = 'robinson@google.com (Will Robinson)'
 
-try:
-  from cStringIO import StringIO
-except ImportError:
-  from StringIO import StringIO
-import struct
-import weakref
 
-# We use "as" to avoid name collisions with variables.
-from google.protobuf.internal import containers
-from google.protobuf.internal import decoder
-from google.protobuf.internal import encoder
-from google.protobuf.internal import message_listener as message_listener_mod
-from google.protobuf.internal import type_checkers
-from google.protobuf.internal import wire_format
+from google.protobuf.internal import api_implementation
 from google.protobuf import descriptor as descriptor_mod
-from google.protobuf import message as message_mod
-from google.protobuf import text_format
-
 _FieldDescriptor = descriptor_mod.FieldDescriptor
 
 
+if api_implementation.Type() == 'cpp':
+  from google.protobuf.internal import cpp_message
+  _NewMessage = cpp_message.NewMessage
+  _InitMessage = cpp_message.InitMessage
+else:
+  from google.protobuf.internal import python_message
+  _NewMessage = python_message.NewMessage
+  _InitMessage = python_message.InitMessage
+
+
 class GeneratedProtocolMessageType(type):
 
   """Metaclass for protocol message classes created at runtime from Descriptors.
@@ -120,10 +112,12 @@
       Newly-allocated class.
     """
     descriptor = dictionary[GeneratedProtocolMessageType._DESCRIPTOR_KEY]
-    _AddSlots(descriptor, dictionary)
-    _AddClassAttributesForNestedExtensions(descriptor, dictionary)
+    _NewMessage(descriptor, dictionary)
     superclass = super(GeneratedProtocolMessageType, cls)
-    return superclass.__new__(cls, name, bases, dictionary)
+
+    new_class = superclass.__new__(cls, name, bases, dictionary)
+    setattr(descriptor, '_concrete_class', new_class)
+    return new_class
 
   def __init__(cls, name, bases, dictionary):
     """Here we perform the majority of our work on the class.
@@ -143,1018 +137,6 @@
         type.
     """
     descriptor = dictionary[GeneratedProtocolMessageType._DESCRIPTOR_KEY]
-
-    cls._decoders_by_tag = {}
-    cls._extensions_by_name = {}
-    cls._extensions_by_number = {}
-    if (descriptor.has_options and
-        descriptor.GetOptions().message_set_wire_format):
-      cls._decoders_by_tag[decoder.MESSAGE_SET_ITEM_TAG] = (
-          decoder.MessageSetItemDecoder(cls._extensions_by_number))
-
-    # We act as a "friend" class of the descriptor, setting
-    # its _concrete_class attribute the first time we use a
-    # given descriptor to initialize a concrete protocol message
-    # class.  We also attach stuff to each FieldDescriptor for quick
-    # lookup later on.
-    concrete_class_attr_name = '_concrete_class'
-    if not hasattr(descriptor, concrete_class_attr_name):
-      setattr(descriptor, concrete_class_attr_name, cls)
-      for field in descriptor.fields:
-        _AttachFieldHelpers(cls, field)
-
-    _AddEnumValues(descriptor, cls)
-    _AddInitMethod(descriptor, cls)
-    _AddPropertiesForFields(descriptor, cls)
-    _AddPropertiesForExtensions(descriptor, cls)
-    _AddStaticMethods(cls)
-    _AddMessageMethods(descriptor, cls)
-    _AddPrivateHelperMethods(cls)
+    _InitMessage(descriptor, cls)
     superclass = super(GeneratedProtocolMessageType, cls)
     superclass.__init__(name, bases, dictionary)
-
-
-# Stateless helpers for GeneratedProtocolMessageType below.
-# Outside clients should not access these directly.
-#
-# I opted not to make any of these methods on the metaclass, to make it more
-# clear that I'm not really using any state there and to keep clients from
-# thinking that they have direct access to these construction helpers.
-
-
-def _PropertyName(proto_field_name):
-  """Returns the name of the public property attribute which
-  clients can use to get and (in some cases) set the value
-  of a protocol message field.
-
-  Args:
-    proto_field_name: The protocol message field name, exactly
-      as it appears (or would appear) in a .proto file.
-  """
-  # TODO(robinson): Escape Python keywords (e.g., yield), and test this support.
-  # nnorwitz makes my day by writing:
-  # """
-  # FYI.  See the keyword module in the stdlib. This could be as simple as:
-  #
-  # if keyword.iskeyword(proto_field_name):
-  #   return proto_field_name + "_"
-  # return proto_field_name
-  # """
-  # Kenton says:  The above is a BAD IDEA.  People rely on being able to use
-  #   getattr() and setattr() to reflectively manipulate field values.  If we
-  #   rename the properties, then every such user has to also make sure to apply
-  #   the same transformation.  Note that currently if you name a field "yield",
-  #   you can still access it just fine using getattr/setattr -- it's not even
-  #   that cumbersome to do so.
-  # TODO(kenton):  Remove this method entirely if/when everyone agrees with my
-  #   position.
-  return proto_field_name
-
-
-def _VerifyExtensionHandle(message, extension_handle):
-  """Verify that the given extension handle is valid."""
-
-  if not isinstance(extension_handle, _FieldDescriptor):
-    raise KeyError('HasExtension() expects an extension handle, got: %s' %
-                   extension_handle)
-
-  if not extension_handle.is_extension:
-    raise KeyError('"%s" is not an extension.' % extension_handle.full_name)
-
-  if extension_handle.containing_type is not message.DESCRIPTOR:
-    raise KeyError('Extension "%s" extends message type "%s", but this '
-                   'message is of type "%s".' %
-                   (extension_handle.full_name,
-                    extension_handle.containing_type.full_name,
-                    message.DESCRIPTOR.full_name))
-
-
-def _AddSlots(message_descriptor, dictionary):
-  """Adds a __slots__ entry to dictionary, containing the names of all valid
-  attributes for this message type.
-
-  Args:
-    message_descriptor: A Descriptor instance describing this message type.
-    dictionary: Class dictionary to which we'll add a '__slots__' entry.
-  """
-  dictionary['__slots__'] = ['_cached_byte_size',
-                             '_cached_byte_size_dirty',
-                             '_fields',
-                             '_is_present_in_parent',
-                             '_listener',
-                             '_listener_for_children',
-                             '__weakref__']
-
-
-def _IsMessageSetExtension(field):
-  return (field.is_extension and
-          field.containing_type.has_options and
-          field.containing_type.GetOptions().message_set_wire_format and
-          field.type == _FieldDescriptor.TYPE_MESSAGE and
-          field.message_type == field.extension_scope and
-          field.label == _FieldDescriptor.LABEL_OPTIONAL)
-
-
-def _AttachFieldHelpers(cls, field_descriptor):
-  is_repeated = (field_descriptor.label == _FieldDescriptor.LABEL_REPEATED)
-  is_packed = (field_descriptor.has_options and
-               field_descriptor.GetOptions().packed)
-
-  if _IsMessageSetExtension(field_descriptor):
-    field_encoder = encoder.MessageSetItemEncoder(field_descriptor.number)
-    sizer = encoder.MessageSetItemSizer(field_descriptor.number)
-  else:
-    field_encoder = type_checkers.TYPE_TO_ENCODER[field_descriptor.type](
-        field_descriptor.number, is_repeated, is_packed)
-    sizer = type_checkers.TYPE_TO_SIZER[field_descriptor.type](
-        field_descriptor.number, is_repeated, is_packed)
-
-  field_descriptor._encoder = field_encoder
-  field_descriptor._sizer = sizer
-  field_descriptor._default_constructor = _DefaultValueConstructorForField(
-      field_descriptor)
-
-  def AddDecoder(wiretype, is_packed):
-    tag_bytes = encoder.TagBytes(field_descriptor.number, wiretype)
-    cls._decoders_by_tag[tag_bytes] = (
-        type_checkers.TYPE_TO_DECODER[field_descriptor.type](
-            field_descriptor.number, is_repeated, is_packed,
-            field_descriptor, field_descriptor._default_constructor))
-
-  AddDecoder(type_checkers.FIELD_TYPE_TO_WIRE_TYPE[field_descriptor.type],
-             False)
-
-  if is_repeated and wire_format.IsTypePackable(field_descriptor.type):
-    # To support wire compatibility of adding packed = true, add a decoder for
-    # packed values regardless of the field's options.
-    AddDecoder(wire_format.WIRETYPE_LENGTH_DELIMITED, True)
-
-
-def _AddClassAttributesForNestedExtensions(descriptor, dictionary):
-  extension_dict = descriptor.extensions_by_name
-  for extension_name, extension_field in extension_dict.iteritems():
-    assert extension_name not in dictionary
-    dictionary[extension_name] = extension_field
-
-
-def _AddEnumValues(descriptor, cls):
-  """Sets class-level attributes for all enum fields defined in this message.
-
-  Args:
-    descriptor: Descriptor object for this message type.
-    cls: Class we're constructing for this message type.
-  """
-  for enum_type in descriptor.enum_types:
-    for enum_value in enum_type.values:
-      setattr(cls, enum_value.name, enum_value.number)
-
-
-def _DefaultValueConstructorForField(field):
-  """Returns a function which returns a default value for a field.
-
-  Args:
-    field: FieldDescriptor object for this field.
-
-  The returned function has one argument:
-    message: Message instance containing this field, or a weakref proxy
-      of same.
-
-  That function in turn returns a default value for this field.  The default
-    value may refer back to |message| via a weak reference.
-  """
-
-  if field.label == _FieldDescriptor.LABEL_REPEATED:
-    if field.default_value != []:
-      raise ValueError('Repeated field default value not empty list: %s' % (
-          field.default_value))
-    if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
-      # We can't look at _concrete_class yet since it might not have
-      # been set.  (Depends on order in which we initialize the classes).
-      message_type = field.message_type
-      def MakeRepeatedMessageDefault(message):
-        return containers.RepeatedCompositeFieldContainer(
-            message._listener_for_children, field.message_type)
-      return MakeRepeatedMessageDefault
-    else:
-      type_checker = type_checkers.GetTypeChecker(field.cpp_type, field.type)
-      def MakeRepeatedScalarDefault(message):
-        return containers.RepeatedScalarFieldContainer(
-            message._listener_for_children, type_checker)
-      return MakeRepeatedScalarDefault
-
-  if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
-    # _concrete_class may not yet be initialized.
-    message_type = field.message_type
-    def MakeSubMessageDefault(message):
-      result = message_type._concrete_class()
-      result._SetListener(message._listener_for_children)
-      return result
-    return MakeSubMessageDefault
-
-  def MakeScalarDefault(message):
-    return field.default_value
-  return MakeScalarDefault
-
-
-def _AddInitMethod(message_descriptor, cls):
-  """Adds an __init__ method to cls."""
-  fields = message_descriptor.fields
-  def init(self, **kwargs):
-    self._cached_byte_size = 0
-    self._cached_byte_size_dirty = False
-    self._fields = {}
-    self._is_present_in_parent = False
-    self._listener = message_listener_mod.NullMessageListener()
-    self._listener_for_children = _Listener(self)
-    for field_name, field_value in kwargs.iteritems():
-      field = _GetFieldByName(message_descriptor, field_name)
-      if field is None:
-        raise TypeError("%s() got an unexpected keyword argument '%s'" %
-                        (message_descriptor.name, field_name))
-      if field.label == _FieldDescriptor.LABEL_REPEATED:
-        copy = field._default_constructor(self)
-        if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:  # Composite
-          for val in field_value:
-            copy.add().MergeFrom(val)
-        else:  # Scalar
-          copy.extend(field_value)
-        self._fields[field] = copy
-      elif field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
-        copy = field._default_constructor(self)
-        copy.MergeFrom(field_value)
-        self._fields[field] = copy
-      else:
-        setattr(self, field_name, field_value)
-
-  init.__module__ = None
-  init.__doc__ = None
-  cls.__init__ = init
-
-
-def _GetFieldByName(message_descriptor, field_name):
-  """Returns a field descriptor by field name.
-
-  Args:
-    message_descriptor: A Descriptor describing all fields in message.
-    field_name: The name of the field to retrieve.
-  Returns:
-    The field descriptor associated with the field name.
-  """
-  try:
-    return message_descriptor.fields_by_name[field_name]
-  except KeyError:
-    raise ValueError('Protocol message has no "%s" field.' % field_name)
-
-
-def _AddPropertiesForFields(descriptor, cls):
-  """Adds properties for all fields in this protocol message type."""
-  for field in descriptor.fields:
-    _AddPropertiesForField(field, cls)
-
-  if descriptor.is_extendable:
-    # _ExtensionDict is just an adaptor with no state so we allocate a new one
-    # every time it is accessed.
-    cls.Extensions = property(lambda self: _ExtensionDict(self))
-
-
-def _AddPropertiesForField(field, cls):
-  """Adds a public property for a protocol message field.
-  Clients can use this property to get and (in the case
-  of non-repeated scalar fields) directly set the value
-  of a protocol message field.
-
-  Args:
-    field: A FieldDescriptor for this field.
-    cls: The class we're constructing.
-  """
-  # Catch it if we add other types that we should
-  # handle specially here.
-  assert _FieldDescriptor.MAX_CPPTYPE == 10
-
-  constant_name = field.name.upper() + "_FIELD_NUMBER"
-  setattr(cls, constant_name, field.number)
-
-  if field.label == _FieldDescriptor.LABEL_REPEATED:
-    _AddPropertiesForRepeatedField(field, cls)
-  elif field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
-    _AddPropertiesForNonRepeatedCompositeField(field, cls)
-  else:
-    _AddPropertiesForNonRepeatedScalarField(field, cls)
-
-
-def _AddPropertiesForRepeatedField(field, cls):
-  """Adds a public property for a "repeated" protocol message field.  Clients
-  can use this property to get the value of the field, which will be either a
-  _RepeatedScalarFieldContainer or _RepeatedCompositeFieldContainer (see
-  below).
-
-  Note that when clients add values to these containers, we perform
-  type-checking in the case of repeated scalar fields, and we also set any
-  necessary "has" bits as a side-effect.
-
-  Args:
-    field: A FieldDescriptor for this field.
-    cls: The class we're constructing.
-  """
-  proto_field_name = field.name
-  property_name = _PropertyName(proto_field_name)
-
-  def getter(self):
-    field_value = self._fields.get(field)
-    if field_value is None:
-      # Construct a new object to represent this field.
-      field_value = field._default_constructor(self)
-
-      # Atomically check if another thread has preempted us and, if not, swap
-      # in the new object we just created.  If someone has preempted us, we
-      # take that object and discard ours.
-      # WARNING:  We are relying on setdefault() being atomic.  This is true
-      #   in CPython but we haven't investigated others.  This warning appears
-      #   in several other locations in this file.
-      field_value = self._fields.setdefault(field, field_value)
-    return field_value
-  getter.__module__ = None
-  getter.__doc__ = 'Getter for %s.' % proto_field_name
-
-  # We define a setter just so we can throw an exception with a more
-  # helpful error message.
-  def setter(self, new_value):
-    raise AttributeError('Assignment not allowed to repeated field '
-                         '"%s" in protocol message object.' % proto_field_name)
-
-  doc = 'Magic attribute generated for "%s" proto field.' % proto_field_name
-  setattr(cls, property_name, property(getter, setter, doc=doc))
-
-
-def _AddPropertiesForNonRepeatedScalarField(field, cls):
-  """Adds a public property for a nonrepeated, scalar protocol message field.
-  Clients can use this property to get and directly set the value of the field.
-  Note that when the client sets the value of a field by using this property,
-  all necessary "has" bits are set as a side-effect, and we also perform
-  type-checking.
-
-  Args:
-    field: A FieldDescriptor for this field.
-    cls: The class we're constructing.
-  """
-  proto_field_name = field.name
-  property_name = _PropertyName(proto_field_name)
-  type_checker = type_checkers.GetTypeChecker(field.cpp_type, field.type)
-  default_value = field.default_value
-
-  def getter(self):
-    return self._fields.get(field, default_value)
-  getter.__module__ = None
-  getter.__doc__ = 'Getter for %s.' % proto_field_name
-  def setter(self, new_value):
-    type_checker.CheckValue(new_value)
-    self._fields[field] = new_value
-    # Check _cached_byte_size_dirty inline to improve performance, since scalar
-    # setters are called frequently.
-    if not self._cached_byte_size_dirty:
-      self._Modified()
-  setter.__module__ = None
-  setter.__doc__ = 'Setter for %s.' % proto_field_name
-
-  # Add a property to encapsulate the getter/setter.
-  doc = 'Magic attribute generated for "%s" proto field.' % proto_field_name
-  setattr(cls, property_name, property(getter, setter, doc=doc))
-
-
-def _AddPropertiesForNonRepeatedCompositeField(field, cls):
-  """Adds a public property for a nonrepeated, composite protocol message field.
-  A composite field is a "group" or "message" field.
-
-  Clients can use this property to get the value of the field, but cannot
-  assign to the property directly.
-
-  Args:
-    field: A FieldDescriptor for this field.
-    cls: The class we're constructing.
-  """
-  # TODO(robinson): Remove duplication with similar method
-  # for non-repeated scalars.
-  proto_field_name = field.name
-  property_name = _PropertyName(proto_field_name)
-  message_type = field.message_type
-
-  def getter(self):
-    field_value = self._fields.get(field)
-    if field_value is None:
-      # Construct a new object to represent this field.
-      field_value = message_type._concrete_class()
-      field_value._SetListener(self._listener_for_children)
-
-      # Atomically check if another thread has preempted us and, if not, swap
-      # in the new object we just created.  If someone has preempted us, we
-      # take that object and discard ours.
-      # WARNING:  We are relying on setdefault() being atomic.  This is true
-      #   in CPython but we haven't investigated others.  This warning appears
-      #   in several other locations in this file.
-      field_value = self._fields.setdefault(field, field_value)
-    return field_value
-  getter.__module__ = None
-  getter.__doc__ = 'Getter for %s.' % proto_field_name
-
-  # We define a setter just so we can throw an exception with a more
-  # helpful error message.
-  def setter(self, new_value):
-    raise AttributeError('Assignment not allowed to composite field '
-                         '"%s" in protocol message object.' % proto_field_name)
-
-  # Add a property to encapsulate the getter.
-  doc = 'Magic attribute generated for "%s" proto field.' % proto_field_name
-  setattr(cls, property_name, property(getter, setter, doc=doc))
-
-
-def _AddPropertiesForExtensions(descriptor, cls):
-  """Adds properties for all fields in this protocol message type."""
-  extension_dict = descriptor.extensions_by_name
-  for extension_name, extension_field in extension_dict.iteritems():
-    constant_name = extension_name.upper() + "_FIELD_NUMBER"
-    setattr(cls, constant_name, extension_field.number)
-
-
-def _AddStaticMethods(cls):
-  # TODO(robinson): This probably needs to be thread-safe(?)
-  def RegisterExtension(extension_handle):
-    extension_handle.containing_type = cls.DESCRIPTOR
-    _AttachFieldHelpers(cls, extension_handle)
-
-    # Try to insert our extension, failing if an extension with the same number
-    # already exists.
-    actual_handle = cls._extensions_by_number.setdefault(
-        extension_handle.number, extension_handle)
-    if actual_handle is not extension_handle:
-      raise AssertionError(
-          'Extensions "%s" and "%s" both try to extend message type "%s" with '
-          'field number %d.' %
-          (extension_handle.full_name, actual_handle.full_name,
-           cls.DESCRIPTOR.full_name, extension_handle.number))
-
-    cls._extensions_by_name[extension_handle.full_name] = extension_handle
-
-    handle = extension_handle  # avoid line wrapping
-    if _IsMessageSetExtension(handle):
-      # MessageSet extension.  Also register under type name.
-      cls._extensions_by_name[
-          extension_handle.message_type.full_name] = extension_handle
-
-  cls.RegisterExtension = staticmethod(RegisterExtension)
-
-  def FromString(s):
-    message = cls()
-    message.MergeFromString(s)
-    return message
-  cls.FromString = staticmethod(FromString)
-
-
-def _IsPresent(item):
-  """Given a (FieldDescriptor, value) tuple from _fields, return true if the
-  value should be included in the list returned by ListFields()."""
-
-  if item[0].label == _FieldDescriptor.LABEL_REPEATED:
-    return bool(item[1])
-  elif item[0].cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
-    return item[1]._is_present_in_parent
-  else:
-    return True
-
-
-def _AddListFieldsMethod(message_descriptor, cls):
-  """Helper for _AddMessageMethods()."""
-
-  def ListFields(self):
-    all_fields = [item for item in self._fields.iteritems() if _IsPresent(item)]
-    all_fields.sort(key = lambda item: item[0].number)
-    return all_fields
-
-  cls.ListFields = ListFields
-
-
-def _AddHasFieldMethod(message_descriptor, cls):
-  """Helper for _AddMessageMethods()."""
-
-  singular_fields = {}
-  for field in message_descriptor.fields:
-    if field.label != _FieldDescriptor.LABEL_REPEATED:
-      singular_fields[field.name] = field
-
-  def HasField(self, field_name):
-    try:
-      field = singular_fields[field_name]
-    except KeyError:
-      raise ValueError(
-          'Protocol message has no singular "%s" field.' % field_name)
-
-    if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
-      value = self._fields.get(field)
-      return value is not None and value._is_present_in_parent
-    else:
-      return field in self._fields
-  cls.HasField = HasField
-
-
-def _AddClearFieldMethod(message_descriptor, cls):
-  """Helper for _AddMessageMethods()."""
-  def ClearField(self, field_name):
-    try:
-      field = message_descriptor.fields_by_name[field_name]
-    except KeyError:
-      raise ValueError('Protocol message has no "%s" field.' % field_name)
-
-    if field in self._fields:
-      # Note:  If the field is a sub-message, its listener will still point
-      #   at us.  That's fine, because the worst than can happen is that it
-      #   will call _Modified() and invalidate our byte size.  Big deal.
-      del self._fields[field]
-
-    # Always call _Modified() -- even if nothing was changed, this is
-    # a mutating method, and thus calling it should cause the field to become
-    # present in the parent message.
-    self._Modified()
-
-  cls.ClearField = ClearField
-
-
-def _AddClearExtensionMethod(cls):
-  """Helper for _AddMessageMethods()."""
-  def ClearExtension(self, extension_handle):
-    _VerifyExtensionHandle(self, extension_handle)
-
-    # Similar to ClearField(), above.
-    if extension_handle in self._fields:
-      del self._fields[extension_handle]
-    self._Modified()
-  cls.ClearExtension = ClearExtension
-
-
-def _AddClearMethod(message_descriptor, cls):
-  """Helper for _AddMessageMethods()."""
-  def Clear(self):
-    # Clear fields.
-    self._fields = {}
-    self._Modified()
-  cls.Clear = Clear
-
-
-def _AddHasExtensionMethod(cls):
-  """Helper for _AddMessageMethods()."""
-  def HasExtension(self, extension_handle):
-    _VerifyExtensionHandle(self, extension_handle)
-    if extension_handle.label == _FieldDescriptor.LABEL_REPEATED:
-      raise KeyError('"%s" is repeated.' % extension_handle.full_name)
-
-    if extension_handle.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
-      value = self._fields.get(extension_handle)
-      return value is not None and value._is_present_in_parent
-    else:
-      return extension_handle in self._fields
-  cls.HasExtension = HasExtension
-
-
-def _AddEqualsMethod(message_descriptor, cls):
-  """Helper for _AddMessageMethods()."""
-  def __eq__(self, other):
-    if (not isinstance(other, message_mod.Message) or
-        other.DESCRIPTOR != self.DESCRIPTOR):
-      return False
-
-    if self is other:
-      return True
-
-    return self.ListFields() == other.ListFields()
-
-  cls.__eq__ = __eq__
-
-
-def _AddStrMethod(message_descriptor, cls):
-  """Helper for _AddMessageMethods()."""
-  def __str__(self):
-    return text_format.MessageToString(self)
-  cls.__str__ = __str__
-
-
-def _AddSetListenerMethod(cls):
-  """Helper for _AddMessageMethods()."""
-  def SetListener(self, listener):
-    if listener is None:
-      self._listener = message_listener_mod.NullMessageListener()
-    else:
-      self._listener = listener
-  cls._SetListener = SetListener
-
-
-def _BytesForNonRepeatedElement(value, field_number, field_type):
-  """Returns the number of bytes needed to serialize a non-repeated element.
-  The returned byte count includes space for tag information and any
-  other additional space associated with serializing value.
-
-  Args:
-    value: Value we're serializing.
-    field_number: Field number of this value.  (Since the field number
-      is stored as part of a varint-encoded tag, this has an impact
-      on the total bytes required to serialize the value).
-    field_type: The type of the field.  One of the TYPE_* constants
-      within FieldDescriptor.
-  """
-  try:
-    fn = type_checkers.TYPE_TO_BYTE_SIZE_FN[field_type]
-    return fn(field_number, value)
-  except KeyError:
-    raise message_mod.EncodeError('Unrecognized field type: %d' % field_type)
-
-
-def _AddByteSizeMethod(message_descriptor, cls):
-  """Helper for _AddMessageMethods()."""
-
-  def ByteSize(self):
-    if not self._cached_byte_size_dirty:
-      return self._cached_byte_size
-
-    size = 0
-    for field_descriptor, field_value in self.ListFields():
-      size += field_descriptor._sizer(field_value)
-
-    self._cached_byte_size = size
-    self._cached_byte_size_dirty = False
-    self._listener_for_children.dirty = False
-    return size
-
-  cls.ByteSize = ByteSize
-
-
-def _AddSerializeToStringMethod(message_descriptor, cls):
-  """Helper for _AddMessageMethods()."""
-
-  def SerializeToString(self):
-    # Check if the message has all of its required fields set.
-    errors = []
-    if not self.IsInitialized():
-      raise message_mod.EncodeError(
-          'Message is missing required fields: ' +
-          ','.join(self.FindInitializationErrors()))
-    return self.SerializePartialToString()
-  cls.SerializeToString = SerializeToString
-
-
-def _AddSerializePartialToStringMethod(message_descriptor, cls):
-  """Helper for _AddMessageMethods()."""
-
-  def SerializePartialToString(self):
-    out = StringIO()
-    self._InternalSerialize(out.write)
-    return out.getvalue()
-  cls.SerializePartialToString = SerializePartialToString
-
-  def InternalSerialize(self, write_bytes):
-    for field_descriptor, field_value in self.ListFields():
-      field_descriptor._encoder(write_bytes, field_value)
-  cls._InternalSerialize = InternalSerialize
-
-
-def _AddMergeFromStringMethod(message_descriptor, cls):
-  """Helper for _AddMessageMethods()."""
-  def MergeFromString(self, serialized):
-    length = len(serialized)
-    try:
-      if self._InternalParse(serialized, 0, length) != length:
-        # The only reason _InternalParse would return early is if it
-        # encountered an end-group tag.
-        raise message_mod.DecodeError('Unexpected end-group tag.')
-    except IndexError:
-      raise message_mod.DecodeError('Truncated message.')
-    except struct.error, e:
-      raise message_mod.DecodeError(e)
-    return length   # Return this for legacy reasons.
-  cls.MergeFromString = MergeFromString
-
-  local_ReadTag = decoder.ReadTag
-  local_SkipField = decoder.SkipField
-  decoders_by_tag = cls._decoders_by_tag
-
-  def InternalParse(self, buffer, pos, end):
-    self._Modified()
-    field_dict = self._fields
-    while pos != end:
-      (tag_bytes, new_pos) = local_ReadTag(buffer, pos)
-      field_decoder = decoders_by_tag.get(tag_bytes)
-      if field_decoder is None:
-        new_pos = local_SkipField(buffer, new_pos, end, tag_bytes)
-        if new_pos == -1:
-          return pos
-        pos = new_pos
-      else:
-        pos = field_decoder(buffer, new_pos, end, self, field_dict)
-    return pos
-  cls._InternalParse = InternalParse
-
-
-def _AddIsInitializedMethod(message_descriptor, cls):
-  """Adds the IsInitialized and FindInitializationError methods to the
-  protocol message class."""
-
-  required_fields = [field for field in message_descriptor.fields
-                           if field.label == _FieldDescriptor.LABEL_REQUIRED]
-
-  def IsInitialized(self, errors=None):
-    """Checks if all required fields of a message are set.
-
-    Args:
-      errors:  A list which, if provided, will be populated with the field
-               paths of all missing required fields.
-
-    Returns:
-      True iff the specified message has all required fields set.
-    """
-
-    # Performance is critical so we avoid HasField() and ListFields().
-
-    for field in required_fields:
-      if (field not in self._fields or
-          (field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE and
-           not self._fields[field]._is_present_in_parent)):
-        if errors is not None:
-          errors.extend(self.FindInitializationErrors())
-        return False
-
-    for field, value in self._fields.iteritems():
-      if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
-        if field.label == _FieldDescriptor.LABEL_REPEATED:
-          for element in value:
-            if not element.IsInitialized():
-              if errors is not None:
-                errors.extend(self.FindInitializationErrors())
-              return False
-        elif value._is_present_in_parent and not value.IsInitialized():
-          if errors is not None:
-            errors.extend(self.FindInitializationErrors())
-          return False
-
-    return True
-
-  cls.IsInitialized = IsInitialized
-
-  def FindInitializationErrors(self):
-    """Finds required fields which are not initialized.
-
-    Returns:
-      A list of strings.  Each string is a path to an uninitialized field from
-      the top-level message, e.g. "foo.bar[5].baz".
-    """
-
-    errors = []  # simplify things
-
-    for field in required_fields:
-      if not self.HasField(field.name):
-        errors.append(field.name)
-
-    for field, value in self.ListFields():
-      if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
-        if field.is_extension:
-          name = "(%s)" % field.full_name
-        else:
-          name = field.name
-
-        if field.label == _FieldDescriptor.LABEL_REPEATED:
-          for i in xrange(len(value)):
-            element = value[i]
-            prefix = "%s[%d]." % (name, i)
-            sub_errors = element.FindInitializationErrors()
-            errors += [ prefix + error for error in sub_errors ]
-        else:
-          prefix = name + "."
-          sub_errors = value.FindInitializationErrors()
-          errors += [ prefix + error for error in sub_errors ]
-
-    return errors
-
-  cls.FindInitializationErrors = FindInitializationErrors
-
-
-def _AddMergeFromMethod(cls):
-  LABEL_REPEATED = _FieldDescriptor.LABEL_REPEATED
-  CPPTYPE_MESSAGE = _FieldDescriptor.CPPTYPE_MESSAGE
-
-  def MergeFrom(self, msg):
-    if not isinstance(msg, cls):
-      raise TypeError(
-          "Parameter to MergeFrom() must be instance of same class.")
-
-    assert msg is not self
-    self._Modified()
-
-    fields = self._fields
-
-    for field, value in msg._fields.iteritems():
-      if field.label == LABEL_REPEATED:
-        field_value = fields.get(field)
-        if field_value is None:
-          # Construct a new object to represent this field.
-          field_value = field._default_constructor(self)
-          fields[field] = field_value
-        field_value.MergeFrom(value)
-      elif field.cpp_type == CPPTYPE_MESSAGE:
-        if value._is_present_in_parent:
-          field_value = fields.get(field)
-          if field_value is None:
-            # Construct a new object to represent this field.
-            field_value = field._default_constructor(self)
-            fields[field] = field_value
-          field_value.MergeFrom(value)
-      else:
-        self._fields[field] = value
-  cls.MergeFrom = MergeFrom
-
-
-def _AddMessageMethods(message_descriptor, cls):
-  """Adds implementations of all Message methods to cls."""
-  _AddListFieldsMethod(message_descriptor, cls)
-  _AddHasFieldMethod(message_descriptor, cls)
-  _AddClearFieldMethod(message_descriptor, cls)
-  if message_descriptor.is_extendable:
-    _AddClearExtensionMethod(cls)
-    _AddHasExtensionMethod(cls)
-  _AddClearMethod(message_descriptor, cls)
-  _AddEqualsMethod(message_descriptor, cls)
-  _AddStrMethod(message_descriptor, cls)
-  _AddSetListenerMethod(cls)
-  _AddByteSizeMethod(message_descriptor, cls)
-  _AddSerializeToStringMethod(message_descriptor, cls)
-  _AddSerializePartialToStringMethod(message_descriptor, cls)
-  _AddMergeFromStringMethod(message_descriptor, cls)
-  _AddIsInitializedMethod(message_descriptor, cls)
-  _AddMergeFromMethod(cls)
-
-
-def _AddPrivateHelperMethods(cls):
-  """Adds implementation of private helper methods to cls."""
-
-  def Modified(self):
-    """Sets the _cached_byte_size_dirty bit to true,
-    and propagates this to our listener iff this was a state change.
-    """
-
-    # Note:  Some callers check _cached_byte_size_dirty before calling
-    #   _Modified() as an extra optimization.  So, if this method is ever
-    #   changed such that it does stuff even when _cached_byte_size_dirty is
-    #   already true, the callers need to be updated.
-    if not self._cached_byte_size_dirty:
-      self._cached_byte_size_dirty = True
-      self._listener_for_children.dirty = True
-      self._is_present_in_parent = True
-      self._listener.Modified()
-
-  cls._Modified = Modified
-  cls.SetInParent = Modified
-
-
-class _Listener(object):
-
-  """MessageListener implementation that a parent message registers with its
-  child message.
-
-  In order to support semantics like:
-
-    foo.bar.baz.qux = 23
-    assert foo.HasField('bar')
-
-  ...child objects must have back references to their parents.
-  This helper class is at the heart of this support.
-  """
-
-  def __init__(self, parent_message):
-    """Args:
-      parent_message: The message whose _Modified() method we should call when
-        we receive Modified() messages.
-    """
-    # This listener establishes a back reference from a child (contained) object
-    # to its parent (containing) object.  We make this a weak reference to avoid
-    # creating cyclic garbage when the client finishes with the 'parent' object
-    # in the tree.
-    if isinstance(parent_message, weakref.ProxyType):
-      self._parent_message_weakref = parent_message
-    else:
-      self._parent_message_weakref = weakref.proxy(parent_message)
-
-    # As an optimization, we also indicate directly on the listener whether
-    # or not the parent message is dirty.  This way we can avoid traversing
-    # up the tree in the common case.
-    self.dirty = False
-
-  def Modified(self):
-    if self.dirty:
-      return
-    try:
-      # Propagate the signal to our parents iff this is the first field set.
-      self._parent_message_weakref._Modified()
-    except ReferenceError:
-      # We can get here if a client has kept a reference to a child object,
-      # and is now setting a field on it, but the child's parent has been
-      # garbage-collected.  This is not an error.
-      pass
-
-
-# TODO(robinson): Move elsewhere?  This file is getting pretty ridiculous...
-# TODO(robinson): Unify error handling of "unknown extension" crap.
-# TODO(robinson): Support iteritems()-style iteration over all
-# extensions with the "has" bits turned on?
-class _ExtensionDict(object):
-
-  """Dict-like container for supporting an indexable "Extensions"
-  field on proto instances.
-
-  Note that in all cases we expect extension handles to be
-  FieldDescriptors.
-  """
-
-  def __init__(self, extended_message):
-    """extended_message: Message instance for which we are the Extensions dict.
-    """
-
-    self._extended_message = extended_message
-
-  def __getitem__(self, extension_handle):
-    """Returns the current value of the given extension handle."""
-
-    _VerifyExtensionHandle(self._extended_message, extension_handle)
-
-    result = self._extended_message._fields.get(extension_handle)
-    if result is not None:
-      return result
-
-    if extension_handle.label == _FieldDescriptor.LABEL_REPEATED:
-      result = extension_handle._default_constructor(self._extended_message)
-    elif extension_handle.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
-      result = extension_handle.message_type._concrete_class()
-      try:
-        result._SetListener(self._extended_message._listener_for_children)
-      except ReferenceError:
-        pass
-    else:
-      # Singular scalar -- just return the default without inserting into the
-      # dict.
-      return extension_handle.default_value
-
-    # Atomically check if another thread has preempted us and, if not, swap
-    # in the new object we just created.  If someone has preempted us, we
-    # take that object and discard ours.
-    # WARNING:  We are relying on setdefault() being atomic.  This is true
-    #   in CPython but we haven't investigated others.  This warning appears
-    #   in several other locations in this file.
-    result = self._extended_message._fields.setdefault(
-        extension_handle, result)
-
-    return result
-
-  def __eq__(self, other):
-    if not isinstance(other, self.__class__):
-      return False
-
-    my_fields = self._extended_message.ListFields()
-    other_fields = other._extended_message.ListFields()
-
-    # Get rid of non-extension fields.
-    my_fields    = [ field for field in my_fields    if field.is_extension ]
-    other_fields = [ field for field in other_fields if field.is_extension ]
-
-    return my_fields == other_fields
-
-  def __ne__(self, other):
-    return not self == other
-
-  # Note that this is only meaningful for non-repeated, scalar extension
-  # fields.  Note also that we may have to call _Modified() when we do
-  # successfully set a field this way, to set any necssary "has" bits in the
-  # ancestors of the extended message.
-  def __setitem__(self, extension_handle, value):
-    """If extension_handle specifies a non-repeated, scalar extension
-    field, sets the value of that field.
-    """
-
-    _VerifyExtensionHandle(self._extended_message, extension_handle)
-
-    if (extension_handle.label == _FieldDescriptor.LABEL_REPEATED or
-        extension_handle.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE):
-      raise TypeError(
-          'Cannot assign to extension "%s" because it is a repeated or '
-          'composite type.' % extension_handle.full_name)
-
-    # It's slightly wasteful to lookup the type checker each time,
-    # but we expect this to be a vanishingly uncommon case anyway.
-    type_checker = type_checkers.GetTypeChecker(
-        extension_handle.cpp_type, extension_handle.type)
-    type_checker.CheckValue(value)
-    self._extended_message._fields[extension_handle] = value
-    self._extended_message._Modified()
-
-  def _FindExtensionByName(self, name):
-    """Tries to find a known extension with the specified name.
-
-    Args:
-      name: Extension full name.
-
-    Returns:
-      Extension field descriptor.
-    """
-    return self._extended_message._extensions_by_name.get(name, None)
diff --git a/python/google/protobuf/text_format.py b/python/google/protobuf/text_format.py
index cc6ac90..6d77b54 100755
--- a/python/google/protobuf/text_format.py
+++ b/python/google/protobuf/text_format.py
@@ -53,24 +53,26 @@
   """Thrown in case of ASCII parsing error."""
 
 
-def MessageToString(message):
+def MessageToString(message, as_utf8=False, as_one_line=False):
   out = cStringIO.StringIO()
-  PrintMessage(message, out)
+  PrintMessage(message, out, as_utf8=as_utf8, as_one_line=as_one_line)
   result = out.getvalue()
   out.close()
+  if as_one_line:
+    return result.rstrip()
   return result
 
 
-def PrintMessage(message, out, indent = 0):
+def PrintMessage(message, out, indent=0, as_utf8=False, as_one_line=False):
   for field, value in message.ListFields():
     if field.label == descriptor.FieldDescriptor.LABEL_REPEATED:
       for element in value:
-        PrintField(field, element, out, indent)
+        PrintField(field, element, out, indent, as_utf8, as_one_line)
     else:
-      PrintField(field, value, out, indent)
+      PrintField(field, value, out, indent, as_utf8, as_one_line)
 
 
-def PrintField(field, value, out, indent = 0):
+def PrintField(field, value, out, indent=0, as_utf8=False, as_one_line=False):
   """Print a single field name/value pair.  For repeated fields, the value
   should be a single element."""
 
@@ -96,23 +98,35 @@
     # don't include it.
     out.write(': ')
 
-  PrintFieldValue(field, value, out, indent)
-  out.write('\n')
+  PrintFieldValue(field, value, out, indent, as_utf8, as_one_line)
+  if as_one_line:
+    out.write(' ')
+  else:
+    out.write('\n')
 
 
-def PrintFieldValue(field, value, out, indent = 0):
+def PrintFieldValue(field, value, out, indent=0,
+                    as_utf8=False, as_one_line=False):
   """Print a single field value (not including name).  For repeated fields,
   the value should be a single element."""
 
   if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
-    out.write(' {\n')
-    PrintMessage(value, out, indent + 2)
-    out.write(' ' * indent + '}')
+    if as_one_line:
+      out.write(' { ')
+      PrintMessage(value, out, indent, as_utf8, as_one_line)
+      out.write('}')
+    else:
+      out.write(' {\n')
+      PrintMessage(value, out, indent + 2, as_utf8, as_one_line)
+      out.write(' ' * indent + '}')
   elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_ENUM:
     out.write(field.enum_type.values_by_number[value].name)
   elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_STRING:
     out.write('\"')
-    out.write(_CEscape(value))
+    if type(value) is unicode:
+      out.write(_CEscape(value.encode('utf-8'), as_utf8))
+    else:
+      out.write(_CEscape(value, as_utf8))
     out.write('\"')
   elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_BOOL:
     if value:
@@ -334,10 +348,10 @@
     Returns:
       True iff the end was reached.
     """
-    return not self._lines and not self._current_line
+    return self.token == ''
 
   def _PopLine(self):
-    while not self._current_line:
+    while len(self._current_line) <= self._column:
       if not self._lines:
         self._current_line = ''
         return
@@ -348,11 +362,10 @@
   def _SkipWhitespace(self):
     while True:
       self._PopLine()
-      match = re.match(self._WHITESPACE, self._current_line)
+      match = self._WHITESPACE.match(self._current_line, self._column)
       if not match:
         break
       length = len(match.group(0))
-      self._current_line = self._current_line[length:]
       self._column += length
 
   def TryConsume(self, token):
@@ -402,7 +415,7 @@
       ParseError: If an identifier couldn't be consumed.
     """
     result = self.token
-    if not re.match(self._IDENTIFIER, result):
+    if not self._IDENTIFIER.match(result):
       raise self._ParseError('Expected identifier.')
     self.NextToken()
     return result
@@ -481,13 +494,13 @@
       ParseError: If a floating point number couldn't be consumed.
     """
     text = self.token
-    if re.match(self._FLOAT_INFINITY, text):
+    if self._FLOAT_INFINITY.match(text):
       self.NextToken()
       if text.startswith('-'):
         return -_INFINITY
       return _INFINITY
 
-    if re.match(self._FLOAT_NAN, text):
+    if self._FLOAT_NAN.match(text):
       self.NextToken()
       return _NAN
 
@@ -507,10 +520,10 @@
     Raises:
       ParseError: If a boolean value couldn't be consumed.
     """
-    if self.token == 'true':
+    if self.token in ('true', 't', '1'):
       self.NextToken()
       return True
-    elif self.token == 'false':
+    elif self.token in ('false', 'f', '0'):
       self.NextToken()
       return False
     else:
@@ -525,7 +538,11 @@
     Raises:
       ParseError: If a string value couldn't be consumed.
     """
-    return unicode(self.ConsumeByteString(), 'utf-8')
+    bytes = self.ConsumeByteString()
+    try:
+      return unicode(bytes, 'utf-8')
+    except UnicodeDecodeError, e:
+      raise self._StringParseError(e)
 
   def ConsumeByteString(self):
     """Consumes a byte array value.
@@ -609,7 +626,7 @@
   def _ParseError(self, message):
     """Creates and *returns* a ParseError for the current token."""
     return ParseError('%d:%d : %s' % (
-        self._line + 1, self._column + 1, message))
+        self._line + 1, self._column - len(self.token) + 1, message))
 
   def _IntegerParseError(self, e):
     return self._ParseError('Couldn\'t parse integer: ' + str(e))
@@ -617,27 +634,27 @@
   def _FloatParseError(self, e):
     return self._ParseError('Couldn\'t parse number: ' + str(e))
 
+  def _StringParseError(self, e):
+    return self._ParseError('Couldn\'t parse string: ' + str(e))
+
   def NextToken(self):
     """Reads the next meaningful token."""
     self._previous_line = self._line
     self._previous_column = self._column
-    if self.AtEnd():
+
+    self._column += len(self.token)
+    self._SkipWhitespace()
+
+    if not self._lines and len(self._current_line) <= self._column:
       self.token = ''
       return
-    self._column += len(self.token)
 
-    # Make sure there is data to work on.
-    self._PopLine()
-
-    match = re.match(self._TOKEN, self._current_line)
+    match = self._TOKEN.match(self._current_line, self._column)
     if match:
       token = match.group(0)
-      self._current_line = self._current_line[len(token):]
       self.token = token
     else:
-      self.token = self._current_line[0]
-      self._current_line = self._current_line[1:]
-    self._SkipWhitespace()
+      self.token = self._current_line[self._column]
 
 
 # text.encode('string_escape') does not seem to satisfy our needs as it
@@ -645,7 +662,7 @@
 # C++ unescaping function allows hex escapes to be any length.  So,
 # "\0011".encode('string_escape') ends up being "\\x011", which will be
 # decoded in C++ as a single-character string with char code 0x11.
-def _CEscape(text):
+def _CEscape(text, as_utf8):
   def escape(c):
     o = ord(c)
     if o == 10: return r"\n"   # optional escape
@@ -656,12 +673,13 @@
     if o == 34: return r'\"'   # necessary escape
     if o == 92: return r"\\"   # necessary escape
 
-    if o >= 127 or o < 32: return "\\%03o" % o # necessary escapes
+    # necessary escapes
+    if not as_utf8 and (o >= 127 or o < 32): return "\\%03o" % o
     return c
   return "".join([escape(c) for c in text])
 
 
-_CUNESCAPE_HEX = re.compile('\\\\x([0-9a-fA-F]{2}|[0-9a-f-A-F])')
+_CUNESCAPE_HEX = re.compile('\\\\x([0-9a-fA-F]{2}|[0-9a-fA-F])')
 
 
 def _CUnescape(text):
diff --git a/python/setup.py b/python/setup.py
index 8188730..47646a8 100755
--- a/python/setup.py
+++ b/python/setup.py
@@ -7,7 +7,7 @@
 from ez_setup import use_setuptools
 use_setuptools()
 
-from setuptools import setup
+from setuptools import setup, Extension
 from distutils.spawn import find_executable
 import sys
 import os
@@ -60,6 +60,7 @@
     del sys.modules['google']
 
   generate_proto("../src/google/protobuf/unittest.proto")
+  generate_proto("../src/google/protobuf/unittest_custom_options.proto")
   generate_proto("../src/google/protobuf/unittest_import.proto")
   generate_proto("../src/google/protobuf/unittest_mset.proto")
   generate_proto("../src/google/protobuf/unittest_no_generic_services.proto")
@@ -94,24 +95,39 @@
     for (dirpath, dirnames, filenames) in os.walk("."):
       for filename in filenames:
         filepath = os.path.join(dirpath, filename)
-        if filepath.endswith("_pb2.py") or filepath.endswith(".pyc"):
+        if filepath.endswith("_pb2.py") or filepath.endswith(".pyc") or \
+          filepath.endswith(".so") or filepath.endswith(".o"):
           os.remove(filepath)
   else:
     # Generate necessary .proto file if it doesn't exist.
     # TODO(kenton):  Maybe we should hook this into a distutils command?
     generate_proto("../src/google/protobuf/descriptor.proto")
 
+  python_c_extension = Extension("google.protobuf.internal._net_proto2___python",
+                                 [ "google/protobuf/pyext/python_descriptor.cc",
+                                   "google/protobuf/pyext/python_protobuf.cc",
+                                   "google/protobuf/pyext/python-proto2.cc",
+                                   ],
+                                 include_dirs = [ "../src", ".", ],
+                                 libraries = [ "protobuf" ],
+                                 runtime_library_dirs = [ "../src/.libs" ],
+                                 library_dirs = [ "../src/.libs" ],
+                                 )
+
   setup(name = 'protobuf',
-        version = '2.3.1-pre',
+        version = '2.4.0-pre',
         packages = [ 'google' ],
         namespace_packages = [ 'google' ],
         test_suite = 'setup.MakeTestSuite',
         # Must list modules explicitly so that we don't install tests.
         py_modules = [
+          'google.protobuf.internal.api_implementation',
           'google.protobuf.internal.containers',
+          'google.protobuf.internal.cpp_message',
           'google.protobuf.internal.decoder',
           'google.protobuf.internal.encoder',
           'google.protobuf.internal.message_listener',
+          'google.protobuf.internal.python_message',
           'google.protobuf.internal.type_checkers',
           'google.protobuf.internal.wire_format',
           'google.protobuf.descriptor',
@@ -121,6 +137,7 @@
           'google.protobuf.service',
           'google.protobuf.service_reflection',
           'google.protobuf.text_format' ],
+        ext_modules = [ python_c_extension ],
         url = 'http://code.google.com/p/protobuf/',
         maintainer = maintainer_email,
         maintainer_email = 'protobuf@googlegroups.com',
diff --git a/src/Makefile.am b/src/Makefile.am
index 35f5c0c..92bbe8c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -178,6 +178,8 @@
   google/protobuf/compiler/java/java_primitive_field.h         \
   google/protobuf/compiler/java/java_service.cc                \
   google/protobuf/compiler/java/java_service.h                 \
+  google/protobuf/compiler/java/java_string_field.cc           \
+  google/protobuf/compiler/java/java_string_field.h            \
   google/protobuf/compiler/python/python_generator.cc
 
 bin_PROGRAMS = protoc
diff --git a/src/google/protobuf/compiler/code_generator.cc b/src/google/protobuf/compiler/code_generator.cc
index 3413a36..455c239 100644
--- a/src/google/protobuf/compiler/code_generator.cc
+++ b/src/google/protobuf/compiler/code_generator.cc
@@ -42,14 +42,19 @@
 namespace compiler {
 
 CodeGenerator::~CodeGenerator() {}
-OutputDirectory::~OutputDirectory() {}
+GeneratorContext::~GeneratorContext() {}
 
-io::ZeroCopyOutputStream* OutputDirectory::OpenForInsert(
+io::ZeroCopyOutputStream* GeneratorContext::OpenForInsert(
     const string& filename, const string& insertion_point) {
-  GOOGLE_LOG(FATAL) << "This OutputDirectory does not support insertion.";
+  GOOGLE_LOG(FATAL) << "This GeneratorContext does not support insertion.";
   return NULL;  // make compiler happy
 }
 
+void GeneratorContext::ListParsedFiles(
+    vector<const FileDescriptor*>* output) {
+  GOOGLE_LOG(FATAL) << "This GeneratorContext does not support ListParsedFiles";
+}
+
 // Parses a set of comma-delimited name/value pairs.
 void ParseGeneratorParameter(const string& text,
                              vector<pair<string, string> >* output) {
diff --git a/src/google/protobuf/compiler/code_generator.h b/src/google/protobuf/compiler/code_generator.h
index ea094cd..252f68d 100644
--- a/src/google/protobuf/compiler/code_generator.h
+++ b/src/google/protobuf/compiler/code_generator.h
@@ -53,7 +53,7 @@
 
 // Defined in this file.
 class CodeGenerator;
-class OutputDirectory;
+class GeneratorContext;
 
 // The abstract interface to a class which generates code implementing a
 // particular proto file in a particular language.  A number of these may
@@ -76,7 +76,7 @@
   // the problem (e.g. "invalid parameter") and returns false.
   virtual bool Generate(const FileDescriptor* file,
                         const string& parameter,
-                        OutputDirectory* output_directory,
+                        GeneratorContext* generator_context,
                         string* error) const = 0;
 
  private:
@@ -85,11 +85,12 @@
 
 // CodeGenerators generate one or more files in a given directory.  This
 // abstract interface represents the directory to which the CodeGenerator is
-// to write.
-class LIBPROTOC_EXPORT OutputDirectory {
+// to write and other information about the context in which the Generator
+// runs.
+class LIBPROTOC_EXPORT GeneratorContext {
  public:
-  inline OutputDirectory() {}
-  virtual ~OutputDirectory();
+  inline GeneratorContext() {}
+  virtual ~GeneratorContext();
 
   // Opens the given file, truncating it if it exists, and returns a
   // ZeroCopyOutputStream that writes to the file.  The caller takes ownership
@@ -112,10 +113,19 @@
   virtual io::ZeroCopyOutputStream* OpenForInsert(
       const string& filename, const string& insertion_point);
 
+  // Returns a vector of FileDescriptors for all the files being compiled
+  // in this run.  Useful for languages, such as Go, that treat files
+  // differently when compiled as a set rather than individually.
+  virtual void ListParsedFiles(vector<const FileDescriptor*>* output);
+
  private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OutputDirectory);
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GeneratorContext);
 };
 
+// The type GeneratorContext was once called OutputDirectory. This typedef
+// provides backward compatibility.
+typedef GeneratorContext OutputDirectory;
+
 // Several code generators treat the parameter argument as holding a
 // list of options separated by commas.  This helper function parses
 // a set of comma-delimited name/value pairs: e.g.,
diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc
index 02c3e0f..9e9849c 100644
--- a/src/google/protobuf/compiler/command_line_interface.cc
+++ b/src/google/protobuf/compiler/command_line_interface.cc
@@ -48,6 +48,9 @@
 #include <iostream>
 #include <ctype.h>
 
+#include <google/protobuf/stubs/hash.h>
+
+#include <google/protobuf/stubs/common.h>
 #include <google/protobuf/compiler/importer.h>
 #include <google/protobuf/compiler/code_generator.h>
 #include <google/protobuf/compiler/plugin.pb.h>
@@ -58,12 +61,10 @@
 #include <google/protobuf/dynamic_message.h>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
 #include <google/protobuf/io/printer.h>
-#include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/substitute.h>
 #include <google/protobuf/stubs/map-util.h>
 #include <google/protobuf/stubs/stl_util-inl.h>
-#include <google/protobuf/stubs/hash.h>
 
 
 namespace google {
@@ -182,7 +183,7 @@
 class CommandLineInterface::ErrorPrinter : public MultiFileErrorCollector,
                                            public io::ErrorCollector {
  public:
-  ErrorPrinter(ErrorFormat format, DiskSourceTree *tree = NULL) 
+  ErrorPrinter(ErrorFormat format, DiskSourceTree *tree = NULL)
     : format_(format), tree_(tree) {}
   ~ErrorPrinter() {}
 
@@ -191,8 +192,8 @@
                 const string& message) {
 
     // Print full path when running under MSVS
-    std::string dfile;
-    if (format_ == CommandLineInterface::ERROR_FORMAT_MSVS && 
+    string dfile;
+    if (format_ == CommandLineInterface::ERROR_FORMAT_MSVS &&
         tree_ != NULL &&
         tree_->VirtualFileToDiskFile(filename, &dfile)) {
       cerr << dfile;
@@ -229,12 +230,12 @@
 
 // -------------------------------------------------------------------
 
-// An OutputDirectory implementation that buffers files in memory, then dumps
+// A GeneratorContext implementation that buffers files in memory, then dumps
 // them all to disk on demand.
-class CommandLineInterface::MemoryOutputDirectory : public OutputDirectory {
+class CommandLineInterface::GeneratorContextImpl : public GeneratorContext {
  public:
-  MemoryOutputDirectory();
-  ~MemoryOutputDirectory();
+  GeneratorContextImpl(const vector<const FileDescriptor*>& parsed_files);
+  ~GeneratorContextImpl();
 
   // Write all files in the directory to disk at the given output location,
   // which must end in a '/'.
@@ -248,10 +249,13 @@
   // format, unless one has already been written.
   void AddJarManifest();
 
-  // implements OutputDirectory --------------------------------------
+  // implements GeneratorContext --------------------------------------
   io::ZeroCopyOutputStream* Open(const string& filename);
   io::ZeroCopyOutputStream* OpenForInsert(
       const string& filename, const string& insertion_point);
+  void ListParsedFiles(vector<const FileDescriptor*>* output) {
+    *output = parsed_files_;
+  }
 
  private:
   friend class MemoryOutputStream;
@@ -259,14 +263,15 @@
   // map instead of hash_map so that files are written in order (good when
   // writing zips).
   map<string, string*> files_;
+  const vector<const FileDescriptor*>& parsed_files_;
   bool had_error_;
 };
 
 class CommandLineInterface::MemoryOutputStream
     : public io::ZeroCopyOutputStream {
  public:
-  MemoryOutputStream(MemoryOutputDirectory* directory, const string& filename);
-  MemoryOutputStream(MemoryOutputDirectory* directory, const string& filename,
+  MemoryOutputStream(GeneratorContextImpl* directory, const string& filename);
+  MemoryOutputStream(GeneratorContextImpl* directory, const string& filename,
                      const string& insertion_point);
   virtual ~MemoryOutputStream();
 
@@ -277,7 +282,7 @@
 
  private:
   // Where to insert the string when it's done.
-  MemoryOutputDirectory* directory_;
+  GeneratorContextImpl* directory_;
   string filename_;
   string insertion_point_;
 
@@ -290,14 +295,17 @@
 
 // -------------------------------------------------------------------
 
-CommandLineInterface::MemoryOutputDirectory::MemoryOutputDirectory()
-    : had_error_(false) {}
+CommandLineInterface::GeneratorContextImpl::GeneratorContextImpl(
+    const vector<const FileDescriptor*>& parsed_files)
+    : parsed_files_(parsed_files),
+      had_error_(false) {
+}
 
-CommandLineInterface::MemoryOutputDirectory::~MemoryOutputDirectory() {
+CommandLineInterface::GeneratorContextImpl::~GeneratorContextImpl() {
   STLDeleteValues(&files_);
 }
 
-bool CommandLineInterface::MemoryOutputDirectory::WriteAllToDisk(
+bool CommandLineInterface::GeneratorContextImpl::WriteAllToDisk(
     const string& prefix) {
   if (had_error_) {
     return false;
@@ -372,7 +380,7 @@
   return true;
 }
 
-bool CommandLineInterface::MemoryOutputDirectory::WriteAllToZip(
+bool CommandLineInterface::GeneratorContextImpl::WriteAllToZip(
     const string& filename) {
   if (had_error_) {
     return false;
@@ -413,7 +421,7 @@
   return true;
 }
 
-void CommandLineInterface::MemoryOutputDirectory::AddJarManifest() {
+void CommandLineInterface::GeneratorContextImpl::AddJarManifest() {
   string** map_slot = &files_["META-INF/MANIFEST.MF"];
   if (*map_slot == NULL) {
     *map_slot = new string(
@@ -423,13 +431,13 @@
   }
 }
 
-io::ZeroCopyOutputStream* CommandLineInterface::MemoryOutputDirectory::Open(
+io::ZeroCopyOutputStream* CommandLineInterface::GeneratorContextImpl::Open(
     const string& filename) {
   return new MemoryOutputStream(this, filename);
 }
 
 io::ZeroCopyOutputStream*
-CommandLineInterface::MemoryOutputDirectory::OpenForInsert(
+CommandLineInterface::GeneratorContextImpl::OpenForInsert(
     const string& filename, const string& insertion_point) {
   return new MemoryOutputStream(this, filename, insertion_point);
 }
@@ -437,14 +445,14 @@
 // -------------------------------------------------------------------
 
 CommandLineInterface::MemoryOutputStream::MemoryOutputStream(
-    MemoryOutputDirectory* directory, const string& filename)
+    GeneratorContextImpl* directory, const string& filename)
     : directory_(directory),
       filename_(filename),
       inner_(new io::StringOutputStream(&data_)) {
 }
 
 CommandLineInterface::MemoryOutputStream::MemoryOutputStream(
-    MemoryOutputDirectory* directory, const string& filename,
+    GeneratorContextImpl* directory, const string& filename,
     const string& insertion_point)
     : directory_(directory),
       filename_(filename),
@@ -613,11 +621,11 @@
     }
   }
 
-  // We construct a separate OutputDirectory for each output location.  Note
+  // We construct a separate GeneratorContext for each output location.  Note
   // that two code generators may output to the same location, in which case
-  // they should share a single OutputDirectory (so that OpenForInsert() works).
-  typedef hash_map<string, MemoryOutputDirectory*> OutputDirectoryMap;
-  OutputDirectoryMap output_directories;
+  // they should share a single GeneratorContext so that OpenForInsert() works.
+  typedef hash_map<string, GeneratorContextImpl*> GeneratorContextMap;
+  GeneratorContextMap output_directories;
 
   // Generate output.
   if (mode_ == MODE_COMPILE) {
@@ -627,11 +635,11 @@
           !HasSuffixString(output_location, ".jar")) {
         AddTrailingSlash(&output_location);
       }
-      MemoryOutputDirectory** map_slot = &output_directories[output_location];
+      GeneratorContextImpl** map_slot = &output_directories[output_location];
 
       if (*map_slot == NULL) {
         // First time we've seen this output location.
-        *map_slot = new MemoryOutputDirectory;
+        *map_slot = new GeneratorContextImpl(parsed_files);
       }
 
       if (!GenerateOutput(parsed_files, output_directives_[i], *map_slot)) {
@@ -642,10 +650,10 @@
   }
 
   // Write all output to disk.
-  for (OutputDirectoryMap::iterator iter = output_directories.begin();
+  for (GeneratorContextMap::iterator iter = output_directories.begin();
        iter != output_directories.end(); ++iter) {
     const string& location = iter->first;
-    MemoryOutputDirectory* directory = iter->second;
+    GeneratorContextImpl* directory = iter->second;
     if (HasSuffixString(location, "/")) {
       if (!directory->WriteAllToDisk(location)) {
         STLDeleteValues(&output_directories);
@@ -1107,7 +1115,7 @@
 bool CommandLineInterface::GenerateOutput(
     const vector<const FileDescriptor*>& parsed_files,
     const OutputDirective& output_directive,
-    OutputDirectory* output_directory) {
+    GeneratorContext* generator_context) {
   // Call the generator.
   string error;
   if (output_directive.generator == NULL) {
@@ -1122,7 +1130,7 @@
 
     if (!GeneratePluginOutput(parsed_files, plugin_name,
                               output_directive.parameter,
-                              output_directory, &error)) {
+                              generator_context, &error)) {
       cerr << output_directive.name << ": " << error << endl;
       return false;
     }
@@ -1131,7 +1139,7 @@
     for (int i = 0; i < parsed_files.size(); i++) {
       if (!output_directive.generator->Generate(
           parsed_files[i], output_directive.parameter,
-          output_directory, &error)) {
+          generator_context, &error)) {
         // Generator returned an error.
         cerr << output_directive.name << ": " << parsed_files[i]->name() << ": "
              << error << endl;
@@ -1147,7 +1155,7 @@
     const vector<const FileDescriptor*>& parsed_files,
     const string& plugin_name,
     const string& parameter,
-    OutputDirectory* output_directory,
+    GeneratorContext* generator_context,
     string* error) {
   CodeGeneratorRequest request;
   CodeGeneratorResponse response;
@@ -1190,14 +1198,14 @@
       // We reset current_output to NULL first so that the old file is closed
       // before the new one is opened.
       current_output.reset();
-      current_output.reset(output_directory->OpenForInsert(
+      current_output.reset(generator_context->OpenForInsert(
           output_file.name(), output_file.insertion_point()));
     } else if (!output_file.name().empty()) {
       // Starting a new file.  Open it.
       // We reset current_output to NULL first so that the old file is closed
       // before the new one is opened.
       current_output.reset();
-      current_output.reset(output_directory->Open(output_file.name()));
+      current_output.reset(generator_context->Open(output_file.name()));
     } else if (current_output == NULL) {
       *error = strings::Substitute(
         "$0: First file chunk returned by plugin did not specify a file name.",
diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h
index d25a50e..0b507d8 100644
--- a/src/google/protobuf/compiler/command_line_interface.h
+++ b/src/google/protobuf/compiler/command_line_interface.h
@@ -56,7 +56,7 @@
 namespace compiler {
 
 class CodeGenerator;        // code_generator.h
-class OutputDirectory;      // code_generator.h
+class GeneratorContext;      // code_generator.h
 class DiskSourceTree;       // importer.h
 
 // This class implements the command-line interface to the protocol compiler.
@@ -174,7 +174,7 @@
   // -----------------------------------------------------------------
 
   class ErrorPrinter;
-  class MemoryOutputDirectory;
+  class GeneratorContextImpl;
   class MemoryOutputStream;
 
   // Clear state from previous Run().
@@ -212,11 +212,11 @@
   struct OutputDirective;  // see below
   bool GenerateOutput(const vector<const FileDescriptor*>& parsed_files,
                       const OutputDirective& output_directive,
-                      OutputDirectory* output_directory);
+                      GeneratorContext* generator_context);
   bool GeneratePluginOutput(const vector<const FileDescriptor*>& parsed_files,
                             const string& plugin_name,
                             const string& parameter,
-                            OutputDirectory* output_directory,
+                            GeneratorContext* generator_context,
                             string* error);
 
   // Implements --encode and --decode.
diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc
index bdf37ad..6634b67 100644
--- a/src/google/protobuf/compiler/command_line_interface_unittest.cc
+++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc
@@ -143,6 +143,10 @@
                        const string& proto_name,
                        const string& message_name,
                        const string& output_directory);
+  void ExpectGeneratedWithMultipleInputs(const string& generator_name,
+                                         const string& all_proto_names,
+                                         const string& proto_name,
+                                         const string& message_name);
   void ExpectGeneratedWithInsertions(const string& generator_name,
                                      const string& parameter,
                                      const string& insertions,
@@ -190,7 +194,7 @@
   // implements CodeGenerator ----------------------------------------
   bool Generate(const FileDescriptor* file,
                 const string& parameter,
-                OutputDirectory* output_directory,
+                GeneratorContext* context,
                 string* error) const {
     called_ = true;
     parameter_ = parameter;
@@ -251,7 +255,6 @@
 
   if (!disallow_plugins_) {
     cli_.AllowPlugins("prefix-");
-
     const char* possible_paths[] = {
       // When building with shared libraries, libtool hides the real executable
       // in .libs and puts a fake wrapper in the current directory.
@@ -353,7 +356,8 @@
     const string& proto_name,
     const string& message_name) {
   MockCodeGenerator::ExpectGenerated(
-      generator_name, parameter, "", proto_name, message_name, temp_directory_);
+      generator_name, parameter, "", proto_name, message_name, proto_name,
+      temp_directory_);
 }
 
 void CommandLineInterfaceTest::ExpectGenerated(
@@ -363,10 +367,21 @@
     const string& message_name,
     const string& output_directory) {
   MockCodeGenerator::ExpectGenerated(
-      generator_name, parameter, "", proto_name, message_name,
+      generator_name, parameter, "", proto_name, message_name, proto_name,
       temp_directory_ + "/" + output_directory);
 }
 
+void CommandLineInterfaceTest::ExpectGeneratedWithMultipleInputs(
+    const string& generator_name,
+    const string& all_proto_names,
+    const string& proto_name,
+    const string& message_name) {
+  MockCodeGenerator::ExpectGenerated(
+      generator_name, "", "", proto_name, message_name,
+      all_proto_names,
+      temp_directory_);
+}
+
 void CommandLineInterfaceTest::ExpectGeneratedWithInsertions(
     const string& generator_name,
     const string& parameter,
@@ -375,7 +390,7 @@
     const string& message_name) {
   MockCodeGenerator::ExpectGenerated(
       generator_name, parameter, insertions, proto_name, message_name,
-      temp_directory_);
+      proto_name, temp_directory_);
 }
 
 void CommandLineInterfaceTest::ExpectNullCodeGeneratorCalled(
@@ -455,8 +470,44 @@
       "--proto_path=$tmpdir foo.proto bar.proto");
 
   ExpectNoErrors();
-  ExpectGenerated("test_generator", "", "foo.proto", "Foo");
-  ExpectGenerated("test_generator", "", "bar.proto", "Bar");
+  ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto",
+                                    "foo.proto", "Foo");
+  ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto",
+                                    "bar.proto", "Bar");
+  ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto",
+                                    "foo.proto", "Foo");
+  ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto",
+                                    "bar.proto", "Bar");
+}
+
+TEST_F(CommandLineInterfaceTest, MultipleInputsWithImport) {
+  // Test parsing multiple input files with an import of a separate file.
+
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+  CreateTempFile("bar.proto",
+    "syntax = \"proto2\";\n"
+    "import \"baz.proto\";\n"
+    "message Bar {\n"
+    "  optional Baz a = 1;\n"
+    "}\n");
+  CreateTempFile("baz.proto",
+    "syntax = \"proto2\";\n"
+    "message Baz {}\n");
+
+  Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir "
+      "--proto_path=$tmpdir foo.proto bar.proto");
+
+  ExpectNoErrors();
+  ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto",
+                                    "foo.proto", "Foo");
+  ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto",
+                                    "bar.proto", "Bar");
+  ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto",
+                                    "foo.proto", "Foo");
+  ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto",
+                                    "bar.proto", "Bar");
 }
 
 TEST_F(CommandLineInterfaceTest, CreateDirectory) {
diff --git a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
index 30b1d2b..bcfa502 100644
--- a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
@@ -79,10 +79,10 @@
   }
 };
 
-class MockOutputDirectory : public OutputDirectory {
+class MockGeneratorContext : public GeneratorContext {
  public:
-  MockOutputDirectory() {}
-  ~MockOutputDirectory() {
+  MockGeneratorContext() {}
+  ~MockGeneratorContext() {
     STLDeleteValues(&files_);
   }
 
@@ -102,7 +102,7 @@
          "to your CL.";
   }
 
-  // implements OutputDirectory --------------------------------------
+  // implements GeneratorContext --------------------------------------
 
   virtual io::ZeroCopyOutputStream* Open(const string& filename) {
     string** map_slot = &files_[filename];
@@ -130,24 +130,24 @@
   ASSERT_TRUE(plugin_proto_file != NULL);
 
   CppGenerator generator;
-  MockOutputDirectory output_directory;
+  MockGeneratorContext context;
   string error;
   string parameter;
   parameter = "dllexport_decl=LIBPROTOBUF_EXPORT";
   ASSERT_TRUE(generator.Generate(proto_file, parameter,
-                                 &output_directory, &error));
+                                 &context, &error));
   parameter = "dllexport_decl=LIBPROTOC_EXPORT";
   ASSERT_TRUE(generator.Generate(plugin_proto_file, parameter,
-                                 &output_directory, &error));
+                                 &context, &error));
 
-  output_directory.ExpectFileMatches("google/protobuf/descriptor.pb.h",
-                                     "google/protobuf/descriptor.pb.h");
-  output_directory.ExpectFileMatches("google/protobuf/descriptor.pb.cc",
-                                     "google/protobuf/descriptor.pb.cc");
-  output_directory.ExpectFileMatches("google/protobuf/compiler/plugin.pb.h",
-                                     "google/protobuf/compiler/plugin.pb.h");
-  output_directory.ExpectFileMatches("google/protobuf/compiler/plugin.pb.cc",
-                                     "google/protobuf/compiler/plugin.pb.cc");
+  context.ExpectFileMatches("google/protobuf/descriptor.pb.h",
+                            "google/protobuf/descriptor.pb.h");
+  context.ExpectFileMatches("google/protobuf/descriptor.pb.cc",
+                            "google/protobuf/descriptor.pb.cc");
+  context.ExpectFileMatches("google/protobuf/compiler/plugin.pb.h",
+                            "google/protobuf/compiler/plugin.pb.h");
+  context.ExpectFileMatches("google/protobuf/compiler/plugin.pb.cc",
+                            "google/protobuf/compiler/plugin.pb.cc");
 }
 
 }  // namespace
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
index 91ce493..a369f41 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
@@ -85,7 +85,7 @@
     "}\n"
     "inline void $classname$::set_$name$($type$ value) {\n"
     "  GOOGLE_DCHECK($type$_IsValid(value));\n"
-    "  _set_bit($index$);\n"
+    "  set_has_$name$();\n"
     "  $name$_ = value;\n"
     "}\n");
 }
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc
index e31cb42..22d6fdb 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_file.cc
@@ -283,6 +283,7 @@
   printer->Print(
     "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
     "\n"
+
     // The generated code calls accessors that might be deprecated. We don't
     // want the compiler to warn in generated code.
     "#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION\n"
diff --git a/src/google/protobuf/compiler/cpp/cpp_generator.cc b/src/google/protobuf/compiler/cpp/cpp_generator.cc
index d67d350..bb84e2a 100644
--- a/src/google/protobuf/compiler/cpp/cpp_generator.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_generator.cc
@@ -53,7 +53,7 @@
 
 bool CppGenerator::Generate(const FileDescriptor* file,
                             const string& parameter,
-                            OutputDirectory* output_directory,
+                            GeneratorContext* generator_context,
                             string* error) const {
   vector<pair<string, string> > options;
   ParseGeneratorParameter(parameter, &options);
@@ -100,7 +100,7 @@
   // Generate header.
   {
     scoped_ptr<io::ZeroCopyOutputStream> output(
-      output_directory->Open(basename + ".h"));
+      generator_context->Open(basename + ".h"));
     io::Printer printer(output.get(), '$');
     file_generator.GenerateHeader(&printer);
   }
@@ -108,7 +108,7 @@
   // Generate cc file.
   {
     scoped_ptr<io::ZeroCopyOutputStream> output(
-      output_directory->Open(basename + ".cc"));
+      generator_context->Open(basename + ".cc"));
     io::Printer printer(output.get(), '$');
     file_generator.GenerateSource(&printer);
   }
diff --git a/src/google/protobuf/compiler/cpp/cpp_generator.h b/src/google/protobuf/compiler/cpp/cpp_generator.h
index f52e886..a90e84d 100644
--- a/src/google/protobuf/compiler/cpp/cpp_generator.h
+++ b/src/google/protobuf/compiler/cpp/cpp_generator.h
@@ -57,7 +57,7 @@
   // implements CodeGenerator ----------------------------------------
   bool Generate(const FileDescriptor* file,
                 const string& parameter,
-                OutputDirectory* output_directory,
+                GeneratorContext* generator_context,
                 string* error) const;
 
  private:
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
index cbdcce8..c4e6fb2 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -35,6 +35,7 @@
 #include <algorithm>
 #include <google/protobuf/stubs/hash.h>
 #include <map>
+#include <utility>
 #include <vector>
 #include <google/protobuf/compiler/cpp/cpp_message.h>
 #include <google/protobuf/compiler/cpp/cpp_field.h>
@@ -143,6 +144,137 @@
   return HasRequiredFields(type, &already_seen);
 }
 
+// This returns an estimate of the compiler's alignment for the field.  This
+// can't guarantee to be correct because the generated code could be compiled on
+// different systems with different alignment rules.  The estimates below assume
+// 64-bit pointers.
+int EstimateAlignmentSize(const FieldDescriptor* field) {
+  if (field == NULL) return 0;
+  if (field->is_repeated()) return 8;
+  switch (field->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_BOOL:
+      return 1;
+
+    case FieldDescriptor::CPPTYPE_INT32:
+    case FieldDescriptor::CPPTYPE_UINT32:
+    case FieldDescriptor::CPPTYPE_ENUM:
+    case FieldDescriptor::CPPTYPE_FLOAT:
+      return 4;
+
+    case FieldDescriptor::CPPTYPE_INT64:
+    case FieldDescriptor::CPPTYPE_UINT64:
+    case FieldDescriptor::CPPTYPE_DOUBLE:
+    case FieldDescriptor::CPPTYPE_STRING:
+    case FieldDescriptor::CPPTYPE_MESSAGE:
+      return 8;
+  }
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return -1;  // Make compiler happy.
+}
+
+// FieldGroup is just a helper for OptimizePadding below.  It holds a vector of
+// fields that are grouped together because they have compatible alignment, and
+// a preferred location in the final field ordering.
+class FieldGroup {
+ public:
+  FieldGroup()
+      : preferred_location_(0) {}
+
+  // A group with a single field.
+  FieldGroup(float preferred_location, const FieldDescriptor* field)
+      : preferred_location_(preferred_location),
+        fields_(1, field) {}
+
+  // Append the fields in 'other' to this group.
+  void Append(const FieldGroup& other) {
+    if (other.fields_.empty()) {
+      return;
+    }
+    // Preferred location is the average among all the fields, so we weight by
+    // the number of fields on each FieldGroup object.
+    preferred_location_ =
+        (preferred_location_ * fields_.size() +
+         (other.preferred_location_ * other.fields_.size())) /
+        (fields_.size() + other.fields_.size());
+    fields_.insert(fields_.end(), other.fields_.begin(), other.fields_.end());
+  }
+
+  void SetPreferredLocation(float location) { preferred_location_ = location; }
+  const vector<const FieldDescriptor*>& fields() const { return fields_; }
+
+  // FieldGroup objects sort by their preferred location.
+  bool operator<(const FieldGroup& other) const {
+    return preferred_location_ < other.preferred_location_;
+  }
+
+ private:
+  // "preferred_location_" is an estimate of where this group should go in the
+  // final list of fields.  We compute this by taking the average index of each
+  // field in this group in the original ordering of fields.  This is very
+  // approximate, but should put this group close to where its member fields
+  // originally went.
+  float preferred_location_;
+  vector<const FieldDescriptor*> fields_;
+  // We rely on the default copy constructor and operator= so this type can be
+  // used in a vector.
+};
+
+// Reorder 'fields' so that if the fields are output into a c++ class in the new
+// order, the alignment padding is minimized.  We try to do this while keeping
+// each field as close as possible to its original position so that we don't
+// reduce cache locality much for function that access each field in order.
+void OptimizePadding(vector<const FieldDescriptor*>* fields) {
+  // First divide fields into those that align to 1 byte, 4 bytes or 8 bytes.
+  vector<FieldGroup> aligned_to_1, aligned_to_4, aligned_to_8;
+  for (int i = 0; i < fields->size(); ++i) {
+    switch (EstimateAlignmentSize((*fields)[i])) {
+      case 1: aligned_to_1.push_back(FieldGroup(i, (*fields)[i])); break;
+      case 4: aligned_to_4.push_back(FieldGroup(i, (*fields)[i])); break;
+      case 8: aligned_to_8.push_back(FieldGroup(i, (*fields)[i])); break;
+      default:
+        GOOGLE_LOG(FATAL) << "Unknown alignment size.";
+    }
+  }
+
+  // Now group fields aligned to 1 byte into sets of 4, and treat those like a
+  // single field aligned to 4 bytes.
+  for (int i = 0; i < aligned_to_1.size(); i += 4) {
+    FieldGroup field_group;
+    for (int j = i; j < aligned_to_1.size() && j < i + 4; ++j) {
+      field_group.Append(aligned_to_1[j]);
+    }
+    aligned_to_4.push_back(field_group);
+  }
+  // Sort by preferred location to keep fields as close to their original
+  // location as possible.
+  sort(aligned_to_4.begin(), aligned_to_4.end());
+
+  // Now group fields aligned to 4 bytes (or the 4-field groups created above)
+  // into pairs, and treat those like a single field aligned to 8 bytes.
+  for (int i = 0; i < aligned_to_4.size(); i += 2) {
+    FieldGroup field_group;
+    for (int j = i; j < aligned_to_4.size() && j < i + 2; ++j) {
+      field_group.Append(aligned_to_4[j]);
+    }
+    if (i == aligned_to_4.size() - 1) {
+      // Move incomplete 4-byte block to the end.
+      field_group.SetPreferredLocation(fields->size() + 1);
+    }
+    aligned_to_8.push_back(field_group);
+  }
+  // Sort by preferred location to keep fields as close to their original
+  // location as possible.
+  sort(aligned_to_8.begin(), aligned_to_8.end());
+
+  // Now pull out all the FieldDescriptors in order.
+  fields->clear();
+  for (int i = 0; i < aligned_to_8.size(); ++i) {
+    fields->insert(fields->end(),
+                   aligned_to_8[i].fields().begin(),
+                   aligned_to_8[i].fields().end());
+  }
+}
+
 }
 
 // ===================================================================
@@ -264,10 +396,20 @@
         "}\n");
     } else {
       // Singular field.
+      char buffer[kFastToBufferSize];
+      vars["has_array_index"] = SimpleItoa(field->index() / 32);
+      vars["has_mask"] = FastHex32ToBuffer(1u << (field->index() % 32), buffer);
       printer->Print(vars,
         "inline bool $classname$::has_$name$() const {\n"
-        "  return _has_bit($index$);\n"
-        "}\n");
+        "  return (_has_bits_[$has_array_index$] & 0x$has_mask$u) != 0;\n"
+        "}\n"
+        "inline void $classname$::set_has_$name$() {\n"
+        "  _has_bits_[$has_array_index$] |= 0x$has_mask$u;\n"
+        "}\n"
+        "inline void $classname$::clear_has_$name$() {\n"
+        "  _has_bits_[$has_array_index$] &= ~0x$has_mask$u;\n"
+        "}\n"
+        );
     }
 
     // Generate clear_$name$()
@@ -279,7 +421,8 @@
     printer->Outdent();
 
     if (!field->is_repeated()) {
-      printer->Print(vars, "  _clear_bit($index$);\n");
+      printer->Print(vars,
+                     "  clear_has_$name$();\n");
     }
 
     printer->Print("}\n");
@@ -444,28 +587,74 @@
     "// @@protoc_insertion_point(class_scope:$full_name$)\n",
     "full_name", descriptor_->full_name());
 
-  // Generate private members for fields.
+  // Generate private members.
   printer->Outdent();
   printer->Print(" private:\n");
   printer->Indent();
 
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    if (!descriptor_->field(i)->is_repeated()) {
+      printer->Print(
+        "inline void set_has_$name$();\n",
+        "name", FieldName(descriptor_->field(i)));
+      printer->Print(
+        "inline void clear_has_$name$();\n",
+        "name", FieldName(descriptor_->field(i)));
+    }
+  }
+  printer->Print("\n");
+
+  // To minimize padding, data members are divided into three sections:
+  // (1) members assumed to align to 8 bytes
+  // (2) members corresponding to message fields, re-ordered to optimize
+  //     alignment.
+  // (3) members assumed to align to 4 bytes.
+
+  // Members assumed to align to 8 bytes:
+
   if (descriptor_->extension_range_count() > 0) {
     printer->Print(
-      "::google::protobuf::internal::ExtensionSet _extensions_;\n");
+      "::google::protobuf::internal::ExtensionSet _extensions_;\n"
+      "\n");
   }
 
   if (HasUnknownFields(descriptor_->file())) {
     printer->Print(
-      "::google::protobuf::UnknownFieldSet _unknown_fields_;\n");
+      "::google::protobuf::UnknownFieldSet _unknown_fields_;\n"
+      "\n");
   }
 
+  // Field members:
+
+  vector<const FieldDescriptor*> fields;
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    fields.push_back(descriptor_->field(i));
+  }
+  OptimizePadding(&fields);
+  for (int i = 0; i < fields.size(); ++i) {
+    field_generators_.get(fields[i]).GeneratePrivateMembers(printer);
+  }
+
+  // Members assumed to align to 4 bytes:
+
   // TODO(kenton):  Make _cached_size_ an atomic<int> when C++ supports it.
   printer->Print(
-    "mutable int _cached_size_;\n"
-    "\n");
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    field_generators_.get(descriptor_->field(i))
-                     .GeneratePrivateMembers(printer);
+      "\n"
+      "mutable int _cached_size_;\n");
+
+  // Generate _has_bits_.
+  if (descriptor_->field_count() > 0) {
+    printer->Print(vars,
+      "::google::protobuf::uint32 _has_bits_[($field_count$ + 31) / 32];\n"
+      "\n");
+  } else {
+    // Zero-size arrays aren't technically allowed, and MSVC in particular
+    // doesn't like them.  We still need to declare these arrays to make
+    // other code compile.  Since this is an uncommon case, we'll just declare
+    // them with size 1 and waste some space.  Oh well.
+    printer->Print(
+      "::google::protobuf::uint32 _has_bits_[1];\n"
+      "\n");
   }
 
   // Declare AddDescriptors(), BuildDescriptors(), and ShutdownFile() as
@@ -484,32 +673,7 @@
       GlobalAssignDescriptorsName(descriptor_->file()->name()),
     "shutdownfilename", GlobalShutdownFileName(descriptor_->file()->name()));
 
-  // Generate offsets and _has_bits_ boilerplate.
-  if (descriptor_->field_count() > 0) {
-    printer->Print(vars,
-      "::google::protobuf::uint32 _has_bits_[($field_count$ + 31) / 32];\n");
-  } else {
-    // Zero-size arrays aren't technically allowed, and MSVC in particular
-    // doesn't like them.  We still need to declare these arrays to make
-    // other code compile.  Since this is an uncommon case, we'll just declare
-    // them with size 1 and waste some space.  Oh well.
-    printer->Print(
-      "::google::protobuf::uint32 _has_bits_[1];\n");
-  }
-
   printer->Print(
-    "\n"
-    "// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?\n"
-    "inline bool _has_bit(int index) const {\n"
-    "  return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;\n"
-    "}\n"
-    "inline void _set_bit(int index) {\n"
-    "  _has_bits_[index / 32] |= (1u << (index % 32));\n"
-    "}\n"
-    "inline void _clear_bit(int index) {\n"
-    "  _has_bits_[index / 32] &= ~(1u << (index % 32));\n"
-    "}\n"
-    "\n"
     "void InitAsDefaultInstance();\n"
     "static $classname$* default_instance_;\n",
     "classname", classname_);
@@ -961,9 +1125,6 @@
     const FieldDescriptor* field = descriptor_->field(i);
 
     if (!field->is_repeated()) {
-      map<string, string> vars;
-      vars["index"] = SimpleItoa(field->index());
-
       // We can use the fact that _has_bits_ is a giant bitfield to our
       // advantage:  We can check up to 32 bits at a time for equality to
       // zero, and skip the whole range if so.  This can improve the speed
@@ -975,8 +1136,9 @@
           printer->Outdent();
           printer->Print("}\n");
         }
-        printer->Print(vars,
-          "if (_has_bits_[$index$ / 32] & (0xffu << ($index$ % 32))) {\n");
+        printer->Print(
+          "if (_has_bits_[$index$ / 32] & (0xffu << ($index$ % 32))) {\n",
+          "index", SimpleItoa(field->index()));
         printer->Indent();
       }
       last_index = i;
@@ -989,7 +1151,9 @@
         field->cpp_type() == FieldDescriptor::CPPTYPE_STRING;
 
       if (should_check_bit) {
-        printer->Print(vars, "if (_has_bit($index$)) {\n");
+        printer->Print(
+          "if (has_$name$()) {\n",
+          "name", FieldName(field));
         printer->Indent();
       }
 
@@ -1129,24 +1293,23 @@
     const FieldDescriptor* field = descriptor_->field(i);
 
     if (!field->is_repeated()) {
-      map<string, string> vars;
-      vars["index"] = SimpleItoa(field->index());
-
       // See above in GenerateClear for an explanation of this.
       if (i / 8 != last_index / 8 || last_index < 0) {
         if (last_index >= 0) {
           printer->Outdent();
           printer->Print("}\n");
         }
-        printer->Print(vars,
-          "if (from._has_bits_[$index$ / 32] & (0xffu << ($index$ % 32))) {\n");
+        printer->Print(
+          "if (from._has_bits_[$index$ / 32] & (0xffu << ($index$ % 32))) {\n",
+          "index", SimpleItoa(field->index()));
         printer->Indent();
       }
 
       last_index = i;
 
-      printer->Print(vars,
-        "if (from._has_bit($index$)) {\n");
+      printer->Print(
+        "if (from.has_$name$()) {\n",
+        "name", FieldName(field));
       printer->Indent();
 
       field_generators_.get(field).GenerateMergingCode(printer);
@@ -1423,8 +1586,8 @@
 
   if (!field->is_repeated()) {
     printer->Print(
-      "if (_has_bit($index$)) {\n",
-      "index", SimpleItoa(field->index()));
+      "if (has_$name$()) {\n",
+      "name", FieldName(field));
     printer->Indent();
   }
 
diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
index c04bdc6..23e75b8 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
@@ -75,7 +75,8 @@
 GenerateAccessorDeclarations(io::Printer* printer) const {
   printer->Print(variables_,
     "inline const $type$& $name$() const$deprecation$;\n"
-    "inline $type$* mutable_$name$()$deprecation$;\n");
+    "inline $type$* mutable_$name$()$deprecation$;\n"
+    "inline $type$* release_$name$()$deprecation$;\n");
 }
 
 void MessageFieldGenerator::
@@ -85,9 +86,15 @@
     "  return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n"
     "}\n"
     "inline $type$* $classname$::mutable_$name$() {\n"
-    "  _set_bit($index$);\n"
+    "  set_has_$name$();\n"
     "  if ($name$_ == NULL) $name$_ = new $type$;\n"
     "  return $name$_;\n"
+    "}\n"
+    "inline $type$* $classname$::release_$name$() {\n"
+    "  clear_has_$name$();\n"
+    "  $type$* temp = $name$_;\n"
+    "  $name$_ = NULL;\n"
+    "  return temp;\n"
     "}\n");
 }
 
diff --git a/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
index 440b716..5c4aa4f 100644
--- a/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
@@ -56,24 +56,24 @@
 
   virtual bool Generate(const FileDescriptor* file,
                         const string& parameter,
-                        OutputDirectory* output_directory,
+                        GeneratorContext* context,
                         string* error) const {
-    TryInsert("test.pb.h", "includes", output_directory);
-    TryInsert("test.pb.h", "namespace_scope", output_directory);
-    TryInsert("test.pb.h", "global_scope", output_directory);
-    TryInsert("test.pb.h", "class_scope:foo.Bar", output_directory);
-    TryInsert("test.pb.h", "class_scope:foo.Bar.Baz", output_directory);
+    TryInsert("test.pb.h", "includes", context);
+    TryInsert("test.pb.h", "namespace_scope", context);
+    TryInsert("test.pb.h", "global_scope", context);
+    TryInsert("test.pb.h", "class_scope:foo.Bar", context);
+    TryInsert("test.pb.h", "class_scope:foo.Bar.Baz", context);
 
-    TryInsert("test.pb.cc", "includes", output_directory);
-    TryInsert("test.pb.cc", "namespace_scope", output_directory);
-    TryInsert("test.pb.cc", "global_scope", output_directory);
+    TryInsert("test.pb.cc", "includes", context);
+    TryInsert("test.pb.cc", "namespace_scope", context);
+    TryInsert("test.pb.cc", "global_scope", context);
     return true;
   }
 
   void TryInsert(const string& filename, const string& insertion_point,
-                 OutputDirectory* output_directory) const {
+                 GeneratorContext* context) const {
     scoped_ptr<io::ZeroCopyOutputStream> output(
-      output_directory->OpenForInsert(filename, insertion_point));
+      context->OpenForInsert(filename, insertion_point));
     io::Printer printer(output.get(), '$');
     printer.Print("// inserted $name$\n", "name", insertion_point);
   }
diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
index a69c48b..5e8df0f 100644
--- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
@@ -125,7 +125,7 @@
     "  return $name$_;\n"
     "}\n"
     "inline void $classname$::set_$name$($type$ value) {\n"
-    "  _set_bit($index$);\n"
+    "  set_has_$name$();\n"
     "  $name$_ = value;\n"
     "}\n");
 }
@@ -156,7 +156,7 @@
     "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
     "         $type$, $wire_format_field_type$>(\n"
     "       input, &$name$_)));\n"
-    "_set_bit($index$);\n");
+    "set_has_$name$();\n");
 }
 
 void PrimitiveFieldGenerator::
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
index ea6809a..67d7eae 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
@@ -50,6 +50,9 @@
   SetCommonFieldVariables(descriptor, variables);
   (*variables)["default"] =
     "\"" + CEscape(descriptor->default_value_string()) + "\"";
+  (*variables)["default_variable"] = descriptor->default_value_string().empty()
+      ? "::google::protobuf::internal::kEmptyString"
+      : "_default_" + FieldName(descriptor) + "_";
   (*variables)["pointer_type"] =
       descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char";
 }
@@ -68,9 +71,10 @@
 
 void StringFieldGenerator::
 GeneratePrivateMembers(io::Printer* printer) const {
-  printer->Print(variables_,
-    "::std::string* $name$_;\n"
-    "static const ::std::string _default_$name$_;\n");
+  printer->Print(variables_, "::std::string* $name$_;\n");
+  if (!descriptor_->default_value_string().empty()) {
+    printer->Print(variables_, "static const ::std::string $default_variable$;\n");
+  }
 }
 
 void StringFieldGenerator::
@@ -105,7 +109,8 @@
     "inline void set_$name$(const char* value)$deprecation$;\n"
     "inline void set_$name$(const $pointer_type$* value, size_t size)"
                  "$deprecation$;\n"
-    "inline ::std::string* mutable_$name$()$deprecation$;\n");
+    "inline ::std::string* mutable_$name$()$deprecation$;\n"
+    "inline ::std::string* release_$name$()$deprecation$;\n");
 
   if (descriptor_->options().ctype() != FieldOptions::STRING) {
     printer->Outdent();
@@ -121,51 +126,58 @@
     "  return *$name$_;\n"
     "}\n"
     "inline void $classname$::set_$name$(const ::std::string& value) {\n"
-    "  _set_bit($index$);\n"
-    "  if ($name$_ == &_default_$name$_) {\n"
+    "  set_has_$name$();\n"
+    "  if ($name$_ == &$default_variable$) {\n"
     "    $name$_ = new ::std::string;\n"
     "  }\n"
     "  $name$_->assign(value);\n"
     "}\n"
     "inline void $classname$::set_$name$(const char* value) {\n"
-    "  _set_bit($index$);\n"
-    "  if ($name$_ == &_default_$name$_) {\n"
+    "  set_has_$name$();\n"
+    "  if ($name$_ == &$default_variable$) {\n"
     "    $name$_ = new ::std::string;\n"
     "  }\n"
     "  $name$_->assign(value);\n"
     "}\n"
     "inline "
     "void $classname$::set_$name$(const $pointer_type$* value, size_t size) {\n"
-    "  _set_bit($index$);\n"
-    "  if ($name$_ == &_default_$name$_) {\n"
+    "  set_has_$name$();\n"
+    "  if ($name$_ == &$default_variable$) {\n"
     "    $name$_ = new ::std::string;\n"
     "  }\n"
     "  $name$_->assign(reinterpret_cast<const char*>(value), size);\n"
     "}\n"
     "inline ::std::string* $classname$::mutable_$name$() {\n"
-    "  _set_bit($index$);\n"
-    "  if ($name$_ == &_default_$name$_) {\n");
+    "  set_has_$name$();\n"
+    "  if ($name$_ == &$default_variable$) {\n");
   if (descriptor_->default_value_string().empty()) {
     printer->Print(variables_,
       "    $name$_ = new ::std::string;\n");
   } else {
     printer->Print(variables_,
-      "    $name$_ = new ::std::string(_default_$name$_);\n");
+      "    $name$_ = new ::std::string($default_variable$);\n");
   }
   printer->Print(variables_,
     "  }\n"
     "  return $name$_;\n"
+    "}\n"
+    "inline ::std::string* $classname$::release_$name$() {\n"
+    "  clear_has_$name$();\n"
+    "  if ($name$_ == &$default_variable$) {\n"
+    "    return NULL;\n"
+    "  } else {\n"
+    "    ::std::string* temp = $name$_;\n"
+    "    $name$_ = const_cast< ::std::string*>(&$default_variable$);\n"
+    "    return temp;\n"
+    "  }\n"
     "}\n");
 }
 
 void StringFieldGenerator::
 GenerateNonInlineAccessorDefinitions(io::Printer* printer) const {
-  if (descriptor_->default_value_string().empty()) {
+  if (!descriptor_->default_value_string().empty()) {
     printer->Print(variables_,
-      "const ::std::string $classname$::_default_$name$_;\n");
-  } else {
-    printer->Print(variables_,
-      "const ::std::string $classname$::_default_$name$_($default$);\n");
+      "const ::std::string $classname$::$default_variable$($default$);\n");
   }
 }
 
@@ -173,13 +185,13 @@
 GenerateClearingCode(io::Printer* printer) const {
   if (descriptor_->default_value_string().empty()) {
     printer->Print(variables_,
-      "if ($name$_ != &_default_$name$_) {\n"
+      "if ($name$_ != &$default_variable$) {\n"
       "  $name$_->clear();\n"
       "}\n");
   } else {
     printer->Print(variables_,
-      "if ($name$_ != &_default_$name$_) {\n"
-      "  $name$_->assign(_default_$name$_);\n"
+      "if ($name$_ != &$default_variable$) {\n"
+      "  $name$_->assign($default_variable$);\n"
       "}\n");
   }
 }
@@ -197,13 +209,13 @@
 void StringFieldGenerator::
 GenerateConstructorCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "$name$_ = const_cast< ::std::string*>(&_default_$name$_);\n");
+    "$name$_ = const_cast< ::std::string*>(&$default_variable$);\n");
 }
 
 void StringFieldGenerator::
 GenerateDestructorCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "if ($name$_ != &_default_$name$_) {\n"
+    "if ($name$_ != &$default_variable$) {\n"
     "  delete $name$_;\n"
     "}\n");
 }
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 79971a9..54d830f 100644
--- a/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
+++ b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
@@ -36,6 +36,10 @@
 // though the same identifiers are used internally by the C++ code generator.
 
 
+// Some generic_services option(s) added automatically.
+// See:  http://go/proto2-generic-services-default
+option cc_generic_services = true;     // auto-added
+
 // We don't put this in a package within proto2 because we need to make sure
 // that the generated code doesn't depend on being in the proto2 namespace.
 package protobuf_unittest;
diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
index a7e852d..41ba5e4 100644
--- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
@@ -195,6 +195,48 @@
   EXPECT_EQ("hello", *message.mutable_default_string());
 }
 
+TEST(GeneratedMessageTest, ReleaseString) {
+  // Check that release_foo() starts out NULL, and gives us a value
+  // that we can delete after it's been set.
+  unittest::TestAllTypes message;
+
+  EXPECT_EQ(NULL, message.release_default_string());
+  EXPECT_FALSE(message.has_default_string());
+  EXPECT_EQ("hello", message.default_string());
+
+  message.set_default_string("blah");
+  EXPECT_TRUE(message.has_default_string());
+  string* str = message.release_default_string();
+  EXPECT_FALSE(message.has_default_string());
+  ASSERT_TRUE(str != NULL);
+  EXPECT_EQ("blah", *str);
+  delete str;
+
+  EXPECT_EQ(NULL, message.release_default_string());
+  EXPECT_FALSE(message.has_default_string());
+  EXPECT_EQ("hello", message.default_string());
+}
+
+TEST(GeneratedMessageTest, ReleaseMessage) {
+  // Check that release_foo() starts out NULL, and gives us a value
+  // that we can delete after it's been set.
+  unittest::TestAllTypes message;
+
+  EXPECT_EQ(NULL, message.release_optional_nested_message());
+  EXPECT_FALSE(message.has_optional_nested_message());
+
+  message.mutable_optional_nested_message()->set_bb(1);
+  unittest::TestAllTypes::NestedMessage* nest =
+      message.release_optional_nested_message();
+  EXPECT_FALSE(message.has_optional_nested_message());
+  ASSERT_TRUE(nest != NULL);
+  EXPECT_EQ(1, nest->bb());
+  delete nest;
+
+  EXPECT_EQ(NULL, message.release_optional_nested_message());
+  EXPECT_FALSE(message.has_optional_nested_message());
+}
+
 TEST(GeneratedMessageTest, Clear) {
   // Set every field to a unique value, clear the message, then check that
   // it is cleared.
@@ -282,6 +324,7 @@
   TestUtil::ExpectAllFieldsSet(message2);
 }
 
+
 TEST(GeneratedMessageTest, SwapWithEmpty) {
   unittest::TestAllTypes message1, message2;
   TestUtil::SetAllFields(&message1);
@@ -376,7 +419,7 @@
   TestUtil::ExpectAllFieldsSet(message2);
 
   // Make sure that self-assignment does something sane.
-  message2 = message2;
+  message2.operator=(message2);
   TestUtil::ExpectAllFieldsSet(message2);
 }
 
@@ -718,6 +761,7 @@
 
 #endif  // !PROTOBUF_TEST_NO_DESCRIPTORS
 
+
 TEST(GeneratedMessageTest, FieldConstantValues) {
   unittest::TestRequired message;
   EXPECT_EQ(unittest::TestAllTypes_NestedMessage::kBbFieldNumber, 1);
diff --git a/src/google/protobuf/compiler/java/java_enum.cc b/src/google/protobuf/compiler/java/java_enum.cc
index e796587..9d7bcab 100644
--- a/src/google/protobuf/compiler/java/java_enum.cc
+++ b/src/google/protobuf/compiler/java/java_enum.cc
@@ -104,6 +104,15 @@
       "public static final $classname$ $name$ = $canonical_name$;\n");
   }
 
+  for (int i = 0; i < descriptor_->value_count(); i++) {
+    map<string, string> vars;
+    vars["name"] = descriptor_->value(i)->name();
+    vars["number"] = SimpleItoa(descriptor_->value(i)->number());
+    printer->Print(vars,
+      "public static final int $name$_VALUE = $number$;\n");
+  }
+  printer->Print("\n");
+
   // -----------------------------------------------------------------
 
   printer->Print(
@@ -219,17 +228,6 @@
     "  this.value = value;\n"
     "}\n");
 
-  if (HasDescriptorMethods(descriptor_)) {
-    // Force the static initialization code for the file to run, since it may
-    // initialize static variables declared in this class.
-    printer->Print(
-      "\n"
-      "static {\n"
-      "  $file$.getDescriptor();\n"
-      "}\n",
-      "file", ClassName(descriptor_->file()));
-  }
-
   printer->Print(
     "\n"
     "// @@protoc_insertion_point(enum_scope:$full_name$)\n",
diff --git a/src/google/protobuf/compiler/java/java_enum_field.cc b/src/google/protobuf/compiler/java/java_enum_field.cc
index af6b1cd..72caa10 100644
--- a/src/google/protobuf/compiler/java/java_enum_field.cc
+++ b/src/google/protobuf/compiler/java/java_enum_field.cc
@@ -52,17 +52,44 @@
 // TODO(kenton):  Factor out a "SetCommonFieldVariables()" to get rid of
 //   repeat code between this and the other field types.
 void SetEnumVariables(const FieldDescriptor* descriptor,
+                      int messageBitIndex,
+                      int builderBitIndex,
                       map<string, string>* variables) {
   (*variables)["name"] =
     UnderscoresToCamelCase(descriptor);
   (*variables)["capitalized_name"] =
     UnderscoresToCapitalizedCamelCase(descriptor);
+  (*variables)["constant_name"] = FieldConstantName(descriptor);
   (*variables)["number"] = SimpleItoa(descriptor->number());
   (*variables)["type"] = ClassName(descriptor->enum_type());
   (*variables)["default"] = DefaultValue(descriptor);
   (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
   (*variables)["tag_size"] = SimpleItoa(
       internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
+  // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
+  // by the proto compiler
+  (*variables)["deprecation"] = descriptor->options().deprecated()
+      ? "@java.lang.Deprecated " : "";
+  (*variables)["on_changed"] =
+      HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
+
+  // For singular messages and builders, one bit is used for the hasField bit.
+  (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+
+  (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
+  (*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex);
+  (*variables)["clear_has_field_bit_builder"] =
+      GenerateClearBit(builderBitIndex);
+
+  // For repated builders, one bit is used for whether the array is immutable.
+  (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
+  (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
+  (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
+
+  (*variables)["get_has_field_bit_from_local"] =
+      GenerateGetBitFromLocal(builderBitIndex);
+  (*variables)["set_has_field_bit_to_local"] =
+      GenerateSetBitToLocal(messageBitIndex);
 }
 
 }  // namespace
@@ -70,52 +97,88 @@
 // ===================================================================
 
 EnumFieldGenerator::
-EnumFieldGenerator(const FieldDescriptor* descriptor)
-  : descriptor_(descriptor) {
-  SetEnumVariables(descriptor, &variables_);
+EnumFieldGenerator(const FieldDescriptor* descriptor,
+                      int messageBitIndex,
+                      int builderBitIndex)
+  : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+    builderBitIndex_(builderBitIndex) {
+  SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, &variables_);
 }
 
 EnumFieldGenerator::~EnumFieldGenerator() {}
 
+int EnumFieldGenerator::GetNumBitsForMessage() const {
+  return 1;
+}
+
+int EnumFieldGenerator::GetNumBitsForBuilder() const {
+  return 1;
+}
+
+void EnumFieldGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$deprecation$boolean has$capitalized_name$();\n"
+    "$deprecation$$type$ get$capitalized_name$();\n");
+}
+
 void EnumFieldGenerator::
 GenerateMembers(io::Printer* printer) const {
   printer->Print(variables_,
-    "private boolean has$capitalized_name$;\n"
     "private $type$ $name$_;\n"
-    "public boolean has$capitalized_name$() { return has$capitalized_name$; }\n"
-    "public $type$ get$capitalized_name$() { return $name$_; }\n");
+    "$deprecation$public boolean has$capitalized_name$() {\n"
+    "  return $get_has_field_bit_message$;\n"
+    "}\n"
+    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "  return $name$_;\n"
+    "}\n");
 }
 
 void EnumFieldGenerator::
 GenerateBuilderMembers(io::Printer* printer) const {
   printer->Print(variables_,
-    "public boolean has$capitalized_name$() {\n"
-    "  return result.has$capitalized_name$();\n"
+    "private $type$ $name$_ = $default$;\n"
+    "$deprecation$public boolean has$capitalized_name$() {\n"
+    "  return $get_has_field_bit_builder$;\n"
     "}\n"
-    "public $type$ get$capitalized_name$() {\n"
-    "  return result.get$capitalized_name$();\n"
+    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "  return $name$_;\n"
     "}\n"
-    "public Builder set$capitalized_name$($type$ value) {\n"
+    "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
     "  if (value == null) {\n"
     "    throw new NullPointerException();\n"
     "  }\n"
-    "  result.has$capitalized_name$ = true;\n"
-    "  result.$name$_ = value;\n"
+    "  $set_has_field_bit_builder$;\n"
+    "  $name$_ = value;\n"
+    "  $on_changed$\n"
     "  return this;\n"
     "}\n"
-    "public Builder clear$capitalized_name$() {\n"
-    "  result.has$capitalized_name$ = false;\n"
-    "  result.$name$_ = $default$;\n"
+    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "  $clear_has_field_bit_builder$;\n"
+    "  $name$_ = $default$;\n"
+    "  $on_changed$\n"
     "  return this;\n"
     "}\n");
 }
 
 void EnumFieldGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
+  // noop for enums
+}
+
+void EnumFieldGenerator::
 GenerateInitializationCode(io::Printer* printer) const {
   printer->Print(variables_, "$name$_ = $default$;\n");
 }
 
 void EnumFieldGenerator::
+GenerateBuilderClearCode(io::Printer* printer) const {
+  printer->Print(variables_,
+      "$name$_ = $default$;\n"
+      "$clear_has_field_bit_builder$;\n");
+}
+
+void EnumFieldGenerator::
 GenerateMergingCode(io::Printer* printer) const {
   printer->Print(variables_,
     "if (other.has$capitalized_name$()) {\n"
@@ -125,7 +188,11 @@
 
 void EnumFieldGenerator::
 GenerateBuildingCode(io::Printer* printer) const {
-  // Nothing to do here for enum types.
+  printer->Print(variables_,
+    "if ($get_has_field_bit_from_local$) {\n"
+    "  $set_has_field_bit_to_local$;\n"
+    "}\n"
+    "result.$name$_ = $name$_;\n");
 }
 
 void EnumFieldGenerator::
@@ -143,27 +210,42 @@
       "if (value != null) {\n");
   }
   printer->Print(variables_,
-    "  set$capitalized_name$(value);\n"
+    "  $set_has_field_bit_builder$;\n"
+    "  $name$_ = value;\n"
     "}\n");
 }
 
 void EnumFieldGenerator::
 GenerateSerializationCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "if (has$capitalized_name$()) {\n"
-    "  output.writeEnum($number$, get$capitalized_name$().getNumber());\n"
+    "if ($get_has_field_bit_message$) {\n"
+    "  output.writeEnum($number$, $name$_.getNumber());\n"
     "}\n");
 }
 
 void EnumFieldGenerator::
 GenerateSerializedSizeCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "if (has$capitalized_name$()) {\n"
+    "if ($get_has_field_bit_message$) {\n"
     "  size += com.google.protobuf.CodedOutputStream\n"
-    "    .computeEnumSize($number$, get$capitalized_name$().getNumber());\n"
+    "    .computeEnumSize($number$, $name$_.getNumber());\n"
     "}\n");
 }
 
+void EnumFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "result = result &&\n"
+    "    (get$capitalized_name$() == other.get$capitalized_name$());\n");
+}
+
+void EnumFieldGenerator::
+GenerateHashCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "hash = (37 * hash) + $constant_name$;\n"
+    "hash = (53 * hash) + hashEnum(get$capitalized_name$());\n");
+}
+
 string EnumFieldGenerator::GetBoxedType() const {
   return ClassName(descriptor_->enum_type());
 }
@@ -171,23 +253,43 @@
 // ===================================================================
 
 RepeatedEnumFieldGenerator::
-RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor)
-  : descriptor_(descriptor) {
-  SetEnumVariables(descriptor, &variables_);
+RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
+                           int messageBitIndex,
+                           int builderBitIndex)
+  : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+    builderBitIndex_(builderBitIndex) {
+  SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, &variables_);
 }
 
 RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
 
+int RepeatedEnumFieldGenerator::GetNumBitsForMessage() const {
+  return 0;
+}
+
+int RepeatedEnumFieldGenerator::GetNumBitsForBuilder() const {
+  return 1;
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$deprecation$java.util.List<$type$> get$capitalized_name$List();\n"
+    "$deprecation$int get$capitalized_name$Count();\n"
+    "$deprecation$$type$ get$capitalized_name$(int index);\n");
+}
+
 void RepeatedEnumFieldGenerator::
 GenerateMembers(io::Printer* printer) const {
   printer->Print(variables_,
-    "private java.util.List<$type$> $name$_ =\n"
-    "  java.util.Collections.emptyList();\n"
-    "public java.util.List<$type$> get$capitalized_name$List() {\n"
+    "private java.util.List<$type$> $name$_;\n"
+    "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
     "  return $name$_;\n"   // note:  unmodifiable list
     "}\n"
-    "public int get$capitalized_name$Count() { return $name$_.size(); }\n"
-    "public $type$ get$capitalized_name$(int index) {\n"
+    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "  return $name$_.size();\n"
+    "}\n"
+    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
     "  return $name$_.get(index);\n"
     "}\n");
 
@@ -201,73 +303,119 @@
 void RepeatedEnumFieldGenerator::
 GenerateBuilderMembers(io::Printer* printer) const {
   printer->Print(variables_,
+    // One field is the list and the other field keeps track of whether the
+    // list is immutable. If it's immutable, the invariant is that it must
+    // either an instance of Collections.emptyList() or it's an ArrayList
+    // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
+    // a refererence to the underlying ArrayList. This invariant allows us to
+    // share instances of lists between protocol buffers avoiding expensive
+    // memory allocations. Note, immutable is a strong guarantee here -- not
+    // just that the list cannot be modified via the reference but that the
+    // list can never be modified.
+    "private java.util.List<$type$> $name$_ =\n"
+    "  java.util.Collections.emptyList();\n"
+
+    "private void ensure$capitalized_name$IsMutable() {\n"
+    "  if (!$get_mutable_bit_builder$) {\n"
+    "    $name$_ = new java.util.ArrayList<$type$>($name$_);\n"
+    "    $set_mutable_bit_builder$;\n"
+    "  }\n"
+    "}\n"
+
     // Note:  We return an unmodifiable list because otherwise the caller
     //   could hold on to the returned list and modify it after the message
     //   has been built, thus mutating the message which is supposed to be
     //   immutable.
-    "public java.util.List<$type$> get$capitalized_name$List() {\n"
-    "  return java.util.Collections.unmodifiableList(result.$name$_);\n"
+    "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
+    "  return java.util.Collections.unmodifiableList($name$_);\n"
     "}\n"
-    "public int get$capitalized_name$Count() {\n"
-    "  return result.get$capitalized_name$Count();\n"
+    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "  return $name$_.size();\n"
     "}\n"
-    "public $type$ get$capitalized_name$(int index) {\n"
-    "  return result.get$capitalized_name$(index);\n"
+    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "  return $name$_.get(index);\n"
     "}\n"
-    "public Builder set$capitalized_name$(int index, $type$ value) {\n"
+    "$deprecation$public Builder set$capitalized_name$(\n"
+    "    int index, $type$ value) {\n"
     "  if (value == null) {\n"
     "    throw new NullPointerException();\n"
     "  }\n"
-    "  result.$name$_.set(index, value);\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.set(index, value);\n"
+    "  $on_changed$\n"
     "  return this;\n"
     "}\n"
-    "public Builder add$capitalized_name$($type$ value) {\n"
+    "$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
     "  if (value == null) {\n"
     "    throw new NullPointerException();\n"
     "  }\n"
-    "  if (result.$name$_.isEmpty()) {\n"
-    "    result.$name$_ = new java.util.ArrayList<$type$>();\n"
-    "  }\n"
-    "  result.$name$_.add(value);\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.add(value);\n"
+    "  $on_changed$\n"
     "  return this;\n"
     "}\n"
-    "public Builder addAll$capitalized_name$(\n"
+    "$deprecation$public Builder addAll$capitalized_name$(\n"
     "    java.lang.Iterable<? extends $type$> values) {\n"
-    "  if (result.$name$_.isEmpty()) {\n"
-    "    result.$name$_ = new java.util.ArrayList<$type$>();\n"
-    "  }\n"
-    "  super.addAll(values, result.$name$_);\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  super.addAll(values, $name$_);\n"
+    "  $on_changed$\n"
     "  return this;\n"
     "}\n"
-    "public Builder clear$capitalized_name$() {\n"
-    "  result.$name$_ = java.util.Collections.emptyList();\n"
+    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "  $name$_ = java.util.Collections.emptyList();\n"
+    "  $clear_mutable_bit_builder$;\n"
+    "  $on_changed$\n"
     "  return this;\n"
     "}\n");
 }
 
 void RepeatedEnumFieldGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
+  // noop for enums
+}
+
+void RepeatedEnumFieldGenerator::
 GenerateInitializationCode(io::Printer* printer) const {
-  // Initialized inline.
+  printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n");
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateBuilderClearCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$name$_ = java.util.Collections.emptyList();\n"
+    "$clear_mutable_bit_builder$;\n");
 }
 
 void RepeatedEnumFieldGenerator::
 GenerateMergingCode(io::Printer* printer) const {
+  // The code below does two optimizations:
+  //   1. If the other list is empty, there's nothing to do. This ensures we
+  //      don't allocate a new array if we already have an immutable one.
+  //   2. If the other list is non-empty and our current list is empty, we can
+  //      reuse the other list which is guaranteed to be immutable.
   printer->Print(variables_,
     "if (!other.$name$_.isEmpty()) {\n"
-    "  if (result.$name$_.isEmpty()) {\n"
-    "    result.$name$_ = new java.util.ArrayList<$type$>();\n"
+    "  if ($name$_.isEmpty()) {\n"
+    "    $name$_ = other.$name$_;\n"
+    "    $clear_mutable_bit_builder$;\n"
+    "  } else {\n"
+    "    ensure$capitalized_name$IsMutable();\n"
+    "    $name$_.addAll(other.$name$_);\n"
     "  }\n"
-    "  result.$name$_.addAll(other.$name$_);\n"
+    "  $on_changed$\n"
     "}\n");
 }
 
 void RepeatedEnumFieldGenerator::
 GenerateBuildingCode(io::Printer* printer) const {
+  // The code below ensures that the result has an immutable list. If our
+  // list is immutable, we can just reuse it. If not, we make it immutable.
   printer->Print(variables_,
-    "if (result.$name$_ != java.util.Collections.EMPTY_LIST) {\n"
-    "  result.$name$_ =\n"
-    "    java.util.Collections.unmodifiableList(result.$name$_);\n"
-    "}\n");
+    "if ($get_mutable_bit_builder$) {\n"
+    "  $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
+    "  $clear_mutable_bit_builder$;\n"
+    "}\n"
+    "result.$name$_ = $name$_;\n");
 }
 
 void RepeatedEnumFieldGenerator::
@@ -316,13 +464,13 @@
       "  output.writeRawVarint32($tag$);\n"
       "  output.writeRawVarint32($name$MemoizedSerializedSize);\n"
       "}\n"
-      "for ($type$ element : get$capitalized_name$List()) {\n"
-      "  output.writeEnumNoTag(element.getNumber());\n"
+      "for (int i = 0; i < $name$_.size(); i++) {\n"
+      "  output.writeEnumNoTag($name$_.get(i).getNumber());\n"
       "}\n");
   } else {
     printer->Print(variables_,
-      "for ($type$ element : get$capitalized_name$List()) {\n"
-      "  output.writeEnum($number$, element.getNumber());\n"
+      "for (int i = 0; i < $name$_.size(); i++) {\n"
+      "  output.writeEnum($number$, $name$_.get(i).getNumber());\n"
       "}\n");
   }
 }
@@ -335,9 +483,9 @@
   printer->Indent();
 
   printer->Print(variables_,
-    "for ($type$ element : get$capitalized_name$List()) {\n"
+    "for (int i = 0; i < $name$_.size(); i++) {\n"
     "  dataSize += com.google.protobuf.CodedOutputStream\n"
-    "    .computeEnumSizeNoTag(element.getNumber());\n"
+    "    .computeEnumSizeNoTag($name$_.get(i).getNumber());\n"
     "}\n");
   printer->Print(
     "size += dataSize;\n");
@@ -350,7 +498,7 @@
       "}");
   } else {
     printer->Print(variables_,
-      "size += $tag_size$ * get$capitalized_name$List().size();\n");
+      "size += $tag_size$ * $name$_.size();\n");
   }
 
   // cache the data size for packed fields.
@@ -363,6 +511,22 @@
   printer->Print("}\n");
 }
 
+void RepeatedEnumFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "result = result && get$capitalized_name$List()\n"
+    "    .equals(other.get$capitalized_name$List());\n");
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateHashCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (get$capitalized_name$Count() > 0) {\n"
+    "  hash = (37 * hash) + $constant_name$;\n"
+    "  hash = (53 * hash) + hashEnumList(get$capitalized_name$List());\n"
+    "}\n");
+}
+
 string RepeatedEnumFieldGenerator::GetBoxedType() const {
   return ClassName(descriptor_->enum_type());
 }
diff --git a/src/google/protobuf/compiler/java/java_enum_field.h b/src/google/protobuf/compiler/java/java_enum_field.h
index c54a0fa..0cad6be 100644
--- a/src/google/protobuf/compiler/java/java_enum_field.h
+++ b/src/google/protobuf/compiler/java/java_enum_field.h
@@ -46,49 +46,69 @@
 
 class EnumFieldGenerator : public FieldGenerator {
  public:
-  explicit EnumFieldGenerator(const FieldDescriptor* descriptor);
+  explicit EnumFieldGenerator(const FieldDescriptor* descriptor,
+      int messageBitIndex, int builderBitIndex);
   ~EnumFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
+  int GetNumBitsForMessage() const;
+  int GetNumBitsForBuilder() const;
+  void GenerateInterfaceMembers(io::Printer* printer) const;
   void GenerateMembers(io::Printer* printer) const;
   void GenerateBuilderMembers(io::Printer* printer) const;
   void GenerateInitializationCode(io::Printer* printer) const;
+  void GenerateBuilderClearCode(io::Printer* printer) const;
   void GenerateMergingCode(io::Printer* printer) const;
   void GenerateBuildingCode(io::Printer* printer) const;
   void GenerateParsingCode(io::Printer* printer) const;
   void GenerateSerializationCode(io::Printer* printer) const;
   void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCode(io::Printer* printer) const;
 
   string GetBoxedType() const;
 
  private:
   const FieldDescriptor* descriptor_;
   map<string, string> variables_;
+  const int messageBitIndex_;
+  const int builderBitIndex_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator);
 };
 
 class RepeatedEnumFieldGenerator : public FieldGenerator {
  public:
-  explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor);
+  explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
+      int messageBitIndex, int builderBitIndex);
   ~RepeatedEnumFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
+  int GetNumBitsForMessage() const;
+  int GetNumBitsForBuilder() const;
+  void GenerateInterfaceMembers(io::Printer* printer) const;
   void GenerateMembers(io::Printer* printer) const;
   void GenerateBuilderMembers(io::Printer* printer) const;
   void GenerateInitializationCode(io::Printer* printer) const;
+  void GenerateBuilderClearCode(io::Printer* printer) const;
   void GenerateMergingCode(io::Printer* printer) const;
   void GenerateBuildingCode(io::Printer* printer) const;
   void GenerateParsingCode(io::Printer* printer) const;
   void GenerateParsingCodeFromPacked(io::Printer* printer) const;
   void GenerateSerializationCode(io::Printer* printer) const;
   void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCode(io::Printer* printer) const;
 
   string GetBoxedType() const;
 
  private:
   const FieldDescriptor* descriptor_;
   map<string, string> variables_;
+  const int messageBitIndex_;
+  const int builderBitIndex_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator);
 };
diff --git a/src/google/protobuf/compiler/java/java_extension.cc b/src/google/protobuf/compiler/java/java_extension.cc
index 903b0a9..9b147c7 100644
--- a/src/google/protobuf/compiler/java/java_extension.cc
+++ b/src/google/protobuf/compiler/java/java_extension.cc
@@ -86,105 +86,120 @@
 
 ExtensionGenerator::~ExtensionGenerator() {}
 
-void ExtensionGenerator::Generate(io::Printer* printer) {
-  map<string, string> vars;
-  vars["name"] = UnderscoresToCamelCase(descriptor_);
-  vars["containing_type"] = ClassName(descriptor_->containing_type());
-  vars["number"] = SimpleItoa(descriptor_->number());
-  vars["constant_name"] = FieldConstantName(descriptor_);
-  vars["lite"] = HasDescriptorMethods(descriptor_->file()) ? "" : "Lite";
-
-  JavaType java_type = GetJavaType(descriptor_);
-  string singular_type;
-  switch (java_type) {
-    case JAVATYPE_MESSAGE:
-      vars["type"] = ClassName(descriptor_->message_type());
-      break;
-    case JAVATYPE_ENUM:
-      vars["type"] = ClassName(descriptor_->enum_type());
-      break;
-    default:
-      vars["type"] = BoxedPrimitiveTypeName(java_type);
-      break;
-  }
-
-  printer->Print(vars,
-    "public static final int $constant_name$ = $number$;\n");
-  if (descriptor_->is_repeated()) {
-    printer->Print(vars,
-      "public static final\n"
-      "  com.google.protobuf.GeneratedMessage$lite$.GeneratedExtension<\n"
-      "    $containing_type$,\n"
-      "    java.util.List<$type$>> $name$ =\n"
-      "      com.google.protobuf.GeneratedMessage$lite$\n"
-      "        .newGeneratedExtension();\n");
-  } else {
-    printer->Print(vars,
-      "public static final\n"
-      "  com.google.protobuf.GeneratedMessage$lite$.GeneratedExtension<\n"
-      "    $containing_type$,\n"
-      "    $type$> $name$ =\n"
-      "      com.google.protobuf.GeneratedMessage$lite$\n"
-      "        .newGeneratedExtension();\n");
-  }
-}
-
-void ExtensionGenerator::GenerateInitializationCode(io::Printer* printer) {
-  map<string, string> vars;
-  vars["name"] = UnderscoresToCamelCase(descriptor_);
-  vars["scope"] = scope_;
-  vars["index"] = SimpleItoa(descriptor_->index());
-  vars["extendee"] = ClassName(descriptor_->containing_type());
-  vars["default"] = descriptor_->is_repeated() ? "" : DefaultValue(descriptor_);
-  vars["number"] = SimpleItoa(descriptor_->number());
-  vars["type_constant"] = TypeName(GetType(descriptor_));
-  vars["packed"] = descriptor_->options().packed() ? "true" : "false";
+// Initializes the vars referenced in the generated code templates.
+void InitTemplateVars(const FieldDescriptor* descriptor,
+                      const string& scope,
+                      map<string, string>* vars_pointer) {
+  map<string, string> &vars = *vars_pointer;
+  vars["scope"] = scope;
+  vars["name"] = UnderscoresToCamelCase(descriptor);
+  vars["containing_type"] = ClassName(descriptor->containing_type());
+  vars["number"] = SimpleItoa(descriptor->number());
+  vars["constant_name"] = FieldConstantName(descriptor);
+  vars["index"] = SimpleItoa(descriptor->index());
+  vars["default"] =
+      descriptor->is_repeated() ? "" : DefaultValue(descriptor);
+  vars["type_constant"] = TypeName(GetType(descriptor));
+  vars["packed"] = descriptor->options().packed() ? "true" : "false";
   vars["enum_map"] = "null";
   vars["prototype"] = "null";
 
-  JavaType java_type = GetJavaType(descriptor_);
+  JavaType java_type = GetJavaType(descriptor);
   string singular_type;
   switch (java_type) {
     case JAVATYPE_MESSAGE:
-      vars["type"] = ClassName(descriptor_->message_type());
-      vars["prototype"] = ClassName(descriptor_->message_type()) +
-                          ".getDefaultInstance()";
+      singular_type = ClassName(descriptor->message_type());
+      vars["prototype"] = singular_type + ".getDefaultInstance()";
       break;
     case JAVATYPE_ENUM:
-      vars["type"] = ClassName(descriptor_->enum_type());
-      vars["enum_map"] = ClassName(descriptor_->enum_type()) +
-                         ".internalGetValueMap()";
+      singular_type = ClassName(descriptor->enum_type());
+      vars["enum_map"] = singular_type + ".internalGetValueMap()";
       break;
     default:
-      vars["type"] = BoxedPrimitiveTypeName(java_type);
+      singular_type = BoxedPrimitiveTypeName(java_type);
       break;
   }
+  vars["type"] = descriptor->is_repeated() ?
+      "java.util.List<" + singular_type + ">" : singular_type;
+  vars["singular_type"] = singular_type;
+}
+
+void ExtensionGenerator::Generate(io::Printer* printer) {
+  map<string, string> vars;
+  InitTemplateVars(descriptor_, scope_, &vars);
+  printer->Print(vars,
+      "public static final int $constant_name$ = $number$;\n");
 
   if (HasDescriptorMethods(descriptor_->file())) {
-    printer->Print(vars,
-      "$scope$.$name$.internalInit(\n"
-      "    $scope$.getDescriptor().getExtensions().get($index$),\n"
-      "    $type$.class);\n");
-  } else {
-    if (descriptor_->is_repeated()) {
-      printer->Print(vars,
-        "$scope$.$name$.internalInitRepeated(\n"
-        "    $extendee$.getDefaultInstance(),\n"
-        "    $prototype$,\n"
-        "    $enum_map$,\n"
-        "    $number$,\n"
-        "    com.google.protobuf.WireFormat.FieldType.$type_constant$,\n"
-        "    $packed$);\n");
+    // Non-lite extensions
+    if (descriptor_->extension_scope() == NULL) {
+      // Non-nested
+      printer->Print(
+          vars,
+          "public static final\n"
+          "  com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
+          "    $containing_type$,\n"
+          "    $type$> $name$ = com.google.protobuf.GeneratedMessage\n"
+          "        .newFileScopedGeneratedExtension(\n"
+          "      $singular_type$.class,\n"
+          "      $prototype$);\n");
     } else {
-      printer->Print(vars,
-        "$scope$.$name$.internalInitSingular(\n"
-        "    $extendee$.getDefaultInstance(),\n"
-        "    $default$,\n"
-        "    $prototype$,\n"
-        "    $enum_map$,\n"
-        "    $number$,\n"
-        "    com.google.protobuf.WireFormat.FieldType.$type_constant$);\n");
+      // Nested
+      printer->Print(
+          vars,
+          "public static final\n"
+          "  com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
+          "    $containing_type$,\n"
+          "    $type$> $name$ = com.google.protobuf.GeneratedMessage\n"
+          "        .newMessageScopedGeneratedExtension(\n"
+          "      $scope$.getDefaultInstance(),\n"
+          "      $index$,\n"
+          "      $singular_type$.class,\n"
+          "      $prototype$);\n");
     }
+  } else {
+    // Lite extensions
+    if (descriptor_->is_repeated()) {
+      printer->Print(
+          vars,
+          "public static final\n"
+          "  com.google.protobuf.GeneratedMessageLite.GeneratedExtension<\n"
+          "    $containing_type$,\n"
+          "    $type$> $name$ = com.google.protobuf.GeneratedMessageLite\n"
+          "        .newRepeatedGeneratedExtension(\n"
+          "      $containing_type$.getDefaultInstance(),\n"
+          "      $prototype$,\n"
+          "      $enum_map$,\n"
+          "      $number$,\n"
+          "      com.google.protobuf.WireFormat.FieldType.$type_constant$,\n"
+          "      $packed$);\n");
+    } else {
+      printer->Print(
+          vars,
+          "public static final\n"
+          "  com.google.protobuf.GeneratedMessageLite.GeneratedExtension<\n"
+          "    $containing_type$,\n"
+          "    $type$> $name$ = com.google.protobuf.GeneratedMessageLite\n"
+          "        .newSingularGeneratedExtension(\n"
+          "      $containing_type$.getDefaultInstance(),\n"
+          "      $default$,\n"
+          "      $prototype$,\n"
+          "      $enum_map$,\n"
+          "      $number$,\n"
+          "      com.google.protobuf.WireFormat.FieldType.$type_constant$);\n");
+    }
+  }
+}
+
+void ExtensionGenerator::GenerateNonNestedInitializationCode(
+    io::Printer* printer) {
+  if (descriptor_->extension_scope() == NULL &&
+      HasDescriptorMethods(descriptor_->file())) {
+    // Only applies to non-nested, non-lite extensions.
+    printer->Print(
+        "$name$.internalInit(descriptor.getExtensions().get($index$));\n",
+        "name", UnderscoresToCamelCase(descriptor_),
+        "index", SimpleItoa(descriptor_->index()));
   }
 }
 
diff --git a/src/google/protobuf/compiler/java/java_extension.h b/src/google/protobuf/compiler/java/java_extension.h
index 1e42304..009ed9f 100644
--- a/src/google/protobuf/compiler/java/java_extension.h
+++ b/src/google/protobuf/compiler/java/java_extension.h
@@ -60,7 +60,7 @@
   ~ExtensionGenerator();
 
   void Generate(io::Printer* printer);
-  void GenerateInitializationCode(io::Printer* printer);
+  void GenerateNonNestedInitializationCode(io::Printer* printer);
   void GenerateRegistrationCode(io::Printer* printer);
 
  private:
diff --git a/src/google/protobuf/compiler/java/java_field.cc b/src/google/protobuf/compiler/java/java_field.cc
index 978c8f3..c7d433c 100644
--- a/src/google/protobuf/compiler/java/java_field.cc
+++ b/src/google/protobuf/compiler/java/java_field.cc
@@ -37,6 +37,7 @@
 #include <google/protobuf/compiler/java/java_primitive_field.h>
 #include <google/protobuf/compiler/java/java_enum_field.h>
 #include <google/protobuf/compiler/java/java_message_field.h>
+#include <google/protobuf/compiler/java/java_string_field.h>
 #include <google/protobuf/stubs/common.h>
 
 namespace google {
@@ -63,33 +64,57 @@
     extension_generators_(
       new scoped_ptr<FieldGenerator>[descriptor->extension_count()]) {
 
-  // Construct all the FieldGenerators.
+  // Construct all the FieldGenerators and assign them bit indices for their
+  // bit fields.
+  int messageBitIndex = 0;
+  int builderBitIndex = 0;
   for (int i = 0; i < descriptor->field_count(); i++) {
-    field_generators_[i].reset(MakeGenerator(descriptor->field(i)));
+    FieldGenerator* generator = MakeGenerator(descriptor->field(i),
+        messageBitIndex, builderBitIndex);
+    field_generators_[i].reset(generator);
+    messageBitIndex += generator->GetNumBitsForMessage();
+    builderBitIndex += generator->GetNumBitsForBuilder();
   }
   for (int i = 0; i < descriptor->extension_count(); i++) {
-    extension_generators_[i].reset(MakeGenerator(descriptor->extension(i)));
+    FieldGenerator* generator = MakeGenerator(descriptor->extension(i),
+        messageBitIndex, builderBitIndex);
+    extension_generators_[i].reset(generator);
+    messageBitIndex += generator->GetNumBitsForMessage();
+    builderBitIndex += generator->GetNumBitsForBuilder();
   }
 }
 
-FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field) {
+FieldGenerator* FieldGeneratorMap::MakeGenerator(
+    const FieldDescriptor* field, int messageBitIndex, int builderBitIndex) {
   if (field->is_repeated()) {
     switch (GetJavaType(field)) {
       case JAVATYPE_MESSAGE:
-        return new RepeatedMessageFieldGenerator(field);
+        return new RepeatedMessageFieldGenerator(
+            field, messageBitIndex, builderBitIndex);
       case JAVATYPE_ENUM:
-        return new RepeatedEnumFieldGenerator(field);
+        return new RepeatedEnumFieldGenerator(
+            field, messageBitIndex, builderBitIndex);
+      case JAVATYPE_STRING:
+        return new RepeatedStringFieldGenerator(
+            field, messageBitIndex, builderBitIndex);
       default:
-        return new RepeatedPrimitiveFieldGenerator(field);
+        return new RepeatedPrimitiveFieldGenerator(
+            field, messageBitIndex, builderBitIndex);
     }
   } else {
     switch (GetJavaType(field)) {
       case JAVATYPE_MESSAGE:
-        return new MessageFieldGenerator(field);
+        return new MessageFieldGenerator(
+            field, messageBitIndex, builderBitIndex);
       case JAVATYPE_ENUM:
-        return new EnumFieldGenerator(field);
+        return new EnumFieldGenerator(
+            field, messageBitIndex, builderBitIndex);
+      case JAVATYPE_STRING:
+        return new StringFieldGenerator(
+            field, messageBitIndex, builderBitIndex);
       default:
-        return new PrimitiveFieldGenerator(field);
+        return new PrimitiveFieldGenerator(
+            field, messageBitIndex, builderBitIndex);
     }
   }
 }
diff --git a/src/google/protobuf/compiler/java/java_field.h b/src/google/protobuf/compiler/java/java_field.h
index f5bef7a..6097f35 100644
--- a/src/google/protobuf/compiler/java/java_field.h
+++ b/src/google/protobuf/compiler/java/java_field.h
@@ -55,15 +55,24 @@
   FieldGenerator() {}
   virtual ~FieldGenerator();
 
+  virtual int GetNumBitsForMessage() const = 0;
+  virtual int GetNumBitsForBuilder() const = 0;
+  virtual void GenerateInterfaceMembers(io::Printer* printer) const = 0;
   virtual void GenerateMembers(io::Printer* printer) const = 0;
   virtual void GenerateBuilderMembers(io::Printer* printer) const = 0;
   virtual void GenerateInitializationCode(io::Printer* printer) const = 0;
+  virtual void GenerateBuilderClearCode(io::Printer* printer) const = 0;
   virtual void GenerateMergingCode(io::Printer* printer) const = 0;
   virtual void GenerateBuildingCode(io::Printer* printer) const = 0;
   virtual void GenerateParsingCode(io::Printer* printer) const = 0;
   virtual void GenerateParsingCodeFromPacked(io::Printer* printer) const;
   virtual void GenerateSerializationCode(io::Printer* printer) const = 0;
   virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0;
+  virtual void GenerateFieldBuilderInitializationCode(io::Printer* printer)
+      const = 0;
+
+  virtual void GenerateEqualsCode(io::Printer* printer) const = 0;
+  virtual void GenerateHashCode(io::Printer* printer) const = 0;
 
   virtual string GetBoxedType() const = 0;
 
@@ -85,7 +94,8 @@
   scoped_array<scoped_ptr<FieldGenerator> > field_generators_;
   scoped_array<scoped_ptr<FieldGenerator> > extension_generators_;
 
-  static FieldGenerator* MakeGenerator(const FieldDescriptor* field);
+  static FieldGenerator* MakeGenerator(const FieldDescriptor* field,
+      int messageBitIndex, int builderBitIndex);
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
 };
diff --git a/src/google/protobuf/compiler/java/java_file.cc b/src/google/protobuf/compiler/java/java_file.cc
index 7ea127c..8968069 100644
--- a/src/google/protobuf/compiler/java/java_file.cc
+++ b/src/google/protobuf/compiler/java/java_file.cc
@@ -88,7 +88,8 @@
 FileGenerator::FileGenerator(const FileDescriptor* file)
   : file_(file),
     java_package_(FileJavaPackage(file)),
-    classname_(FileClassName(file)) {}
+    classname_(FileClassName(file)) {
+}
 
 FileGenerator::~FileGenerator() {}
 
@@ -179,7 +180,9 @@
       EnumGenerator(file_->enum_type(i)).Generate(printer);
     }
     for (int i = 0; i < file_->message_type_count(); i++) {
-      MessageGenerator(file_->message_type(i)).Generate(printer);
+      MessageGenerator messageGenerator(file_->message_type(i));
+      messageGenerator.GenerateInterface(printer);
+      messageGenerator.Generate(printer);
     }
     if (HasGenericServices(file_)) {
       for (int i = 0; i < file_->service_count(); i++) {
@@ -215,24 +218,11 @@
         .GenerateStaticVariableInitializers(printer);
     }
 
-    for (int i = 0; i < file_->extension_count(); i++) {
-      // TODO(kenton):  Reuse ExtensionGenerator objects?
-      ExtensionGenerator(file_->extension(i))
-        .GenerateInitializationCode(printer);
-    }
-
     printer->Outdent();
     printer->Print(
       "}\n");
   }
 
-  // Dummy function we can use to force the static initialization block to
-  // run.  Needed by inner classes.  Cannot be private due to
-  // java_multiple_files option.
-  printer->Print(
-    "\n"
-    "public static void internalForceInit() {}\n");
-
   printer->Print(
     "\n"
     "// @@protoc_insertion_point(outer_class_scope)\n");
@@ -310,11 +300,10 @@
     MessageGenerator(file_->message_type(i))
       .GenerateStaticVariableInitializers(printer);
   }
-
   for (int i = 0; i < file_->extension_count(); i++) {
     // TODO(kenton):  Reuse ExtensionGenerator objects?
     ExtensionGenerator(file_->extension(i))
-      .GenerateInitializationCode(printer);
+        .GenerateNonNestedInitializationCode(printer);
   }
 
   if (UsesExtensions(file_proto)) {
@@ -325,9 +314,11 @@
       "  com.google.protobuf.ExtensionRegistry.newInstance();\n"
       "registerAllExtensions(registry);\n");
     for (int i = 0; i < file_->dependency_count(); i++) {
-      printer->Print(
-        "$dependency$.registerAllExtensions(registry);\n",
-        "dependency", ClassName(file_->dependency(i)));
+      if (ShouldIncludeDependency(file_->dependency(i))) {
+        printer->Print(
+            "$dependency$.registerAllExtensions(registry);\n",
+            "dependency", ClassName(file_->dependency(i)));
+      }
     }
     printer->Print(
       "return registry;\n");
@@ -372,13 +363,14 @@
 static void GenerateSibling(const string& package_dir,
                             const string& java_package,
                             const DescriptorClass* descriptor,
-                            OutputDirectory* output_directory,
-                            vector<string>* file_list) {
-  string filename = package_dir + descriptor->name() + ".java";
+                            GeneratorContext* context,
+                            vector<string>* file_list,
+                            const string& name_suffix,
+                            void (GeneratorClass::*pfn)(io::Printer* printer)) {
+  string filename = package_dir + descriptor->name() + name_suffix + ".java";
   file_list->push_back(filename);
 
-  scoped_ptr<io::ZeroCopyOutputStream> output(
-    output_directory->Open(filename));
+  scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
   io::Printer printer(output.get(), '$');
 
   printer.Print(
@@ -391,28 +383,36 @@
       "package", java_package);
   }
 
-  GeneratorClass(descriptor).Generate(&printer);
+  GeneratorClass generator(descriptor);
+  (generator.*pfn)(&printer);
 }
 
 void FileGenerator::GenerateSiblings(const string& package_dir,
-                                     OutputDirectory* output_directory,
+                                     GeneratorContext* context,
                                      vector<string>* file_list) {
   if (file_->options().java_multiple_files()) {
     for (int i = 0; i < file_->enum_type_count(); i++) {
       GenerateSibling<EnumGenerator>(package_dir, java_package_,
                                      file_->enum_type(i),
-                                     output_directory, file_list);
+                                     context, file_list, "",
+                                     &EnumGenerator::Generate);
     }
     for (int i = 0; i < file_->message_type_count(); i++) {
       GenerateSibling<MessageGenerator>(package_dir, java_package_,
                                         file_->message_type(i),
-                                        output_directory, file_list);
+                                        context, file_list, "OrBuilder",
+                                        &MessageGenerator::GenerateInterface);
+      GenerateSibling<MessageGenerator>(package_dir, java_package_,
+                                        file_->message_type(i),
+                                        context, file_list, "",
+                                        &MessageGenerator::Generate);
     }
     if (HasGenericServices(file_)) {
       for (int i = 0; i < file_->service_count(); i++) {
         GenerateSibling<ServiceGenerator>(package_dir, java_package_,
                                           file_->service(i),
-                                          output_directory, file_list);
+                                          context, file_list, "",
+                                          &ServiceGenerator::Generate);
       }
     }
   }
diff --git a/src/google/protobuf/compiler/java/java_file.h b/src/google/protobuf/compiler/java/java_file.h
index 9e35d33..5991146 100644
--- a/src/google/protobuf/compiler/java/java_file.h
+++ b/src/google/protobuf/compiler/java/java_file.h
@@ -46,7 +46,7 @@
     class Printer;             // printer.h
   }
   namespace compiler {
-    class OutputDirectory;     // code_generator.h
+    class GeneratorContext;     // code_generator.h
   }
 }
 
@@ -70,12 +70,13 @@
   // files other than the outer file (i.e. one for each message, enum, and
   // service type).
   void GenerateSiblings(const string& package_dir,
-                        OutputDirectory* output_directory,
+                        GeneratorContext* generator_context,
                         vector<string>* file_list);
 
   const string& java_package() { return java_package_; }
   const string& classname()    { return classname_;    }
 
+
  private:
   // Returns whether the dependency should be included in the output file.
   // Always returns true for opensource, but used internally at Google to help
@@ -86,6 +87,7 @@
   string java_package_;
   string classname_;
 
+
   void GenerateEmbeddedDescriptor(io::Printer* printer);
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
diff --git a/src/google/protobuf/compiler/java/java_generator.cc b/src/google/protobuf/compiler/java/java_generator.cc
index 745b55a..e6c79ab 100644
--- a/src/google/protobuf/compiler/java/java_generator.cc
+++ b/src/google/protobuf/compiler/java/java_generator.cc
@@ -51,11 +51,8 @@
 
 bool JavaGenerator::Generate(const FileDescriptor* file,
                              const string& parameter,
-                             OutputDirectory* output_directory,
+                             GeneratorContext* context,
                              string* error) const {
-  vector<pair<string, string> > options;
-  ParseGeneratorParameter(parameter, &options);
-
   // -----------------------------------------------------------------
   // parse generator options
 
@@ -63,6 +60,10 @@
   // per line.
   string output_list_file;
 
+
+  vector<pair<string, string> > options;
+  ParseGeneratorParameter(parameter, &options);
+
   for (int i = 0; i < options.size(); i++) {
     if (options[i].first == "output_list_file") {
       output_list_file = options[i].second;
@@ -72,18 +73,23 @@
     }
   }
 
-
   // -----------------------------------------------------------------
 
 
+  if (file->options().optimize_for() == FileOptions::LITE_RUNTIME &&
+      file->options().java_generate_equals_and_hash()) {
+    *error = "The \"java_generate_equals_and_hash\" option is incompatible "
+             "with \"optimize_for = LITE_RUNTIME\".  You must optimize for "
+             "SPEED or CODE_SIZE if you want to use this option.";
+    return false;
+  }
+
   FileGenerator file_generator(file);
   if (!file_generator.Validate(error)) {
     return false;
   }
 
-  string package_dir =
-    StringReplace(file_generator.java_package(), ".", "/", true);
-  if (!package_dir.empty()) package_dir += "/";
+  string package_dir = JavaPackageToDir(file_generator.java_package());
 
   vector<string> all_files;
 
@@ -94,19 +100,19 @@
 
   // Generate main java file.
   scoped_ptr<io::ZeroCopyOutputStream> output(
-    output_directory->Open(java_filename));
+    context->Open(java_filename));
   io::Printer printer(output.get(), '$');
   file_generator.Generate(&printer);
 
   // Generate sibling files.
-  file_generator.GenerateSiblings(package_dir, output_directory, &all_files);
+  file_generator.GenerateSiblings(package_dir, context, &all_files);
 
   // Generate output list if requested.
   if (!output_list_file.empty()) {
     // Generate output list.  This is just a simple text file placed in a
     // deterministic location which lists the .java files being generated.
     scoped_ptr<io::ZeroCopyOutputStream> srclist_raw_output(
-      output_directory->Open(output_list_file));
+      context->Open(output_list_file));
     io::Printer srclist_printer(srclist_raw_output.get(), '$');
     for (int i = 0; i < all_files.size(); i++) {
       srclist_printer.Print("$filename$\n", "filename", all_files[i]);
diff --git a/src/google/protobuf/compiler/java/java_generator.h b/src/google/protobuf/compiler/java/java_generator.h
index c91c905..888b8d8 100644
--- a/src/google/protobuf/compiler/java/java_generator.h
+++ b/src/google/protobuf/compiler/java/java_generator.h
@@ -57,7 +57,7 @@
   // implements CodeGenerator ----------------------------------------
   bool Generate(const FileDescriptor* file,
                 const string& parameter,
-                OutputDirectory* output_directory,
+                GeneratorContext* context,
                 string* error) const;
 
  private:
diff --git a/src/google/protobuf/compiler/java/java_helpers.cc b/src/google/protobuf/compiler/java/java_helpers.cc
index 7ed0c3c..1b6f165 100644
--- a/src/google/protobuf/compiler/java/java_helpers.cc
+++ b/src/google/protobuf/compiler/java/java_helpers.cc
@@ -134,16 +134,27 @@
 }
 
 string FileJavaPackage(const FileDescriptor* file) {
+  string result;
+
   if (file->options().has_java_package()) {
-    return file->options().java_package();
+    result = file->options().java_package();
   } else {
-    string result = kDefaultPackage;
+    result = kDefaultPackage;
     if (!file->package().empty()) {
       if (!result.empty()) result += '.';
       result += file->package();
     }
-    return result;
   }
+
+
+  return result;
+}
+
+string JavaPackageToDir(string package_name) {
+  string package_dir =
+    StringReplace(package_name, ".", "/", true);
+  if (!package_dir.empty()) package_dir += "/";
+  return package_dir;
 }
 
 string ToJavaName(const string& full_name, const FileDescriptor* file) {
@@ -335,6 +346,132 @@
   return "";
 }
 
+bool IsDefaultValueJavaDefault(const FieldDescriptor* field) {
+  // Switch on CppType since we need to know which default_value_* method
+  // of FieldDescriptor to call.
+  switch (field->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_INT32:
+      return field->default_value_int32() == 0;
+    case FieldDescriptor::CPPTYPE_UINT32:
+      return field->default_value_uint32() == 0;
+    case FieldDescriptor::CPPTYPE_INT64:
+      return field->default_value_int64() == 0L;
+    case FieldDescriptor::CPPTYPE_UINT64:
+      return field->default_value_uint64() == 0L;
+    case FieldDescriptor::CPPTYPE_DOUBLE:
+      return field->default_value_double() == 0.0;
+    case FieldDescriptor::CPPTYPE_FLOAT:
+      return field->default_value_float() == 0.0;
+    case FieldDescriptor::CPPTYPE_BOOL:
+      return field->default_value_bool() == false;
+
+    case FieldDescriptor::CPPTYPE_STRING:
+    case FieldDescriptor::CPPTYPE_ENUM:
+    case FieldDescriptor::CPPTYPE_MESSAGE:
+      return false;
+
+    // No default because we want the compiler to complain if any new
+    // types are added.
+  }
+
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return false;
+}
+
+const char* bit_masks[] = {
+  "0x00000001",
+  "0x00000002",
+  "0x00000004",
+  "0x00000008",
+  "0x00000010",
+  "0x00000020",
+  "0x00000040",
+  "0x00000080",
+
+  "0x00000100",
+  "0x00000200",
+  "0x00000400",
+  "0x00000800",
+  "0x00001000",
+  "0x00002000",
+  "0x00004000",
+  "0x00008000",
+
+  "0x00010000",
+  "0x00020000",
+  "0x00040000",
+  "0x00080000",
+  "0x00100000",
+  "0x00200000",
+  "0x00400000",
+  "0x00800000",
+
+  "0x01000000",
+  "0x02000000",
+  "0x04000000",
+  "0x08000000",
+  "0x10000000",
+  "0x20000000",
+  "0x40000000",
+  "0x80000000",
+};
+
+string GetBitFieldName(int index) {
+  string varName = "bitField";
+  varName += SimpleItoa(index);
+  varName += "_";
+  return varName;
+}
+
+string GetBitFieldNameForBit(int bitIndex) {
+  return GetBitFieldName(bitIndex / 32);
+}
+
+string GenerateGetBit(int bitIndex) {
+  string varName = GetBitFieldNameForBit(bitIndex);
+  int bitInVarIndex = bitIndex % 32;
+
+  string mask = bit_masks[bitInVarIndex];
+  string result = "((" + varName + " & " + mask + ") == " + mask + ")";
+  return result;
+}
+
+string GenerateSetBit(int bitIndex) {
+  string varName = GetBitFieldNameForBit(bitIndex);
+  int bitInVarIndex = bitIndex % 32;
+
+  string mask = bit_masks[bitInVarIndex];
+  string result = varName + " |= " + mask;
+  return result;
+}
+
+string GenerateClearBit(int bitIndex) {
+  string varName = GetBitFieldNameForBit(bitIndex);
+  int bitInVarIndex = bitIndex % 32;
+
+  string mask = bit_masks[bitInVarIndex];
+  string result = varName + " = (" + varName + " & ~" + mask + ")";
+  return result;
+}
+
+string GenerateGetBitFromLocal(int bitIndex) {
+  string varName = "from_" + GetBitFieldNameForBit(bitIndex);
+  int bitInVarIndex = bitIndex % 32;
+
+  string mask = bit_masks[bitInVarIndex];
+  string result = "((" + varName + " & " + mask + ") == " + mask + ")";
+  return result;
+}
+
+string GenerateSetBitToLocal(int bitIndex) {
+  string varName = "to_" + GetBitFieldNameForBit(bitIndex);
+  int bitInVarIndex = bitIndex % 32;
+
+  string mask = bit_masks[bitInVarIndex];
+  string result = varName + " |= " + mask;
+  return result;
+}
+
 }  // namespace java
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/java/java_helpers.h b/src/google/protobuf/compiler/java/java_helpers.h
index 3c8974c..4ae07f1 100644
--- a/src/google/protobuf/compiler/java/java_helpers.h
+++ b/src/google/protobuf/compiler/java/java_helpers.h
@@ -68,6 +68,9 @@
 // Returns the file's Java package name.
 string FileJavaPackage(const FileDescriptor* file);
 
+// Returns output directory for the given package name.
+string JavaPackageToDir(string package_name);
+
 // Converts the given fully-qualified name in the proto namespace to its
 // fully-qualified name in the Java namespace, given that it is in the given
 // file.
@@ -118,6 +121,7 @@
 const char* BoxedPrimitiveTypeName(JavaType type);
 
 string DefaultValue(const FieldDescriptor* field);
+bool IsDefaultValueJavaDefault(const FieldDescriptor* field);
 
 // Does this message class keep track of unknown fields?
 inline bool HasUnknownFields(const Descriptor* descriptor) {
@@ -132,6 +136,11 @@
            FileOptions::CODE_SIZE;
 }
 
+// Does this message have specialized equals() and hashCode() methods?
+inline bool HasEqualsAndHashCode(const Descriptor* descriptor) {
+  return descriptor->file()->options().java_generate_equals_and_hash();
+}
+
 // Does this message class have descriptor and reflection methods?
 inline bool HasDescriptorMethods(const Descriptor* descriptor) {
   return descriptor->file()->options().optimize_for() !=
@@ -146,6 +155,12 @@
            FileOptions::LITE_RUNTIME;
 }
 
+inline bool HasNestedBuilders(const Descriptor* descriptor) {
+  // The proto-lite version doesn't support nested builders.
+  return descriptor->file()->options().optimize_for() !=
+           FileOptions::LITE_RUNTIME;
+}
+
 // Should we generate generic services for this file?
 inline bool HasGenericServices(const FileDescriptor *file) {
   return file->service_count() > 0 &&
@@ -153,6 +168,43 @@
          file->options().java_generic_services();
 }
 
+
+// Methods for shared bitfields.
+
+// Gets the name of the shared bitfield for the given index.
+string GetBitFieldName(int index);
+
+// Gets the name of the shared bitfield for the given bit index.
+// Effectively, GetBitFieldName(bitIndex / 32)
+string GetBitFieldNameForBit(int bitIndex);
+
+// Generates the java code for the expression that returns the boolean value
+// of the bit of the shared bitfields for the given bit index.
+// Example: "((bitField1_ & 0x04) == 0x04)"
+string GenerateGetBit(int bitIndex);
+
+// Generates the java code for the expression that sets the bit of the shared
+// bitfields for the given bit index.
+// Example: "bitField1_ = (bitField1_ | 0x04)"
+string GenerateSetBit(int bitIndex);
+
+// Generates the java code for the expression that clears the bit of the shared
+// bitfields for the given bit index.
+// Example: "bitField1_ = (bitField1_ & ~0x04)"
+string GenerateClearBit(int bitIndex);
+
+// Does the same as GenerateGetBit but operates on the bit field on a local
+// variable. This is used by the builder to copy the value in the builder to
+// the message.
+// Example: "((from_bitField1_ & 0x04) == 0x04)"
+string GenerateGetBitFromLocal(int bitIndex);
+
+// Does the same as GenerateSetBit but operates on the bit field on a local
+// variable. This is used by the builder to copy the value in the builder to
+// the message.
+// Example: "to_bitField1_ = (to_bitField1_ | 0x04)"
+string GenerateSetBitToLocal(int bitIndex);
+
 }  // namespace java
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc
index 8b91193..47ee84c 100644
--- a/src/google/protobuf/compiler/java/java_message.cc
+++ b/src/google/protobuf/compiler/java/java_message.cc
@@ -245,14 +245,54 @@
     MessageGenerator(descriptor_->nested_type(i))
       .GenerateStaticVariableInitializers(printer);
   }
-
-  for (int i = 0; i < descriptor_->extension_count(); i++) {
-    // TODO(kenton):  Reuse ExtensionGenerator objects?
-    ExtensionGenerator(descriptor_->extension(i))
-      .GenerateInitializationCode(printer);
-  }
 }
 
+// ===================================================================
+
+void MessageGenerator::GenerateInterface(io::Printer* printer) {
+
+  if (descriptor_->extension_range_count() > 0) {
+    if (HasDescriptorMethods(descriptor_)) {
+      printer->Print(
+        "public interface $classname$OrBuilder extends\n"
+        "    com.google.protobuf.GeneratedMessage.\n"
+        "        ExtendableMessageOrBuilder<$classname$> {\n",
+        "classname", descriptor_->name());
+    } else {
+      printer->Print(
+        "public interface $classname$OrBuilder extends \n"
+        "     com.google.protobuf.GeneratedMessageLite.\n"
+        "          ExtendableMessageOrBuilder<$classname$> {\n",
+        "classname", descriptor_->name());
+    }
+  } else {
+    if (HasDescriptorMethods(descriptor_)) {
+      printer->Print(
+        "public interface $classname$OrBuilder\n"
+        "    extends com.google.protobuf.MessageOrBuilder {\n",
+        "classname", descriptor_->name());
+    } else {
+      printer->Print(
+        "public interface $classname$OrBuilder\n"
+        "    extends com.google.protobuf.MessageLiteOrBuilder {\n",
+        "classname", descriptor_->name());
+    }
+  }
+
+  printer->Indent();
+    for (int i = 0; i < descriptor_->field_count(); i++) {
+      printer->Print("\n");
+      PrintFieldComment(printer, descriptor_->field(i));
+      field_generators_.get(descriptor_->field(i))
+                       .GenerateInterfaceMembers(printer);
+    }
+  printer->Outdent();
+
+  printer->Print("}\n");
+}
+
+// ===================================================================
+
 void MessageGenerator::Generate(io::Printer* printer) {
   bool is_own_file =
     descriptor_->containing_type() == NULL &&
@@ -263,14 +303,14 @@
       printer->Print(
         "public $static$ final class $classname$ extends\n"
         "    com.google.protobuf.GeneratedMessage.ExtendableMessage<\n"
-        "      $classname$> {\n",
+        "      $classname$> implements $classname$OrBuilder {\n",
         "static", is_own_file ? "" : "static",
         "classname", descriptor_->name());
     } else {
       printer->Print(
         "public $static$ final class $classname$ extends\n"
         "    com.google.protobuf.GeneratedMessageLite.ExtendableMessage<\n"
-        "      $classname$> {\n",
+        "      $classname$> implements $classname$OrBuilder {\n",
         "static", is_own_file ? "" : "static",
         "classname", descriptor_->name());
     }
@@ -278,13 +318,15 @@
     if (HasDescriptorMethods(descriptor_)) {
       printer->Print(
         "public $static$ final class $classname$ extends\n"
-        "    com.google.protobuf.GeneratedMessage {\n",
+        "    com.google.protobuf.GeneratedMessage\n"
+        "    implements $classname$OrBuilder {\n",
         "static", is_own_file ? "" : "static",
         "classname", descriptor_->name());
     } else {
       printer->Print(
         "public $static$ final class $classname$ extends\n"
-        "    com.google.protobuf.GeneratedMessageLite {\n",
+        "    com.google.protobuf.GeneratedMessageLite\n"
+        "    implements $classname$OrBuilder {\n",
         "static", is_own_file ? "" : "static",
         "classname", descriptor_->name());
     }
@@ -292,8 +334,8 @@
   printer->Indent();
   printer->Print(
     "// Use $classname$.newBuilder() to construct.\n"
-    "private $classname$() {\n"
-    "  initFields();\n"
+    "private $classname$(Builder builder) {\n"
+    "  super(builder);\n"
     "}\n"
     // Used when constructing the default instance, which cannot be initialized
     // immediately because it may cyclically refer to other default instances.
@@ -310,33 +352,29 @@
     "\n",
     "classname", descriptor_->name());
 
-  if (HasDescriptorMethods(descriptor_)) {
-    printer->Print(
-      "public static final com.google.protobuf.Descriptors.Descriptor\n"
-      "    getDescriptor() {\n"
-      "  return $fileclass$.internal_$identifier$_descriptor;\n"
-      "}\n"
-      "\n"
-      "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
-      "    internalGetFieldAccessorTable() {\n"
-      "  return $fileclass$.internal_$identifier$_fieldAccessorTable;\n"
-      "}\n"
-      "\n",
-      "fileclass", ClassName(descriptor_->file()),
-      "identifier", UniqueFileScopeIdentifier(descriptor_));
-  }
+  GenerateDescriptorMethods(printer);
 
-  // Nested types and extensions
+  // Nested types
   for (int i = 0; i < descriptor_->enum_type_count(); i++) {
     EnumGenerator(descriptor_->enum_type(i)).Generate(printer);
   }
 
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
-    MessageGenerator(descriptor_->nested_type(i)).Generate(printer);
+    MessageGenerator messageGenerator(descriptor_->nested_type(i));
+    messageGenerator.GenerateInterface(printer);
+    messageGenerator.Generate(printer);
   }
 
-  for (int i = 0; i < descriptor_->extension_count(); i++) {
-    ExtensionGenerator(descriptor_->extension(i)).Generate(printer);
+  // Integers for bit fields.
+  int totalBits = 0;
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    totalBits += field_generators_.get(descriptor_->field(i))
+        .GetNumBitsForMessage();
+  }
+  int totalInts = (totalBits + 31) / 32;
+  for (int i = 0; i < totalInts; i++) {
+    printer->Print("private int $bit_field_name$;\n",
+      "bit_field_name", GetBitFieldName(i));
   }
 
   // Fields
@@ -361,35 +399,42 @@
   printer->Print("}\n");
 
   if (HasGeneratedMethods(descriptor_)) {
-    GenerateIsInitialized(printer);
+    GenerateIsInitialized(printer, MEMOIZE);
     GenerateMessageSerializationMethods(printer);
   }
 
+  if (HasEqualsAndHashCode(descriptor_)) {
+    GenerateEqualsAndHashCode(printer);
+  }
+
   GenerateParseFromMethods(printer);
   GenerateBuilder(printer);
 
-  // Force initialization of outer class.  Otherwise, nested extensions may
-  // not be initialized.  Also carefully initialize the default instance in
-  // such a way that it doesn't conflict with other initialization.
+  // Carefully initialize the default instance in such a way that it doesn't
+  // conflict with other initialization.
   printer->Print(
     "\n"
     "static {\n"
     "  defaultInstance = new $classname$(true);\n"
-    "  $file$.internalForceInit();\n"
     "  defaultInstance.initFields();\n"
-    "}\n",
-    "file", ClassName(descriptor_->file()),
-    "classname", descriptor_->name());
-
-  printer->Print(
+    "}\n"
     "\n"
     "// @@protoc_insertion_point(class_scope:$full_name$)\n",
+    "classname", descriptor_->name(),
     "full_name", descriptor_->full_name());
 
+  // Extensions must be declared after the defaultInstance is initialized
+  // because the defaultInstance is used by the extension to lazily retrieve
+  // the outer class's FileDescriptor.
+  for (int i = 0; i < descriptor_->extension_count(); i++) {
+    ExtensionGenerator(descriptor_->extension(i)).Generate(printer);
+  }
+
   printer->Outdent();
   printer->Print("}\n\n");
 }
 
+
 // ===================================================================
 
 void MessageGenerator::
@@ -502,6 +547,13 @@
     "  return size;\n"
     "}\n"
     "\n");
+
+  printer->Print(
+    "@java.lang.Override\n"
+    "protected Object writeReplace() throws java.io.ObjectStreamException {\n"
+    "  return super.writeReplace();\n"
+    "}\n"
+    "\n");
 }
 
 void MessageGenerator::
@@ -605,42 +657,68 @@
     "\n",
     "classname", ClassName(descriptor_));
 
+  if (HasNestedBuilders(descriptor_)) {
+     printer->Print(
+      "@java.lang.Override\n"
+      "protected Builder newBuilderForType(\n"
+      "    com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n"
+      "  Builder builder = new Builder(parent);\n"
+      "  return builder;\n"
+      "}\n");
+  }
+
   if (descriptor_->extension_range_count() > 0) {
     if (HasDescriptorMethods(descriptor_)) {
       printer->Print(
         "public static final class Builder extends\n"
         "    com.google.protobuf.GeneratedMessage.ExtendableBuilder<\n"
-        "      $classname$, Builder> {\n",
+        "      $classname$, Builder> implements $classname$OrBuilder {\n",
         "classname", ClassName(descriptor_));
     } else {
       printer->Print(
         "public static final class Builder extends\n"
         "    com.google.protobuf.GeneratedMessageLite.ExtendableBuilder<\n"
-        "      $classname$, Builder> {\n",
+        "      $classname$, Builder> implements $classname$OrBuilder {\n",
         "classname", ClassName(descriptor_));
     }
   } else {
     if (HasDescriptorMethods(descriptor_)) {
       printer->Print(
         "public static final class Builder extends\n"
-        "    com.google.protobuf.GeneratedMessage.Builder<Builder> {\n",
+        "    com.google.protobuf.GeneratedMessage.Builder<Builder>\n"
+         "   implements $classname$OrBuilder {\n",
         "classname", ClassName(descriptor_));
     } else {
       printer->Print(
         "public static final class Builder extends\n"
         "    com.google.protobuf.GeneratedMessageLite.Builder<\n"
-        "      $classname$, Builder> {\n",
+        "      $classname$, Builder>\n"
+        "    implements $classname$OrBuilder {\n",
         "classname", ClassName(descriptor_));
     }
   }
   printer->Indent();
 
+  GenerateDescriptorMethods(printer);
   GenerateCommonBuilderMethods(printer);
 
   if (HasGeneratedMethods(descriptor_)) {
+    GenerateIsInitialized(printer, DONT_MEMOIZE);
     GenerateBuilderParsingMethods(printer);
   }
 
+  // Integers for bit fields.
+  int totalBits = 0;
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    totalBits += field_generators_.get(descriptor_->field(i))
+        .GetNumBitsForBuilder();
+  }
+  int totalInts = (totalBits + 31) / 32;
+  for (int i = 0; i < totalInts; i++) {
+    printer->Print("private int $bit_field_name$;\n",
+      "bit_field_name", GetBitFieldName(i));
+  }
+
   for (int i = 0; i < descriptor_->field_count(); i++) {
     printer->Print("\n");
     PrintFieldComment(printer, descriptor_->field(i));
@@ -657,36 +735,92 @@
   printer->Print("}\n");
 }
 
+void MessageGenerator::GenerateDescriptorMethods(io::Printer* printer) {
+  if (HasDescriptorMethods(descriptor_)) {
+    printer->Print(
+      "public static final com.google.protobuf.Descriptors.Descriptor\n"
+      "    getDescriptor() {\n"
+      "  return $fileclass$.internal_$identifier$_descriptor;\n"
+      "}\n"
+      "\n"
+      "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
+      "    internalGetFieldAccessorTable() {\n"
+      "  return $fileclass$.internal_$identifier$_fieldAccessorTable;\n"
+      "}\n"
+      "\n",
+      "fileclass", ClassName(descriptor_->file()),
+      "identifier", UniqueFileScopeIdentifier(descriptor_));
+  }
+}
+
 // ===================================================================
 
 void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
   printer->Print(
-    "private $classname$ result;\n"
-    "\n"
     "// Construct using $classname$.newBuilder()\n"
-    "private Builder() {}\n"
-    "\n"
-    "private static Builder create() {\n"
-    "  Builder builder = new Builder();\n"
-    "  builder.result = new $classname$();\n"
-    "  return builder;\n"
+    "private Builder() {\n"
+    "  maybeForceBuilderInitialization();\n"
     "}\n"
-    "\n"
-    "protected $classname$ internalGetResult() {\n"
-    "  return result;\n"
+    "\n",
+    "classname", ClassName(descriptor_));
+
+  if (HasDescriptorMethods(descriptor_)) {
+    printer->Print(
+      "private Builder(BuilderParent parent) {\n"
+      "  super(parent);\n"
+      "  maybeForceBuilderInitialization();\n"
+      "}\n",
+      "classname", ClassName(descriptor_));
+  }
+
+
+  if (HasNestedBuilders(descriptor_)) {
+    printer->Print(
+      "private void maybeForceBuilderInitialization() {\n"
+      "  if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {\n");
+
+    printer->Indent();
+    printer->Indent();
+    for (int i = 0; i < descriptor_->field_count(); i++) {
+      field_generators_.get(descriptor_->field(i))
+          .GenerateFieldBuilderInitializationCode(printer);
+    }
+    printer->Outdent();
+    printer->Outdent();
+
+    printer->Print(
+      "  }\n"
+      "}\n");
+  } else {
+    printer->Print(
+      "private void maybeForceBuilderInitialization() {\n"
+      "}\n");
+  }
+
+  printer->Print(
+    "private static Builder create() {\n"
+    "  return new Builder();\n"
     "}\n"
     "\n"
     "public Builder clear() {\n"
-    "  if (result == null) {\n"
-    "    throw new IllegalStateException(\n"
-    "      \"Cannot call clear() after build().\");\n"
-    "  }\n"
-    "  result = new $classname$();\n"
+    "  super.clear();\n",
+    "classname", ClassName(descriptor_));
+
+  printer->Indent();
+
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    field_generators_.get(descriptor_->field(i))
+        .GenerateBuilderClearCode(printer);
+  }
+
+  printer->Outdent();
+
+  printer->Print(
     "  return this;\n"
     "}\n"
     "\n"
     "public Builder clone() {\n"
-    "  return create().mergeFrom(result);\n"
+    "  return create().mergeFrom(buildPartial());\n"
     "}\n"
     "\n",
     "classname", ClassName(descriptor_));
@@ -703,49 +837,78 @@
     "public $classname$ getDefaultInstanceForType() {\n"
     "  return $classname$.getDefaultInstance();\n"
     "}\n"
-    "\n"
-    "public boolean isInitialized() {\n"
-    "  return result.isInitialized();\n"
-    "}\n",
+    "\n",
     "classname", ClassName(descriptor_));
 
   // -----------------------------------------------------------------
 
   printer->Print(
     "public $classname$ build() {\n"
-    // If result == null, we'll throw an appropriate exception later.
-    "  if (result != null && !isInitialized()) {\n"
+    "  $classname$ result = buildPartial();\n"
+    "  if (!result.isInitialized()) {\n"
     "    throw newUninitializedMessageException(result);\n"
     "  }\n"
-    "  return buildPartial();\n"
+    "  return result;\n"
     "}\n"
     "\n"
     "private $classname$ buildParsed()\n"
     "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
-    "  if (!isInitialized()) {\n"
+    "  $classname$ result = buildPartial();\n"
+    "  if (!result.isInitialized()) {\n"
     "    throw newUninitializedMessageException(\n"
     "      result).asInvalidProtocolBufferException();\n"
     "  }\n"
-    "  return buildPartial();\n"
+    "  return result;\n"
     "}\n"
     "\n"
     "public $classname$ buildPartial() {\n"
-    "  if (result == null) {\n"
-    "    throw new IllegalStateException(\n"
-    "      \"build() has already been called on this Builder.\");\n"
-    "  }\n",
+    "  $classname$ result = new $classname$(this);\n",
     "classname", ClassName(descriptor_));
+
   printer->Indent();
 
+  // Local vars for from and to bit fields to avoid accessing the builder and
+  // message over and over for these fields. Seems to provide a slight
+  // perforamance improvement in micro benchmark and this is also what proto1
+  // code does.
+  int totalBuilderBits = 0;
+  int totalMessageBits = 0;
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldGenerator& field = field_generators_.get(descriptor_->field(i));
+    totalBuilderBits += field.GetNumBitsForBuilder();
+    totalMessageBits += field.GetNumBitsForMessage();
+  }
+  int totalBuilderInts = (totalBuilderBits + 31) / 32;
+  int totalMessageInts = (totalMessageBits + 31) / 32;
+  for (int i = 0; i < totalBuilderInts; i++) {
+    printer->Print("int from_$bit_field_name$ = $bit_field_name$;\n",
+      "bit_field_name", GetBitFieldName(i));
+  }
+  for (int i = 0; i < totalMessageInts; i++) {
+    printer->Print("int to_$bit_field_name$ = 0;\n",
+      "bit_field_name", GetBitFieldName(i));
+  }
+
+  // Output generation code for each field.
   for (int i = 0; i < descriptor_->field_count(); i++) {
     field_generators_.get(descriptor_->field(i)).GenerateBuildingCode(printer);
   }
 
+  // Copy the bit field results to the generated message
+  for (int i = 0; i < totalMessageInts; i++) {
+    printer->Print("result.$bit_field_name$ = to_$bit_field_name$;\n",
+      "bit_field_name", GetBitFieldName(i));
+  }
+
   printer->Outdent();
+
+  if (HasDescriptorMethods(descriptor_)) {
+    printer->Print(
+    "  onBuilt();\n");
+  }
+
   printer->Print(
-    "  $classname$ returnMe = result;\n"
-    "  result = null;\n"
-    "  return returnMe;\n"
+    "  return result;\n"
     "}\n"
     "\n",
     "classname", ClassName(descriptor_));
@@ -834,25 +997,31 @@
     printer->Print(
       "case 0:\n"          // zero signals EOF / limit reached
       "  this.setUnknownFields(unknownFields.build());\n"
+      "  $on_changed$\n"
       "  return this;\n"
       "default: {\n"
       "  if (!parseUnknownField(input, unknownFields,\n"
       "                         extensionRegistry, tag)) {\n"
       "    this.setUnknownFields(unknownFields.build());\n"
+      "    $on_changed$\n"
       "    return this;\n"   // it's an endgroup tag
       "  }\n"
       "  break;\n"
-      "}\n");
+      "}\n",
+      "on_changed", HasDescriptorMethods(descriptor_) ? "onChanged();" : "");
   } else {
     printer->Print(
       "case 0:\n"          // zero signals EOF / limit reached
+      "  $on_changed$\n"
       "  return this;\n"
       "default: {\n"
       "  if (!parseUnknownField(input, extensionRegistry, tag)) {\n"
+      "    $on_changed$\n"
       "    return this;\n"   // it's an endgroup tag
       "  }\n"
       "  break;\n"
-      "}\n");
+      "}\n",
+      "on_changed", HasDescriptorMethods(descriptor_) ? "onChanged();" : "");
   }
 
   for (int i = 0; i < descriptor_->field_count(); i++) {
@@ -898,16 +1067,33 @@
     "    }\n"     // switch (tag)
     "  }\n"       // while (true)
     "}\n"
+
     "\n");
 }
 
 // ===================================================================
 
-void MessageGenerator::GenerateIsInitialized(io::Printer* printer) {
+void MessageGenerator::GenerateIsInitialized(
+    io::Printer* printer, UseMemoization useMemoization) {
+  bool memoization = useMemoization == MEMOIZE;
+  if (memoization) {
+    // Memoizes whether the protocol buffer is fully initialized (has all
+    // required fields). -1 means not yet computed. 0 means false and 1 means
+    // true.
+    printer->Print(
+      "private byte memoizedIsInitialized = -1;\n");
+  }
   printer->Print(
     "public final boolean isInitialized() {\n");
   printer->Indent();
 
+  if (memoization) {
+    printer->Print(
+      "byte isInitialized = memoizedIsInitialized;\n"
+      "if (isInitialized != -1) return isInitialized == 1;\n"
+      "\n");
+  }
+
   // Check that all required fields in this message are set.
   // TODO(kenton):  We can optimize this when we switch to putting all the
   //   "has" fields into a single bitfield.
@@ -916,8 +1102,12 @@
 
     if (field->is_required()) {
       printer->Print(
-        "if (!has$name$) return false;\n",
-        "name", UnderscoresToCapitalizedCamelCase(field));
+        "if (!has$name$()) {\n"
+        "  $memoize$\n"
+        "  return false;\n"
+        "}\n",
+        "name", UnderscoresToCapitalizedCamelCase(field),
+        "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
     }
   }
 
@@ -929,25 +1119,37 @@
       switch (field->label()) {
         case FieldDescriptor::LABEL_REQUIRED:
           printer->Print(
-            "if (!get$name$().isInitialized()) return false;\n",
+            "if (!get$name$().isInitialized()) {\n"
+             "  $memoize$\n"
+             "  return false;\n"
+             "}\n",
             "type", ClassName(field->message_type()),
-            "name", UnderscoresToCapitalizedCamelCase(field));
+            "name", UnderscoresToCapitalizedCamelCase(field),
+            "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
           break;
         case FieldDescriptor::LABEL_OPTIONAL:
           printer->Print(
             "if (has$name$()) {\n"
-            "  if (!get$name$().isInitialized()) return false;\n"
+            "  if (!get$name$().isInitialized()) {\n"
+            "    $memoize$\n"
+            "    return false;\n"
+            "  }\n"
             "}\n",
             "type", ClassName(field->message_type()),
-            "name", UnderscoresToCapitalizedCamelCase(field));
+            "name", UnderscoresToCapitalizedCamelCase(field),
+            "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
           break;
         case FieldDescriptor::LABEL_REPEATED:
           printer->Print(
-            "for ($type$ element : get$name$List()) {\n"
-            "  if (!element.isInitialized()) return false;\n"
+            "for (int i = 0; i < get$name$Count(); i++) {\n"
+            "  if (!get$name$(i).isInitialized()) {\n"
+            "    $memoize$\n"
+            "    return false;\n"
+            "  }\n"
             "}\n",
             "type", ClassName(field->message_type()),
-            "name", UnderscoresToCapitalizedCamelCase(field));
+            "name", UnderscoresToCapitalizedCamelCase(field),
+            "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
           break;
       }
     }
@@ -955,10 +1157,20 @@
 
   if (descriptor_->extension_range_count() > 0) {
     printer->Print(
-      "if (!extensionsAreInitialized()) return false;\n");
+      "if (!extensionsAreInitialized()) {\n"
+      "  $memoize$\n"
+      "  return false;\n"
+      "}\n",
+      "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
   }
 
   printer->Outdent();
+
+  if (memoization) {
+    printer->Print(
+      "  memoizedIsInitialized = 1;\n");
+  }
+
   printer->Print(
     "  return true;\n"
     "}\n"
@@ -967,6 +1179,94 @@
 
 // ===================================================================
 
+void MessageGenerator::GenerateEqualsAndHashCode(io::Printer* printer) {
+  printer->Print(
+    "@java.lang.Override\n"
+    "public boolean equals(final Object obj) {\n");
+  printer->Indent();
+  printer->Print(
+    "if (obj == this) {\n"
+    " return true;\n"
+    "}\n"
+    "if (!(obj instanceof $classname$)) {\n"
+    "  return super.equals(obj);\n"
+    "}\n"
+    "$classname$ other = ($classname$) obj;\n"
+    "\n",
+    "classname", ClassName(descriptor_));
+
+  printer->Print("boolean result = true;\n");
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+    if (!field->is_repeated()) {
+      printer->Print(
+        "result = result && (has$name$() == other.has$name$());\n"
+        "if (has$name$()) {\n",
+        "name", UnderscoresToCapitalizedCamelCase(field));
+      printer->Indent();
+    }
+    field_generators_.get(field).GenerateEqualsCode(printer);
+    if (!field->is_repeated()) {
+      printer->Outdent();
+      printer->Print(
+        "}\n");
+    }
+  }
+  if (HasDescriptorMethods(descriptor_)) {
+    printer->Print(
+      "result = result &&\n"
+      "    getUnknownFields().equals(other.getUnknownFields());\n");
+    if (descriptor_->extension_range_count() > 0) {
+      printer->Print(
+        "result = result &&\n"
+        "    getExtensionFields().equals(other.getExtensionFields());\n");
+    }
+  }
+  printer->Print(
+    "return result;\n");
+  printer->Outdent();
+  printer->Print(
+    "}\n"
+    "\n");
+
+  printer->Print(
+    "@java.lang.Override\n"
+    "public int hashCode() {\n");
+  printer->Indent();
+  printer->Print(
+    "int hash = 41;\n"
+    "hash = (19 * hash) + getDescriptorForType().hashCode();\n");
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+    if (!field->is_repeated()) {
+      printer->Print(
+        "if (has$name$()) {\n",
+        "name", UnderscoresToCapitalizedCamelCase(field));
+      printer->Indent();
+    }
+    field_generators_.get(field).GenerateHashCode(printer);
+    if (!field->is_repeated()) {
+      printer->Outdent();
+      printer->Print("}\n");
+    }
+  }
+  if (HasDescriptorMethods(descriptor_)) {
+    if (descriptor_->extension_range_count() > 0) {
+      printer->Print(
+        "hash = hashFields(hash, getExtensionFields());\n");
+    }
+  }
+  printer->Print(
+    "hash = (29 * hash) + getUnknownFields().hashCode();\n"
+    "return hash;\n");
+  printer->Outdent();
+  printer->Print(
+    "}\n"
+    "\n");
+}
+
+// ===================================================================
+
 void MessageGenerator::GenerateExtensionRegistrationCode(io::Printer* printer) {
   for (int i = 0; i < descriptor_->extension_count(); i++) {
     ExtensionGenerator(descriptor_->extension(i))
diff --git a/src/google/protobuf/compiler/java/java_message.h b/src/google/protobuf/compiler/java/java_message.h
index 50ffae0..4c6fbbe 100644
--- a/src/google/protobuf/compiler/java/java_message.h
+++ b/src/google/protobuf/compiler/java/java_message.h
@@ -67,11 +67,19 @@
   // Generate the class itself.
   void Generate(io::Printer* printer);
 
+  // Generates the base interface that both the class and its builder implement
+  void GenerateInterface(io::Printer* printer);
+
   // Generate code to register all contained extensions with an
   // ExtensionRegistry.
   void GenerateExtensionRegistrationCode(io::Printer* printer);
 
  private:
+  enum UseMemoization {
+    MEMOIZE,
+    DONT_MEMOIZE
+  };
+
   void GenerateMessageSerializationMethods(io::Printer* printer);
   void GenerateParseFromMethods(io::Printer* printer);
   void GenerateSerializeOneField(io::Printer* printer,
@@ -81,8 +89,11 @@
 
   void GenerateBuilder(io::Printer* printer);
   void GenerateCommonBuilderMethods(io::Printer* printer);
+  void GenerateDescriptorMethods(io::Printer* printer);
   void GenerateBuilderParsingMethods(io::Printer* printer);
-  void GenerateIsInitialized(io::Printer* printer);
+  void GenerateIsInitialized(io::Printer* printer,
+      UseMemoization useMemoization);
+  void GenerateEqualsAndHashCode(io::Printer* printer);
 
   const Descriptor* descriptor_;
   FieldGeneratorMap field_generators_;
diff --git a/src/google/protobuf/compiler/java/java_message_field.cc b/src/google/protobuf/compiler/java/java_message_field.cc
index 71edc02..251945a 100644
--- a/src/google/protobuf/compiler/java/java_message_field.cc
+++ b/src/google/protobuf/compiler/java/java_message_field.cc
@@ -51,16 +51,43 @@
 // TODO(kenton):  Factor out a "SetCommonFieldVariables()" to get rid of
 //   repeat code between this and the other field types.
 void SetMessageVariables(const FieldDescriptor* descriptor,
+                         int messageBitIndex,
+                         int builderBitIndex,
                          map<string, string>* variables) {
   (*variables)["name"] =
     UnderscoresToCamelCase(descriptor);
   (*variables)["capitalized_name"] =
     UnderscoresToCapitalizedCamelCase(descriptor);
+  (*variables)["constant_name"] = FieldConstantName(descriptor);
   (*variables)["number"] = SimpleItoa(descriptor->number());
   (*variables)["type"] = ClassName(descriptor->message_type());
   (*variables)["group_or_message"] =
     (GetType(descriptor) == FieldDescriptor::TYPE_GROUP) ?
     "Group" : "Message";
+  // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
+  // by the proto compiler
+  (*variables)["deprecation"] = descriptor->options().deprecated()
+      ? "@java.lang.Deprecated " : "";
+  (*variables)["on_changed"] =
+      HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
+
+  // For singular messages and builders, one bit is used for the hasField bit.
+  (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+
+  (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
+  (*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex);
+  (*variables)["clear_has_field_bit_builder"] =
+      GenerateClearBit(builderBitIndex);
+
+  // For repated builders, one bit is used for whether the array is immutable.
+  (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
+  (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
+  (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
+
+  (*variables)["get_has_field_bit_from_local"] =
+      GenerateGetBitFromLocal(builderBitIndex);
+  (*variables)["set_has_field_bit_to_local"] =
+      GenerateSetBitToLocal(messageBitIndex);
 }
 
 }  // namespace
@@ -68,68 +95,244 @@
 // ===================================================================
 
 MessageFieldGenerator::
-MessageFieldGenerator(const FieldDescriptor* descriptor)
-  : descriptor_(descriptor) {
-  SetMessageVariables(descriptor, &variables_);
+MessageFieldGenerator(const FieldDescriptor* descriptor,
+                      int messageBitIndex,
+                      int builderBitIndex)
+  : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+    builderBitIndex_(builderBitIndex) {
+  SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
+                      &variables_);
 }
 
 MessageFieldGenerator::~MessageFieldGenerator() {}
 
+int MessageFieldGenerator::GetNumBitsForMessage() const {
+  return 1;
+}
+
+int MessageFieldGenerator::GetNumBitsForBuilder() const {
+  return 1;
+}
+
+void MessageFieldGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+  // TODO(jonp): In the future, consider having a method specific to the
+  // interface so that builders can choose dynamically to either return a
+  // message or a nested builder, so that asking for the interface doesn't
+  // cause a message to ever be built.
+  printer->Print(variables_,
+    "$deprecation$boolean has$capitalized_name$();\n"
+    "$deprecation$$type$ get$capitalized_name$();\n");
+
+  if (HasNestedBuilders(descriptor_->containing_type())) {
+    printer->Print(variables_,
+      "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder();\n");
+  }
+}
+
 void MessageFieldGenerator::
 GenerateMembers(io::Printer* printer) const {
   printer->Print(variables_,
-    "private boolean has$capitalized_name$;\n"
     "private $type$ $name$_;\n"
-    "public boolean has$capitalized_name$() { return has$capitalized_name$; }\n"
-    "public $type$ get$capitalized_name$() { return $name$_; }\n");
+    "$deprecation$public boolean has$capitalized_name$() {\n"
+    "  return $get_has_field_bit_message$;\n"
+    "}\n"
+    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "  return $name$_;\n"
+    "}\n");
+
+  if (HasNestedBuilders(descriptor_->containing_type())) {
+    printer->Print(variables_,
+      "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
+      "  return $name$_;\n"
+      "}\n");
+  }
+}
+
+void MessageFieldGenerator::PrintNestedBuilderCondition(
+    io::Printer* printer,
+    const char* regular_case,
+    const char* nested_builder_case) const {
+  if (HasNestedBuilders(descriptor_->containing_type())) {
+     printer->Print(variables_, "if ($name$Builder_ == null) {\n");
+     printer->Indent();
+     printer->Print(variables_, regular_case);
+     printer->Outdent();
+     printer->Print("} else {\n");
+     printer->Indent();
+     printer->Print(variables_, nested_builder_case);
+     printer->Outdent();
+     printer->Print("}\n");
+   } else {
+     printer->Print(variables_, regular_case);
+   }
+}
+
+void MessageFieldGenerator::PrintNestedBuilderFunction(
+    io::Printer* printer,
+    const char* method_prototype,
+    const char* regular_case,
+    const char* nested_builder_case,
+    const char* trailing_code) const {
+  printer->Print(variables_, method_prototype);
+  printer->Print(" {\n");
+  printer->Indent();
+  PrintNestedBuilderCondition(printer, regular_case, nested_builder_case);
+  if (trailing_code != NULL) {
+    printer->Print(variables_, trailing_code);
+  }
+  printer->Outdent();
+  printer->Print("}\n");
 }
 
 void MessageFieldGenerator::
 GenerateBuilderMembers(io::Printer* printer) const {
+  // When using nested-builders, the code initially works just like the
+  // non-nested builder case. It only creates a nested builder lazily on
+  // demand and then forever delegates to it after creation.
+
   printer->Print(variables_,
-    "public boolean has$capitalized_name$() {\n"
-    "  return result.has$capitalized_name$();\n"
-    "}\n"
-    "public $type$ get$capitalized_name$() {\n"
-    "  return result.get$capitalized_name$();\n"
-    "}\n"
-    "public Builder set$capitalized_name$($type$ value) {\n"
-    "  if (value == null) {\n"
-    "    throw new NullPointerException();\n"
-    "  }\n"
-    "  result.has$capitalized_name$ = true;\n"
-    "  result.$name$_ = value;\n"
-    "  return this;\n"
-    "}\n"
-    "public Builder set$capitalized_name$($type$.Builder builderForValue) {\n"
-    "  result.has$capitalized_name$ = true;\n"
-    "  result.$name$_ = builderForValue.build();\n"
-    "  return this;\n"
-    "}\n"
-    "public Builder merge$capitalized_name$($type$ value) {\n"
-    "  if (result.has$capitalized_name$() &&\n"
-    "      result.$name$_ != $type$.getDefaultInstance()) {\n"
-    "    result.$name$_ =\n"
-    "      $type$.newBuilder(result.$name$_).mergeFrom(value).buildPartial();\n"
-    "  } else {\n"
-    "    result.$name$_ = value;\n"
-    "  }\n"
-    "  result.has$capitalized_name$ = true;\n"
-    "  return this;\n"
-    "}\n"
-    "public Builder clear$capitalized_name$() {\n"
-    "  result.has$capitalized_name$ = false;\n"
-    "  result.$name$_ = $type$.getDefaultInstance();\n"
-    "  return this;\n"
+    // Used when the builder is null.
+    "private $type$ $name$_ = $type$.getDefaultInstance();\n");
+
+  if (HasNestedBuilders(descriptor_->containing_type())) {
+    printer->Print(variables_,
+      // If this builder is non-null, it is used and the other fields are
+      // ignored.
+      "private com.google.protobuf.SingleFieldBuilder<\n"
+      "    $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;"
+      "\n");
+  }
+
+  // The comments above the methods below are based on a hypothetical
+  // field of type "Field" called "Field".
+
+  // boolean hasField()
+  printer->Print(variables_,
+    "$deprecation$public boolean has$capitalized_name$() {\n"
+    "  return $get_has_field_bit_builder$;\n"
     "}\n");
+
+  // Field getField()
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public $type$ get$capitalized_name$()",
+
+    "return $name$_;\n",
+
+    "return $name$Builder_.getMessage();\n",
+
+    NULL);
+
+  // Field.Builder setField(Field value)
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder set$capitalized_name$($type$ value)",
+
+    "if (value == null) {\n"
+    "  throw new NullPointerException();\n"
+    "}\n"
+    "$name$_ = value;\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.setMessage(value);\n",
+
+    "$set_has_field_bit_builder$;\n"
+    "return this;\n");
+
+  // Field.Builder setField(Field.Builder builderForValue)
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder set$capitalized_name$(\n"
+    "    $type$.Builder builderForValue)",
+
+    "$name$_ = builderForValue.build();\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.setMessage(builderForValue.build());\n",
+
+    "$set_has_field_bit_builder$;\n"
+    "return this;\n");
+
+  // Field.Builder mergeField(Field value)
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder merge$capitalized_name$($type$ value)",
+
+    "if ($get_has_field_bit_builder$ &&\n"
+    "    $name$_ != $type$.getDefaultInstance()) {\n"
+    "  $name$_ =\n"
+    "    $type$.newBuilder($name$_).mergeFrom(value).buildPartial();\n"
+    "} else {\n"
+    "  $name$_ = value;\n"
+    "}\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.mergeFrom(value);\n",
+
+    "$set_has_field_bit_builder$;\n"
+    "return this;\n");
+
+  // Field.Builder clearField()
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder clear$capitalized_name$()",
+
+    "$name$_ = $type$.getDefaultInstance();\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.clear();\n",
+
+    "$clear_has_field_bit_builder$;\n"
+    "return this;\n");
+
+  if (HasNestedBuilders(descriptor_->containing_type())) {
+    printer->Print(variables_,
+      "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n"
+      "  $set_has_field_bit_builder$;\n"
+      "  $on_changed$\n"
+      "  return get$capitalized_name$FieldBuilder().getBuilder();\n"
+      "}\n"
+      "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
+      "  if ($name$Builder_ != null) {\n"
+      "    return $name$Builder_.getMessageOrBuilder();\n"
+      "  } else {\n"
+      "    return $name$_;\n"
+      "  }\n"
+      "}\n"
+      "private com.google.protobuf.SingleFieldBuilder<\n"
+      "    $type$, $type$.Builder, $type$OrBuilder> \n"
+      "    get$capitalized_name$FieldBuilder() {\n"
+      "  if ($name$Builder_ == null) {\n"
+      "    $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n"
+      "        $type$, $type$.Builder, $type$OrBuilder>(\n"
+      "            $name$_,\n"
+      "            getParentForChildren(),\n"
+      "            isClean());\n"
+      "    $name$_ = null;\n"
+      "  }\n"
+      "  return $name$Builder_;\n"
+      "}\n");
+  }
 }
 
 void MessageFieldGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
+  printer->Print(variables_,
+    "get$capitalized_name$FieldBuilder();\n");
+}
+
+
+void MessageFieldGenerator::
 GenerateInitializationCode(io::Printer* printer) const {
   printer->Print(variables_, "$name$_ = $type$.getDefaultInstance();\n");
 }
 
 void MessageFieldGenerator::
+GenerateBuilderClearCode(io::Printer* printer) const {
+  PrintNestedBuilderCondition(printer,
+    "$name$_ = $type$.getDefaultInstance();\n",
+
+    "$name$Builder_.clear();\n");
+  printer->Print(variables_, "$clear_has_field_bit_builder$;\n");
+}
+
+void MessageFieldGenerator::
 GenerateMergingCode(io::Printer* printer) const {
   printer->Print(variables_,
     "if (other.has$capitalized_name$()) {\n"
@@ -139,7 +342,16 @@
 
 void MessageFieldGenerator::
 GenerateBuildingCode(io::Printer* printer) const {
-  // Nothing to do for singular fields.
+
+  printer->Print(variables_,
+      "if ($get_has_field_bit_from_local$) {\n"
+      "  $set_has_field_bit_to_local$;\n"
+      "}\n");
+
+  PrintNestedBuilderCondition(printer,
+    "result.$name$_ = $name$_;\n",
+
+    "result.$name$_ = $name$Builder_.build();\n");
 }
 
 void MessageFieldGenerator::
@@ -165,20 +377,34 @@
 void MessageFieldGenerator::
 GenerateSerializationCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "if (has$capitalized_name$()) {\n"
-    "  output.write$group_or_message$($number$, get$capitalized_name$());\n"
+    "if ($get_has_field_bit_message$) {\n"
+    "  output.write$group_or_message$($number$, $name$_);\n"
     "}\n");
 }
 
 void MessageFieldGenerator::
 GenerateSerializedSizeCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "if (has$capitalized_name$()) {\n"
+    "if ($get_has_field_bit_message$) {\n"
     "  size += com.google.protobuf.CodedOutputStream\n"
-    "    .compute$group_or_message$Size($number$, get$capitalized_name$());\n"
+    "    .compute$group_or_message$Size($number$, $name$_);\n"
     "}\n");
 }
 
+void MessageFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "result = result && get$capitalized_name$()\n"
+    "    .equals(other.get$capitalized_name$());\n");
+}
+
+void MessageFieldGenerator::
+GenerateHashCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "hash = (37 * hash) + $constant_name$;\n"
+    "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
+}
+
 string MessageFieldGenerator::GetBoxedType() const {
   return ClassName(descriptor_->message_type());
 }
@@ -186,109 +412,416 @@
 // ===================================================================
 
 RepeatedMessageFieldGenerator::
-RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor)
-  : descriptor_(descriptor) {
-  SetMessageVariables(descriptor, &variables_);
+RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
+                              int messageBitIndex,
+                              int builderBitIndex)
+  : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+    builderBitIndex_(builderBitIndex) {
+  SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
+                      &variables_);
 }
 
 RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
 
+int RepeatedMessageFieldGenerator::GetNumBitsForMessage() const {
+  return 0;
+}
+
+int RepeatedMessageFieldGenerator::GetNumBitsForBuilder() const {
+  return 1;
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+  // TODO(jonp): In the future, consider having methods specific to the
+  // interface so that builders can choose dynamically to either return a
+  // message or a nested builder, so that asking for the interface doesn't
+  // cause a message to ever be built.
+  printer->Print(variables_,
+    "$deprecation$java.util.List<$type$> \n"
+    "    get$capitalized_name$List();\n"
+    "$deprecation$$type$ get$capitalized_name$(int index);\n"
+    "$deprecation$int get$capitalized_name$Count();\n");
+  if (HasNestedBuilders(descriptor_->containing_type())) {
+    printer->Print(variables_,
+      "$deprecation$java.util.List<? extends $type$OrBuilder> \n"
+      "    get$capitalized_name$OrBuilderList();\n"
+      "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder(\n"
+      "    int index);\n");
+  }
+}
+
 void RepeatedMessageFieldGenerator::
 GenerateMembers(io::Printer* printer) const {
   printer->Print(variables_,
-    "private java.util.List<$type$> $name$_ =\n"
-    "  java.util.Collections.emptyList();\n"
-    "public java.util.List<$type$> get$capitalized_name$List() {\n"
+    "private java.util.List<$type$> $name$_;\n"
+    "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
     "  return $name$_;\n"   // note:  unmodifiable list
     "}\n"
-    "public int get$capitalized_name$Count() { return $name$_.size(); }\n"
-    "public $type$ get$capitalized_name$(int index) {\n"
+    "$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
+    "    get$capitalized_name$OrBuilderList() {\n"
+    "  return $name$_;\n"
+    "}\n"
+    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "  return $name$_.size();\n"
+    "}\n"
+    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "  return $name$_.get(index);\n"
+    "}\n"
+    "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
+    "    int index) {\n"
     "  return $name$_.get(index);\n"
     "}\n");
+
+}
+
+void RepeatedMessageFieldGenerator::PrintNestedBuilderCondition(
+    io::Printer* printer,
+    const char* regular_case,
+    const char* nested_builder_case) const {
+  if (HasNestedBuilders(descriptor_->containing_type())) {
+     printer->Print(variables_, "if ($name$Builder_ == null) {\n");
+     printer->Indent();
+     printer->Print(variables_, regular_case);
+     printer->Outdent();
+     printer->Print("} else {\n");
+     printer->Indent();
+     printer->Print(variables_, nested_builder_case);
+     printer->Outdent();
+     printer->Print("}\n");
+   } else {
+     printer->Print(variables_, regular_case);
+   }
+}
+
+void RepeatedMessageFieldGenerator::PrintNestedBuilderFunction(
+    io::Printer* printer,
+    const char* method_prototype,
+    const char* regular_case,
+    const char* nested_builder_case,
+    const char* trailing_code) const {
+  printer->Print(variables_, method_prototype);
+  printer->Print(" {\n");
+  printer->Indent();
+  PrintNestedBuilderCondition(printer, regular_case, nested_builder_case);
+  if (trailing_code != NULL) {
+    printer->Print(variables_, trailing_code);
+  }
+  printer->Outdent();
+  printer->Print("}\n");
 }
 
 void RepeatedMessageFieldGenerator::
 GenerateBuilderMembers(io::Printer* printer) const {
+  // When using nested-builders, the code initially works just like the
+  // non-nested builder case. It only creates a nested builder lazily on
+  // demand and then forever delegates to it after creation.
+
   printer->Print(variables_,
-    // Note:  We return an unmodifiable list because otherwise the caller
-    //   could hold on to the returned list and modify it after the message
-    //   has been built, thus mutating the message which is supposed to be
-    //   immutable.
-    "public java.util.List<$type$> get$capitalized_name$List() {\n"
-    "  return java.util.Collections.unmodifiableList(result.$name$_);\n"
+    // Used when the builder is null.
+    // One field is the list and the other field keeps track of whether the
+    // list is immutable. If it's immutable, the invariant is that it must
+    // either an instance of Collections.emptyList() or it's an ArrayList
+    // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
+    // a refererence to the underlying ArrayList. This invariant allows us to
+    // share instances of lists between protocol buffers avoiding expensive
+    // memory allocations. Note, immutable is a strong guarantee here -- not
+    // just that the list cannot be modified via the reference but that the
+    // list can never be modified.
+    "private java.util.List<$type$> $name$_ =\n"
+    "  java.util.Collections.emptyList();\n"
+
+    "private void ensure$capitalized_name$IsMutable() {\n"
+    "  if (!$get_mutable_bit_builder$) {\n"
+    "    $name$_ = new java.util.ArrayList<$type$>($name$_);\n"
+    "    $set_mutable_bit_builder$;\n"
+    "   }\n"
     "}\n"
-    "public int get$capitalized_name$Count() {\n"
-    "  return result.get$capitalized_name$Count();\n"
+    "\n");
+
+  if (HasNestedBuilders(descriptor_->containing_type())) {
+    printer->Print(variables_,
+      // If this builder is non-null, it is used and the other fields are
+      // ignored.
+      "private com.google.protobuf.RepeatedFieldBuilder<\n"
+      "    $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;\n"
+      "\n");
+  }
+
+  // The comments above the methods below are based on a hypothetical
+  // repeated field of type "Field" called "RepeatedField".
+
+  // List<Field> getRepeatedFieldList()
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public java.util.List<$type$> get$capitalized_name$List()",
+
+    "return java.util.Collections.unmodifiableList($name$_);\n",
+    "return $name$Builder_.getMessageList();\n",
+
+    NULL);
+
+  // int getRepeatedFieldCount()
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public int get$capitalized_name$Count()",
+
+    "return $name$_.size();\n",
+    "return $name$Builder_.getCount();\n",
+
+    NULL);
+
+  // Field getRepeatedField(int index)
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public $type$ get$capitalized_name$(int index)",
+
+    "return $name$_.get(index);\n",
+
+    "return $name$Builder_.getMessage(index);\n",
+
+    NULL);
+
+  // Builder setRepeatedField(int index, Field value)
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder set$capitalized_name$(\n"
+    "    int index, $type$ value)",
+    "if (value == null) {\n"
+    "  throw new NullPointerException();\n"
     "}\n"
-    "public $type$ get$capitalized_name$(int index) {\n"
-    "  return result.get$capitalized_name$(index);\n"
+    "ensure$capitalized_name$IsMutable();\n"
+    "$name$_.set(index, value);\n"
+    "$on_changed$\n",
+    "$name$Builder_.setMessage(index, value);\n",
+    "return this;\n");
+
+  // Builder setRepeatedField(int index, Field.Builder builderForValue)
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder set$capitalized_name$(\n"
+    "    int index, $type$.Builder builderForValue)",
+
+    "ensure$capitalized_name$IsMutable();\n"
+    "$name$_.set(index, builderForValue.build());\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.setMessage(index, builderForValue.build());\n",
+
+    "return this;\n");
+
+  // Builder addRepeatedField(Field value)
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder add$capitalized_name$($type$ value)",
+
+    "if (value == null) {\n"
+    "  throw new NullPointerException();\n"
     "}\n"
-    "public Builder set$capitalized_name$(int index, $type$ value) {\n"
-    "  if (value == null) {\n"
-    "    throw new NullPointerException();\n"
-    "  }\n"
-    "  result.$name$_.set(index, value);\n"
-    "  return this;\n"
+    "ensure$capitalized_name$IsMutable();\n"
+    "$name$_.add(value);\n"
+
+    "$on_changed$\n",
+
+    "$name$Builder_.addMessage(value);\n",
+
+    "return this;\n");
+
+  // Builder addRepeatedField(int index, Field value)
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder add$capitalized_name$(\n"
+    "    int index, $type$ value)",
+
+    "if (value == null) {\n"
+    "  throw new NullPointerException();\n"
     "}\n"
-    "public Builder set$capitalized_name$(int index, "
-      "$type$.Builder builderForValue) {\n"
-    "  result.$name$_.set(index, builderForValue.build());\n"
-    "  return this;\n"
-    "}\n"
-    "public Builder add$capitalized_name$($type$ value) {\n"
-    "  if (value == null) {\n"
-    "    throw new NullPointerException();\n"
-    "  }\n"
-    "  if (result.$name$_.isEmpty()) {\n"
-    "    result.$name$_ = new java.util.ArrayList<$type$>();\n"
-    "  }\n"
-    "  result.$name$_.add(value);\n"
-    "  return this;\n"
-    "}\n"
-    "public Builder add$capitalized_name$($type$.Builder builderForValue) {\n"
-    "  if (result.$name$_.isEmpty()) {\n"
-    "    result.$name$_ = new java.util.ArrayList<$type$>();\n"
-    "  }\n"
-    "  result.$name$_.add(builderForValue.build());\n"
-    "  return this;\n"
-    "}\n"
-    "public Builder addAll$capitalized_name$(\n"
-    "    java.lang.Iterable<? extends $type$> values) {\n"
-    "  if (result.$name$_.isEmpty()) {\n"
-    "    result.$name$_ = new java.util.ArrayList<$type$>();\n"
-    "  }\n"
-    "  super.addAll(values, result.$name$_);\n"
-    "  return this;\n"
-    "}\n"
-    "public Builder clear$capitalized_name$() {\n"
-    "  result.$name$_ = java.util.Collections.emptyList();\n"
-    "  return this;\n"
-    "}\n");
+    "ensure$capitalized_name$IsMutable();\n"
+    "$name$_.add(index, value);\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.addMessage(index, value);\n",
+
+    "return this;\n");
+
+  // Builder addRepeatedField(Field.Builder builderForValue)
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder add$capitalized_name$(\n"
+    "    $type$.Builder builderForValue)",
+
+    "ensure$capitalized_name$IsMutable();\n"
+    "$name$_.add(builderForValue.build());\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.addMessage(builderForValue.build());\n",
+
+    "return this;\n");
+
+  // Builder addRepeatedField(int index, Field.Builder builderForValue)
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder add$capitalized_name$(\n"
+    "    int index, $type$.Builder builderForValue)",
+
+    "ensure$capitalized_name$IsMutable();\n"
+    "$name$_.add(index, builderForValue.build());\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.addMessage(index, builderForValue.build());\n",
+
+    "return this;\n");
+
+  // Builder addAllRepeatedField(Iterable<Field> values)
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder addAll$capitalized_name$(\n"
+    "    java.lang.Iterable<? extends $type$> values)",
+
+    "ensure$capitalized_name$IsMutable();\n"
+    "super.addAll(values, $name$_);\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.addAllMessages(values);\n",
+
+    "return this;\n");
+
+  // Builder clearAllRepeatedField()
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder clear$capitalized_name$()",
+
+    "$name$_ = java.util.Collections.emptyList();\n"
+    "$clear_mutable_bit_builder$;\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.clear();\n",
+
+    "return this;\n");
+
+  // Builder removeRepeatedField(int index)
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder remove$capitalized_name$(int index)",
+
+    "ensure$capitalized_name$IsMutable();\n"
+    "$name$_.remove(index);\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.remove(index);\n",
+
+    "return this;\n");
+
+  if (HasNestedBuilders(descriptor_->containing_type())) {
+    printer->Print(variables_,
+      "$deprecation$public $type$.Builder get$capitalized_name$Builder(\n"
+      "    int index) {\n"
+      "  return get$capitalized_name$FieldBuilder().getBuilder(index);\n"
+      "}\n"
+
+      "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
+      "    int index) {\n"
+      "  if ($name$Builder_ == null) {\n"
+      "    return $name$_.get(index);"
+      "  } else {\n"
+      "    return $name$Builder_.getMessageOrBuilder(index);\n"
+      "  }\n"
+      "}\n"
+
+      "$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
+      "     get$capitalized_name$OrBuilderList() {\n"
+      "  if ($name$Builder_ != null) {\n"
+      "    return $name$Builder_.getMessageOrBuilderList();\n"
+      "  } else {\n"
+      "    return java.util.Collections.unmodifiableList($name$_);\n"
+      "  }\n"
+      "}\n"
+
+      "$deprecation$public $type$.Builder add$capitalized_name$Builder() {\n"
+      "  return get$capitalized_name$FieldBuilder().addBuilder(\n"
+      "      $type$.getDefaultInstance());\n"
+      "}\n"
+      "$deprecation$public $type$.Builder add$capitalized_name$Builder(\n"
+      "    int index) {\n"
+      "  return get$capitalized_name$FieldBuilder().addBuilder(\n"
+      "      index, $type$.getDefaultInstance());\n"
+      "}\n"
+      "$deprecation$public java.util.List<$type$.Builder> \n"
+      "     get$capitalized_name$BuilderList() {\n"
+      "  return get$capitalized_name$FieldBuilder().getBuilderList();\n"
+      "}\n"
+      "private com.google.protobuf.RepeatedFieldBuilder<\n"
+      "    $type$, $type$.Builder, $type$OrBuilder> \n"
+      "    get$capitalized_name$FieldBuilder() {\n"
+      "  if ($name$Builder_ == null) {\n"
+      "    $name$Builder_ = new com.google.protobuf.RepeatedFieldBuilder<\n"
+      "        $type$, $type$.Builder, $type$OrBuilder>(\n"
+      "            $name$_,\n"
+      "            $get_mutable_bit_builder$,\n"
+      "            getParentForChildren(),\n"
+      "            isClean());\n"
+      "    $name$_ = null;\n"
+      "  }\n"
+      "  return $name$Builder_;\n"
+      "}\n");
+  }
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
+  printer->Print(variables_,
+    "get$capitalized_name$FieldBuilder();\n");
 }
 
 void RepeatedMessageFieldGenerator::
 GenerateInitializationCode(io::Printer* printer) const {
-  // Initialized inline.
+  printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n");
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateBuilderClearCode(io::Printer* printer) const {
+  PrintNestedBuilderCondition(printer,
+    "$name$_ = java.util.Collections.emptyList();\n"
+    "$clear_mutable_bit_builder$;\n",
+
+    "$name$Builder_.clear();\n");
 }
 
 void RepeatedMessageFieldGenerator::
 GenerateMergingCode(io::Printer* printer) const {
-  printer->Print(variables_,
+  // The code below does two optimizations (non-nested builder case):
+  //   1. If the other list is empty, there's nothing to do. This ensures we
+  //      don't allocate a new array if we already have an immutable one.
+  //   2. If the other list is non-empty and our current list is empty, we can
+  //      reuse the other list which is guaranteed to be immutable.
+  PrintNestedBuilderCondition(printer,
     "if (!other.$name$_.isEmpty()) {\n"
-    "  if (result.$name$_.isEmpty()) {\n"
-    "    result.$name$_ = new java.util.ArrayList<$type$>();\n"
+    "  if ($name$_.isEmpty()) {\n"
+    "    $name$_ = other.$name$_;\n"
+    "    $clear_mutable_bit_builder$;\n"
+    "  } else {\n"
+    "    ensure$capitalized_name$IsMutable();\n"
+    "    $name$_.addAll(other.$name$_);\n"
     "  }\n"
-    "  result.$name$_.addAll(other.$name$_);\n"
+    "  $on_changed$\n"
+    "}\n",
+
+    "if (!other.$name$_.isEmpty()) {\n"
+    "  if ($name$Builder_.isEmpty()) {\n"
+    "    $name$Builder_.dispose();\n"
+    "    $name$Builder_ = null;\n"
+    "    $name$_ = other.$name$_;\n"
+    "    $clear_mutable_bit_builder$;\n"
+    "    $name$Builder_ = \n"
+    "      com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?\n"
+    "         get$capitalized_name$FieldBuilder() : null;\n"
+    "  } else {\n"
+    "    $name$Builder_.addAllMessages(other.$name$_);\n"
+    "  }\n"
     "}\n");
 }
 
 void RepeatedMessageFieldGenerator::
 GenerateBuildingCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "if (result.$name$_ != java.util.Collections.EMPTY_LIST) {\n"
-    "  result.$name$_ =\n"
-    "    java.util.Collections.unmodifiableList(result.$name$_);\n"
-    "}\n");
+  // The code below (non-nested builder case) ensures that the result has an
+  // immutable list. If our list is immutable, we can just reuse it. If not,
+  // we make it immutable.
+  PrintNestedBuilderCondition(printer,
+    "if ($get_mutable_bit_builder$) {\n"
+    "  $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
+    "  $clear_mutable_bit_builder$;\n"
+    "}\n"
+    "result.$name$_ = $name$_;\n",
+
+    "result.$name$_ = $name$Builder_.build();\n");
 }
 
 void RepeatedMessageFieldGenerator::
@@ -311,17 +844,33 @@
 void RepeatedMessageFieldGenerator::
 GenerateSerializationCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "for ($type$ element : get$capitalized_name$List()) {\n"
-    "  output.write$group_or_message$($number$, element);\n"
+    "for (int i = 0; i < $name$_.size(); i++) {\n"
+    "  output.write$group_or_message$($number$, $name$_.get(i));\n"
     "}\n");
 }
 
 void RepeatedMessageFieldGenerator::
 GenerateSerializedSizeCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "for ($type$ element : get$capitalized_name$List()) {\n"
+    "for (int i = 0; i < $name$_.size(); i++) {\n"
     "  size += com.google.protobuf.CodedOutputStream\n"
-    "    .compute$group_or_message$Size($number$, element);\n"
+    "    .compute$group_or_message$Size($number$, $name$_.get(i));\n"
+    "}\n");
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "result = result && get$capitalized_name$List()\n"
+    "    .equals(other.get$capitalized_name$List());\n");
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateHashCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (get$capitalized_name$Count() > 0) {\n"
+    "  hash = (37 * hash) + $constant_name$;\n"
+    "  hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
     "}\n");
 }
 
diff --git a/src/google/protobuf/compiler/java/java_message_field.h b/src/google/protobuf/compiler/java/java_message_field.h
index 66bdd88..2efbcd9 100644
--- a/src/google/protobuf/compiler/java/java_message_field.h
+++ b/src/google/protobuf/compiler/java/java_message_field.h
@@ -46,50 +46,84 @@
 
 class MessageFieldGenerator : public FieldGenerator {
  public:
-  explicit MessageFieldGenerator(const FieldDescriptor* descriptor);
+  explicit MessageFieldGenerator(const FieldDescriptor* descriptor,
+      int messageBitIndex, int builderBitIndex);
   ~MessageFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
+  int GetNumBitsForMessage() const;
+  int GetNumBitsForBuilder() const;
+  void GenerateInterfaceMembers(io::Printer* printer) const;
   void GenerateMembers(io::Printer* printer) const;
   void GenerateBuilderMembers(io::Printer* printer) const;
   void GenerateInitializationCode(io::Printer* printer) const;
+  void GenerateBuilderClearCode(io::Printer* printer) const;
   void GenerateMergingCode(io::Printer* printer) const;
   void GenerateBuildingCode(io::Printer* printer) const;
   void GenerateParsingCode(io::Printer* printer) const;
   void GenerateSerializationCode(io::Printer* printer) const;
   void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCode(io::Printer* printer) const;
 
   string GetBoxedType() const;
 
  private:
   const FieldDescriptor* descriptor_;
   map<string, string> variables_;
+  const int messageBitIndex_;
+  const int builderBitIndex_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator);
+
+  void PrintNestedBuilderCondition(io::Printer* printer,
+      const char* regular_case, const char* nested_builder_case) const;
+  void PrintNestedBuilderFunction(io::Printer* printer,
+      const char* method_prototype, const char* regular_case,
+      const char* nested_builder_case,
+      const char* trailing_code) const;
 };
 
 class RepeatedMessageFieldGenerator : public FieldGenerator {
  public:
-  explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor);
+  explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
+      int messageBitIndex, int builderBitIndex);
   ~RepeatedMessageFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
+  int GetNumBitsForMessage() const;
+  int GetNumBitsForBuilder() const;
+  void GenerateInterfaceMembers(io::Printer* printer) const;
   void GenerateMembers(io::Printer* printer) const;
   void GenerateBuilderMembers(io::Printer* printer) const;
   void GenerateInitializationCode(io::Printer* printer) const;
+  void GenerateBuilderClearCode(io::Printer* printer) const;
   void GenerateMergingCode(io::Printer* printer) const;
   void GenerateBuildingCode(io::Printer* printer) const;
   void GenerateParsingCode(io::Printer* printer) const;
   void GenerateSerializationCode(io::Printer* printer) const;
   void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCode(io::Printer* printer) const;
 
   string GetBoxedType() const;
 
  private:
   const FieldDescriptor* descriptor_;
   map<string, string> variables_;
+  const int messageBitIndex_;
+  const int builderBitIndex_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator);
+
+  void PrintNestedBuilderCondition(io::Printer* printer,
+      const char* regular_case, const char* nested_builder_case) const;
+  void PrintNestedBuilderFunction(io::Printer* printer,
+      const char* method_prototype, const char* regular_case,
+      const char* nested_builder_case,
+      const char* trailing_code) const;
 };
 
 }  // namespace java
diff --git a/src/google/protobuf/compiler/java/java_plugin_unittest.cc b/src/google/protobuf/compiler/java/java_plugin_unittest.cc
index cfe0188..ccc94c9 100644
--- a/src/google/protobuf/compiler/java/java_plugin_unittest.cc
+++ b/src/google/protobuf/compiler/java/java_plugin_unittest.cc
@@ -56,21 +56,22 @@
 
   virtual bool Generate(const FileDescriptor* file,
                         const string& parameter,
-                        OutputDirectory* output_directory,
+                        GeneratorContext* context,
                         string* error) const {
-    TryInsert("Test.java", "outer_class_scope", output_directory);
-    TryInsert("Test.java", "class_scope:foo.Bar", output_directory);
-    TryInsert("Test.java", "class_scope:foo.Bar.Baz", output_directory);
-    TryInsert("Test.java", "builder_scope:foo.Bar", output_directory);
-    TryInsert("Test.java", "builder_scope:foo.Bar.Baz", output_directory);
-    TryInsert("Test.java", "enum_scope:foo.Qux", output_directory);
+    string filename = "Test.java";
+    TryInsert(filename, "outer_class_scope", context);
+    TryInsert(filename, "class_scope:foo.Bar", context);
+    TryInsert(filename, "class_scope:foo.Bar.Baz", context);
+    TryInsert(filename, "builder_scope:foo.Bar", context);
+    TryInsert(filename, "builder_scope:foo.Bar.Baz", context);
+    TryInsert(filename, "enum_scope:foo.Qux", context);
     return true;
   }
 
   void TryInsert(const string& filename, const string& insertion_point,
-                 OutputDirectory* output_directory) const {
+                 GeneratorContext* context) const {
     scoped_ptr<io::ZeroCopyOutputStream> output(
-      output_directory->OpenForInsert(filename, insertion_point));
+      context->OpenForInsert(filename, insertion_point));
     io::Printer printer(output.get(), '$');
     printer.Print("// inserted $name$\n", "name", insertion_point);
   }
diff --git a/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc
index f6179bf..addb881 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field.cc
+++ b/src/google/protobuf/compiler/java/java_primitive_field.cc
@@ -154,15 +154,24 @@
 }
 
 void SetPrimitiveVariables(const FieldDescriptor* descriptor,
+                           int messageBitIndex,
+                           int builderBitIndex,
                            map<string, string>* variables) {
   (*variables)["name"] =
     UnderscoresToCamelCase(descriptor);
   (*variables)["capitalized_name"] =
     UnderscoresToCapitalizedCamelCase(descriptor);
+  (*variables)["constant_name"] = FieldConstantName(descriptor);
   (*variables)["number"] = SimpleItoa(descriptor->number());
   (*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor));
   (*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor));
+  (*variables)["field_type"] = (*variables)["type"];
+  (*variables)["field_list_type"] = "java.util.List<" +
+      (*variables)["boxed_type"] + ">";
+  (*variables)["empty_list"] = "java.util.Collections.emptyList();";
   (*variables)["default"] = DefaultValue(descriptor);
+  (*variables)["default_init"] = IsDefaultValueJavaDefault(descriptor) ?
+      "" : ("= " + DefaultValue(descriptor));
   (*variables)["capitalized_type"] = GetCapitalizedType(descriptor);
   (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
   (*variables)["tag_size"] = SimpleItoa(
@@ -175,67 +184,135 @@
   } else {
     (*variables)["null_check"] = "";
   }
+  // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
+  // by the proto compiler
+  (*variables)["deprecation"] = descriptor->options().deprecated()
+      ? "@java.lang.Deprecated " : "";
   int fixed_size = FixedSize(GetType(descriptor));
   if (fixed_size != -1) {
     (*variables)["fixed_size"] = SimpleItoa(fixed_size);
   }
+  (*variables)["on_changed"] =
+      HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
+
+  // For singular messages and builders, one bit is used for the hasField bit.
+  (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+
+  (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
+  (*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex);
+  (*variables)["clear_has_field_bit_builder"] =
+      GenerateClearBit(builderBitIndex);
+
+  // For repated builders, one bit is used for whether the array is immutable.
+  (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
+  (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
+  (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
+
+  (*variables)["get_has_field_bit_from_local"] =
+      GenerateGetBitFromLocal(builderBitIndex);
+  (*variables)["set_has_field_bit_to_local"] =
+      GenerateSetBitToLocal(messageBitIndex);
 }
+
 }  // namespace
 
 // ===================================================================
 
 PrimitiveFieldGenerator::
-PrimitiveFieldGenerator(const FieldDescriptor* descriptor)
-  : descriptor_(descriptor) {
-  SetPrimitiveVariables(descriptor, &variables_);
+PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+                        int messageBitIndex,
+                        int builderBitIndex)
+  : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+    builderBitIndex_(builderBitIndex) {
+  SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
+                        &variables_);
 }
 
 PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
 
+int PrimitiveFieldGenerator::GetNumBitsForMessage() const {
+  return 1;
+}
+
+int PrimitiveFieldGenerator::GetNumBitsForBuilder() const {
+  return 1;
+}
+
+void PrimitiveFieldGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$deprecation$boolean has$capitalized_name$();\n"
+    "$deprecation$$type$ get$capitalized_name$();\n");
+}
+
 void PrimitiveFieldGenerator::
 GenerateMembers(io::Printer* printer) const {
   printer->Print(variables_,
-    "private boolean has$capitalized_name$;\n"
-    "private $type$ $name$_ = $default$;\n"
-    "public boolean has$capitalized_name$() { return has$capitalized_name$; }\n"
-    "public $type$ get$capitalized_name$() { return $name$_; }\n");
+    "private $field_type$ $name$_;\n"
+    "$deprecation$public boolean has$capitalized_name$() {\n"
+    "  return $get_has_field_bit_message$;\n"
+    "}\n");
+
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "  return $name$_;\n"
+    "}\n");
 }
 
 void PrimitiveFieldGenerator::
 GenerateBuilderMembers(io::Printer* printer) const {
   printer->Print(variables_,
-    "public boolean has$capitalized_name$() {\n"
-    "  return result.has$capitalized_name$();\n"
-    "}\n"
-    "public $type$ get$capitalized_name$() {\n"
-    "  return result.get$capitalized_name$();\n"
-    "}\n"
-    "public Builder set$capitalized_name$($type$ value) {\n"
+    "private $field_type$ $name$_ $default_init$;\n"
+    "$deprecation$public boolean has$capitalized_name$() {\n"
+    "  return $get_has_field_bit_builder$;\n"
+    "}\n");
+
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "  return $name$_;\n"
+    "}\n");
+
+  printer->Print(variables_,
+    "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
     "$null_check$"
-    "  result.has$capitalized_name$ = true;\n"
-    "  result.$name$_ = value;\n"
+    "  $set_has_field_bit_builder$;\n"
+    "  $name$_ = value;\n"
+    "  $on_changed$\n"
     "  return this;\n"
     "}\n"
-    "public Builder clear$capitalized_name$() {\n"
-    "  result.has$capitalized_name$ = false;\n");
+    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "  $clear_has_field_bit_builder$;\n");
   JavaType type = GetJavaType(descriptor_);
   if (type == JAVATYPE_STRING || type == JAVATYPE_BYTES) {
     // The default value is not a simple literal so we want to avoid executing
     // it multiple times.  Instead, get the default out of the default instance.
     printer->Print(variables_,
-      "  result.$name$_ = getDefaultInstance().get$capitalized_name$();\n");
+      "  $name$_ = getDefaultInstance().get$capitalized_name$();\n");
   } else {
     printer->Print(variables_,
-      "  result.$name$_ = $default$;\n");
+      "  $name$_ = $default$;\n");
   }
   printer->Print(variables_,
+    "  $on_changed$\n"
     "  return this;\n"
     "}\n");
 }
 
 void PrimitiveFieldGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
+  // noop for primitives
+}
+
+void PrimitiveFieldGenerator::
 GenerateInitializationCode(io::Printer* printer) const {
-  // Initialized inline.
+  printer->Print(variables_, "$name$_ = $default$;\n");
+}
+
+void PrimitiveFieldGenerator::
+GenerateBuilderClearCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$name$_ = $default$;\n"
+    "$clear_has_field_bit_builder$;\n");
 }
 
 void PrimitiveFieldGenerator::
@@ -248,32 +325,121 @@
 
 void PrimitiveFieldGenerator::
 GenerateBuildingCode(io::Printer* printer) const {
-  // Nothing to do here for primitive types.
+  printer->Print(variables_,
+    "if ($get_has_field_bit_from_local$) {\n"
+    "  $set_has_field_bit_to_local$;\n"
+    "}\n"
+    "result.$name$_ = $name$_;\n");
 }
 
 void PrimitiveFieldGenerator::
 GenerateParsingCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "set$capitalized_name$(input.read$capitalized_type$());\n");
+    "$set_has_field_bit_builder$;\n"
+    "$name$_ = input.read$capitalized_type$();\n");
 }
 
 void PrimitiveFieldGenerator::
 GenerateSerializationCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "if (has$capitalized_name$()) {\n"
-    "  output.write$capitalized_type$($number$, get$capitalized_name$());\n"
+    "if ($get_has_field_bit_message$) {\n"
+    "  output.write$capitalized_type$($number$, $name$_);\n"
     "}\n");
 }
 
 void PrimitiveFieldGenerator::
 GenerateSerializedSizeCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "if (has$capitalized_name$()) {\n"
+    "if ($get_has_field_bit_message$) {\n"
     "  size += com.google.protobuf.CodedOutputStream\n"
-    "    .compute$capitalized_type$Size($number$, get$capitalized_name$());\n"
+    "    .compute$capitalized_type$Size($number$, $name$_);\n"
     "}\n");
 }
 
+void PrimitiveFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  switch (GetJavaType(descriptor_)) {
+    case JAVATYPE_INT:
+    case JAVATYPE_LONG:
+    case JAVATYPE_BOOLEAN:
+      printer->Print(variables_,
+        "result = result && (get$capitalized_name$()\n"
+        "    == other.get$capitalized_name$());\n");
+      break;
+
+    case JAVATYPE_FLOAT:
+      printer->Print(variables_,
+        "result = result && (Float.floatToIntBits(get$capitalized_name$())"
+        "    == Float.floatToIntBits(other.get$capitalized_name$()));\n");
+      break;
+
+    case JAVATYPE_DOUBLE:
+      printer->Print(variables_,
+        "result = result && (Double.doubleToLongBits(get$capitalized_name$())"
+        "    == Double.doubleToLongBits(other.get$capitalized_name$()));\n");
+      break;
+
+    case JAVATYPE_STRING:
+    case JAVATYPE_BYTES:
+      printer->Print(variables_,
+        "result = result && get$capitalized_name$()\n"
+        "    .equals(other.get$capitalized_name$());\n");
+      break;
+
+    case JAVATYPE_ENUM:
+    case JAVATYPE_MESSAGE:
+    default:
+      GOOGLE_LOG(FATAL) << "Can't get here.";
+      break;
+  }
+}
+
+void PrimitiveFieldGenerator::
+GenerateHashCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "hash = (37 * hash) + $constant_name$;\n");
+  switch (GetJavaType(descriptor_)) {
+    case JAVATYPE_INT:
+      printer->Print(variables_,
+        "hash = (53 * hash) + get$capitalized_name$();\n");
+      break;
+
+    case JAVATYPE_LONG:
+      printer->Print(variables_,
+        "hash = (53 * hash) + hashLong(get$capitalized_name$());\n");
+      break;
+
+    case JAVATYPE_BOOLEAN:
+      printer->Print(variables_,
+        "hash = (53 * hash) + hashBoolean(get$capitalized_name$());\n");
+      break;
+
+    case JAVATYPE_FLOAT:
+      printer->Print(variables_,
+        "hash = (53 * hash) + Float.floatToIntBits(\n"
+        "    get$capitalized_name$());\n");
+      break;
+
+    case JAVATYPE_DOUBLE:
+      printer->Print(variables_,
+        "hash = (53 * hash) + hashLong(\n"
+        "    Double.doubleToLongBits(get$capitalized_name$()));\n");
+      break;
+
+    case JAVATYPE_STRING:
+    case JAVATYPE_BYTES:
+      printer->Print(variables_,
+        "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
+      break;
+
+    case JAVATYPE_ENUM:
+    case JAVATYPE_MESSAGE:
+    default:
+      GOOGLE_LOG(FATAL) << "Can't get here.";
+      break;
+  }
+}
+
 string PrimitiveFieldGenerator::GetBoxedType() const {
   return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
 }
@@ -281,23 +447,46 @@
 // ===================================================================
 
 RepeatedPrimitiveFieldGenerator::
-RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor)
-  : descriptor_(descriptor) {
-  SetPrimitiveVariables(descriptor, &variables_);
+RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+                                int messageBitIndex,
+                                int builderBitIndex)
+  : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+    builderBitIndex_(builderBitIndex) {
+  SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
+                        &variables_);
 }
 
 RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
 
+int RepeatedPrimitiveFieldGenerator::GetNumBitsForMessage() const {
+  return 0;
+}
+
+int RepeatedPrimitiveFieldGenerator::GetNumBitsForBuilder() const {
+  return 1;
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$deprecation$java.util.List<$boxed_type$> get$capitalized_name$List();\n"
+    "$deprecation$int get$capitalized_name$Count();\n"
+    "$deprecation$$type$ get$capitalized_name$(int index);\n");
+}
+
+
 void RepeatedPrimitiveFieldGenerator::
 GenerateMembers(io::Printer* printer) const {
   printer->Print(variables_,
-    "private java.util.List<$boxed_type$> $name$_ =\n"
-    "  java.util.Collections.emptyList();\n"
-    "public java.util.List<$boxed_type$> get$capitalized_name$List() {\n"
+    "private $field_list_type$ $name$_;\n"
+    "$deprecation$public java.util.List<$boxed_type$>\n"
+    "    get$capitalized_name$List() {\n"
     "  return $name$_;\n"   // note:  unmodifiable list
     "}\n"
-    "public int get$capitalized_name$Count() { return $name$_.size(); }\n"
-    "public $type$ get$capitalized_name$(int index) {\n"
+    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "  return $name$_.size();\n"
+    "}\n"
+    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
     "  return $name$_.get(index);\n"
     "}\n");
 
@@ -310,76 +499,125 @@
 
 void RepeatedPrimitiveFieldGenerator::
 GenerateBuilderMembers(io::Printer* printer) const {
+  // One field is the list and the bit field keeps track of whether the
+  // list is immutable. If it's immutable, the invariant is that it must
+  // either an instance of Collections.emptyList() or it's an ArrayList
+  // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
+  // a refererence to the underlying ArrayList. This invariant allows us to
+  // share instances of lists between protocol buffers avoiding expensive
+  // memory allocations. Note, immutable is a strong guarantee here -- not
+  // just that the list cannot be modified via the reference but that the
+  // list can never be modified.
   printer->Print(variables_,
+    "private $field_list_type$ $name$_ = $empty_list$;\n");
+
+  printer->Print(variables_,
+    "private void ensure$capitalized_name$IsMutable() {\n"
+    "  if (!$get_mutable_bit_builder$) {\n"
+    "    $name$_ = new java.util.ArrayList<$boxed_type$>($name$_);\n"
+    "    $set_mutable_bit_builder$;\n"
+    "   }\n"
+    "}\n");
+
     // Note:  We return an unmodifiable list because otherwise the caller
     //   could hold on to the returned list and modify it after the message
     //   has been built, thus mutating the message which is supposed to be
     //   immutable.
-    "public java.util.List<$boxed_type$> get$capitalized_name$List() {\n"
-    "  return java.util.Collections.unmodifiableList(result.$name$_);\n"
+  printer->Print(variables_,
+    "$deprecation$public java.util.List<$boxed_type$>\n"
+    "    get$capitalized_name$List() {\n"
+    "  return java.util.Collections.unmodifiableList($name$_);\n"
     "}\n"
-    "public int get$capitalized_name$Count() {\n"
-    "  return result.get$capitalized_name$Count();\n"
+    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "  return $name$_.size();\n"
     "}\n"
-    "public $type$ get$capitalized_name$(int index) {\n"
-    "  return result.get$capitalized_name$(index);\n"
+    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "  return $name$_.get(index);\n"
     "}\n"
-    "public Builder set$capitalized_name$(int index, $type$ value) {\n"
+    "$deprecation$public Builder set$capitalized_name$(\n"
+    "    int index, $type$ value) {\n"
     "$null_check$"
-    "  result.$name$_.set(index, value);\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.set(index, value);\n"
+    "  $on_changed$\n"
     "  return this;\n"
     "}\n"
-    "public Builder add$capitalized_name$($type$ value) {\n"
+    "$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
     "$null_check$"
-    "  if (result.$name$_.isEmpty()) {\n"
-    "    result.$name$_ = new java.util.ArrayList<$boxed_type$>();\n"
-    "  }\n"
-    "  result.$name$_.add(value);\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.add(value);\n"
+    "  $on_changed$\n"
     "  return this;\n"
     "}\n"
-    "public Builder addAll$capitalized_name$(\n"
+    "$deprecation$public Builder addAll$capitalized_name$(\n"
     "    java.lang.Iterable<? extends $boxed_type$> values) {\n"
-    "  if (result.$name$_.isEmpty()) {\n"
-    "    result.$name$_ = new java.util.ArrayList<$boxed_type$>();\n"
-    "  }\n"
-    "  super.addAll(values, result.$name$_);\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  super.addAll(values, $name$_);\n"
+    "  $on_changed$\n"
     "  return this;\n"
     "}\n"
-    "public Builder clear$capitalized_name$() {\n"
-    "  result.$name$_ = java.util.Collections.emptyList();\n"
+    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "  $name$_ = $empty_list$;\n"
+    "  $clear_mutable_bit_builder$;\n"
+    "  $on_changed$\n"
     "  return this;\n"
     "}\n");
 }
 
 void RepeatedPrimitiveFieldGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
+  // noop for primitives
+}
+
+void RepeatedPrimitiveFieldGenerator::
 GenerateInitializationCode(io::Printer* printer) const {
-  // Initialized inline.
+  printer->Print(variables_, "$name$_ = $empty_list$;\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateBuilderClearCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$name$_ = $empty_list$;\n"
+    "$clear_mutable_bit_builder$;\n");
 }
 
 void RepeatedPrimitiveFieldGenerator::
 GenerateMergingCode(io::Printer* printer) const {
+  // The code below does two optimizations:
+  //   1. If the other list is empty, there's nothing to do. This ensures we
+  //      don't allocate a new array if we already have an immutable one.
+  //   2. If the other list is non-empty and our current list is empty, we can
+  //      reuse the other list which is guaranteed to be immutable.
   printer->Print(variables_,
     "if (!other.$name$_.isEmpty()) {\n"
-    "  if (result.$name$_.isEmpty()) {\n"
-    "    result.$name$_ = new java.util.ArrayList<$boxed_type$>();\n"
+    "  if ($name$_.isEmpty()) {\n"
+    "    $name$_ = other.$name$_;\n"
+    "    $clear_mutable_bit_builder$;\n"
+    "  } else {\n"
+    "    ensure$capitalized_name$IsMutable();\n"
+    "    $name$_.addAll(other.$name$_);\n"
     "  }\n"
-    "  result.$name$_.addAll(other.$name$_);\n"
+    "  $on_changed$\n"
     "}\n");
 }
 
 void RepeatedPrimitiveFieldGenerator::
 GenerateBuildingCode(io::Printer* printer) const {
+  // The code below ensures that the result has an immutable list. If our
+  // list is immutable, we can just reuse it. If not, we make it immutable.
   printer->Print(variables_,
-    "if (result.$name$_ != java.util.Collections.EMPTY_LIST) {\n"
-    "  result.$name$_ =\n"
-    "    java.util.Collections.unmodifiableList(result.$name$_);\n"
-    "}\n");
+    "if ($get_mutable_bit_builder$) {\n"
+    "  $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
+    "  $clear_mutable_bit_builder$;\n"
+    "}\n"
+    "result.$name$_ = $name$_;\n");
 }
 
 void RepeatedPrimitiveFieldGenerator::
 GenerateParsingCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "add$capitalized_name$(input.read$capitalized_type$());\n");
+    "ensure$capitalized_name$IsMutable();\n"
+    "$name$_.add(input.read$capitalized_type$());\n");
 }
 
 void RepeatedPrimitiveFieldGenerator::
@@ -401,13 +639,13 @@
       "  output.writeRawVarint32($tag$);\n"
       "  output.writeRawVarint32($name$MemoizedSerializedSize);\n"
       "}\n"
-      "for ($type$ element : get$capitalized_name$List()) {\n"
-      "  output.write$capitalized_type$NoTag(element);\n"
+      "for (int i = 0; i < $name$_.size(); i++) {\n"
+      "  output.write$capitalized_type$NoTag($name$_.get(i));\n"
       "}\n");
   } else {
     printer->Print(variables_,
-      "for ($type$ element : get$capitalized_name$List()) {\n"
-      "  output.write$capitalized_type$($number$, element);\n"
+      "for (int i = 0; i < $name$_.size(); i++) {\n"
+      "  output.write$capitalized_type$($number$, $name$_.get(i));\n"
       "}\n");
   }
 }
@@ -421,9 +659,9 @@
 
   if (FixedSize(GetType(descriptor_)) == -1) {
     printer->Print(variables_,
-      "for ($type$ element : get$capitalized_name$List()) {\n"
+      "for (int i = 0; i < $name$_.size(); i++) {\n"
       "  dataSize += com.google.protobuf.CodedOutputStream\n"
-      "    .compute$capitalized_type$SizeNoTag(element);\n"
+      "    .compute$capitalized_type$SizeNoTag($name$_.get(i));\n"
       "}\n");
   } else {
     printer->Print(variables_,
@@ -455,6 +693,22 @@
   printer->Print("}\n");
 }
 
+void RepeatedPrimitiveFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "result = result && get$capitalized_name$List()\n"
+    "    .equals(other.get$capitalized_name$List());\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateHashCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (get$capitalized_name$Count() > 0) {\n"
+    "  hash = (37 * hash) + $constant_name$;\n"
+    "  hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
+    "}\n");
+}
+
 string RepeatedPrimitiveFieldGenerator::GetBoxedType() const {
   return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
 }
diff --git a/src/google/protobuf/compiler/java/java_primitive_field.h b/src/google/protobuf/compiler/java/java_primitive_field.h
index 4e482a0..7900fac 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field.h
+++ b/src/google/protobuf/compiler/java/java_primitive_field.h
@@ -46,49 +46,69 @@
 
 class PrimitiveFieldGenerator : public FieldGenerator {
  public:
-  explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor);
+  explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+      int messageBitIndex, int builderBitIndex);
   ~PrimitiveFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
+  int GetNumBitsForMessage() const;
+  int GetNumBitsForBuilder() const;
+  void GenerateInterfaceMembers(io::Printer* printer) const;
   void GenerateMembers(io::Printer* printer) const;
   void GenerateBuilderMembers(io::Printer* printer) const;
   void GenerateInitializationCode(io::Printer* printer) const;
+  void GenerateBuilderClearCode(io::Printer* printer) const;
   void GenerateMergingCode(io::Printer* printer) const;
   void GenerateBuildingCode(io::Printer* printer) const;
   void GenerateParsingCode(io::Printer* printer) const;
   void GenerateSerializationCode(io::Printer* printer) const;
   void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCode(io::Printer* printer) const;
 
   string GetBoxedType() const;
 
  private:
   const FieldDescriptor* descriptor_;
   map<string, string> variables_;
+  const int messageBitIndex_;
+  const int builderBitIndex_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator);
 };
 
 class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
  public:
-  explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor);
+  explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+      int messageBitIndex, int builderBitIndex);
   ~RepeatedPrimitiveFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
+  int GetNumBitsForMessage() const;
+  int GetNumBitsForBuilder() const;
+  void GenerateInterfaceMembers(io::Printer* printer) const;
   void GenerateMembers(io::Printer* printer) const;
   void GenerateBuilderMembers(io::Printer* printer) const;
   void GenerateInitializationCode(io::Printer* printer) const;
+  void GenerateBuilderClearCode(io::Printer* printer) const;
   void GenerateMergingCode(io::Printer* printer) const;
   void GenerateBuildingCode(io::Printer* printer) const;
   void GenerateParsingCode(io::Printer* printer) const;
   void GenerateParsingCodeFromPacked(io::Printer* printer) const;
   void GenerateSerializationCode(io::Printer* printer) const;
   void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCode(io::Printer* printer) const;
 
   string GetBoxedType() const;
 
  private:
   const FieldDescriptor* descriptor_;
   map<string, string> variables_;
+  const int messageBitIndex_;
+  const int builderBitIndex_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator);
 };
diff --git a/src/google/protobuf/compiler/java/java_service.cc b/src/google/protobuf/compiler/java/java_service.cc
index 5545bf7..1ae4f46 100644
--- a/src/google/protobuf/compiler/java/java_service.cc
+++ b/src/google/protobuf/compiler/java/java_service.cc
@@ -118,7 +118,7 @@
 
   for (int i = 0; i < descriptor_->method_count(); i++) {
     const MethodDescriptor* method = descriptor_->method(i);
-    printer->Print("@Override\n");
+    printer->Print("@java.lang.Override\n");
     GenerateMethodSignature(printer, method, IS_CONCRETE);
     printer->Print(
       " {\n"
diff --git a/src/google/protobuf/compiler/java/java_string_field.cc b/src/google/protobuf/compiler/java/java_string_field.cc
new file mode 100644
index 0000000..a93ff43
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_string_field.cc
@@ -0,0 +1,605 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Author: jonp@google.com (Jon Perlow)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/java/java_string_field.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+namespace {
+
+void SetPrimitiveVariables(const FieldDescriptor* descriptor,
+                           int messageBitIndex,
+                           int builderBitIndex,
+                           map<string, string>* variables) {
+  (*variables)["name"] =
+    UnderscoresToCamelCase(descriptor);
+  (*variables)["capitalized_name"] =
+    UnderscoresToCapitalizedCamelCase(descriptor);
+  (*variables)["constant_name"] = FieldConstantName(descriptor);
+  (*variables)["number"] = SimpleItoa(descriptor->number());
+  (*variables)["empty_list"] = "com.google.protobuf.LazyStringArrayList.EMPTY";
+
+  (*variables)["default"] = DefaultValue(descriptor);
+  (*variables)["default_init"] = ("= " + DefaultValue(descriptor));
+  (*variables)["capitalized_type"] = "String";
+  (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
+  (*variables)["tag_size"] = SimpleItoa(
+      WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
+  (*variables)["null_check"] =
+      "  if (value == null) {\n"
+      "    throw new NullPointerException();\n"
+      "  }\n";
+
+  // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
+  // by the proto compiler
+  (*variables)["deprecation"] = descriptor->options().deprecated()
+      ? "@java.lang.Deprecated " : "";
+  (*variables)["on_changed"] =
+      HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
+
+  // For singular messages and builders, one bit is used for the hasField bit.
+  (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+
+  (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
+  (*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex);
+  (*variables)["clear_has_field_bit_builder"] =
+      GenerateClearBit(builderBitIndex);
+
+  // For repated builders, one bit is used for whether the array is immutable.
+  (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
+  (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
+  (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
+
+  (*variables)["get_has_field_bit_from_local"] =
+      GenerateGetBitFromLocal(builderBitIndex);
+  (*variables)["set_has_field_bit_to_local"] =
+      GenerateSetBitToLocal(messageBitIndex);
+}
+
+}  // namespace
+
+// ===================================================================
+
+StringFieldGenerator::
+StringFieldGenerator(const FieldDescriptor* descriptor,
+                     int messageBitIndex,
+                     int builderBitIndex)
+  : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+    builderBitIndex_(builderBitIndex) {
+  SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
+                        &variables_);
+}
+
+StringFieldGenerator::~StringFieldGenerator() {}
+
+int StringFieldGenerator::GetNumBitsForMessage() const {
+  return 1;
+}
+
+int StringFieldGenerator::GetNumBitsForBuilder() const {
+  return 1;
+}
+
+// A note about how strings are handled. This code used to just store a String
+// in the Message. This had two issues:
+//
+//  1. It wouldn't roundtrip byte arrays that were not vaid UTF-8 encoded
+//     strings, but rather fields that were raw bytes incorrectly marked
+//     as strings in the proto file. This is common because in the proto1
+//     syntax, string was the way to indicate bytes and C++ engineers can
+//     easily make this mistake without affecting the C++ API. By converting to
+//     strings immediately, some java code might corrupt these byte arrays as
+//     it passes through a java server even if the field was never accessed by
+//     application code.
+//
+//  2. There's a performance hit to converting between bytes and strings and
+//     it many cases, the field is never even read by the application code. This
+//     avoids unnecessary conversions in the common use cases.
+//
+// So now, the field for String is maintained as an Object reference which can
+// either store a String or a ByteString. The code uses an instanceof check
+// to see which one it has and converts to the other one if needed. It remembers
+// the last value requested (in a thread safe manner) as this is most likely
+// the one needed next. The thread safety is such that if two threads both
+// convert the field because the changes made by each thread were not visible to
+// the other, they may cause a conversion to happen more times than would
+// otherwise be necessary. This was deemed better than adding synchronization
+// overhead. It will not cause any corruption issues or affect the behavior of
+// the API. The instanceof check is also highly optimized in the JVM and we
+// decided it was better to reduce the memory overhead by not having two
+// separate fields but rather use dynamic type checking.
+//
+// For single fields, the logic for this is done inside the generated code. For
+// repeated fields, the logic is done in LazyStringArrayList and
+// UnmodifiableLazyStringList.
+void StringFieldGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$deprecation$boolean has$capitalized_name$();\n"
+    "$deprecation$String get$capitalized_name$();\n");
+}
+
+void StringFieldGenerator::
+GenerateMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "private Object $name$_;\n"
+    "$deprecation$public boolean has$capitalized_name$() {\n"
+    "  return $get_has_field_bit_message$;\n"
+    "}\n");
+
+  printer->Print(variables_,
+    "$deprecation$public String get$capitalized_name$() {\n"
+    "  Object ref = $name$_;\n"
+    "  if (ref instanceof String) {\n"
+    "    return (String) ref;\n"
+    "  } else {\n"
+    "    com.google.protobuf.ByteString bs = \n"
+    "        (com.google.protobuf.ByteString) ref;\n"
+    "    String s = bs.toStringUtf8();\n"
+    "    if (com.google.protobuf.Internal.isValidUtf8(bs)) {\n"
+    "      $name$_ = s;\n"
+    "    }\n"
+    "    return s;\n"
+    "  }\n"
+    "}\n"
+    "private com.google.protobuf.ByteString get$capitalized_name$Bytes() {\n"
+    "  Object ref = $name$_;\n"
+    "  if (ref instanceof String) {\n"
+    "    com.google.protobuf.ByteString b = \n"
+    "        com.google.protobuf.ByteString.copyFromUtf8((String) ref);\n"
+    "    $name$_ = b;\n"
+    "    return b;\n"
+    "  } else {\n"
+    "    return (com.google.protobuf.ByteString) ref;\n"
+    "  }\n"
+    "}\n");
+}
+
+void StringFieldGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "private Object $name$_ $default_init$;\n"
+    "$deprecation$public boolean has$capitalized_name$() {\n"
+    "  return $get_has_field_bit_builder$;\n"
+    "}\n");
+
+  printer->Print(variables_,
+    "$deprecation$public String get$capitalized_name$() {\n"
+    "  Object ref = $name$_;\n"
+    "  if (!(ref instanceof String)) {\n"
+    "    String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();\n"
+    "    $name$_ = s;\n"
+    "    return s;\n"
+    "  } else {\n"
+    "    return (String) ref;\n"
+    "  }\n"
+    "}\n");
+
+  printer->Print(variables_,
+    "$deprecation$public Builder set$capitalized_name$(String value) {\n"
+    "$null_check$"
+    "  $set_has_field_bit_builder$;\n"
+    "  $name$_ = value;\n"
+    "  $on_changed$\n"
+    "  return this;\n"
+    "}\n"
+    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "  $clear_has_field_bit_builder$;\n");
+  // The default value is not a simple literal so we want to avoid executing
+  // it multiple times.  Instead, get the default out of the default instance.
+  printer->Print(variables_,
+    "  $name$_ = getDefaultInstance().get$capitalized_name$();\n");
+  printer->Print(variables_,
+    "  $on_changed$\n"
+    "  return this;\n"
+    "}\n");
+
+  printer->Print(variables_,
+    "void set$capitalized_name$(com.google.protobuf.ByteString value) {\n"
+    "  $set_has_field_bit_builder$;\n"
+    "  $name$_ = value;\n"
+    "  $on_changed$\n"
+    "}\n");
+}
+
+void StringFieldGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
+  // noop for primitives
+}
+
+void StringFieldGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_ = $default$;\n");
+}
+
+void StringFieldGenerator::
+GenerateBuilderClearCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$name$_ = $default$;\n"
+    "$clear_has_field_bit_builder$;\n");
+}
+
+void StringFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (other.has$capitalized_name$()) {\n"
+    "  set$capitalized_name$(other.get$capitalized_name$());\n"
+    "}\n");
+}
+
+void StringFieldGenerator::
+GenerateBuildingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($get_has_field_bit_from_local$) {\n"
+    "  $set_has_field_bit_to_local$;\n"
+    "}\n"
+    "result.$name$_ = $name$_;\n");
+}
+
+void StringFieldGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$set_has_field_bit_builder$;\n"
+    "$name$_ = input.readBytes();\n");
+}
+
+void StringFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($get_has_field_bit_message$) {\n"
+    "  output.writeBytes($number$, get$capitalized_name$Bytes());\n"
+    "}\n");
+}
+
+void StringFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($get_has_field_bit_message$) {\n"
+    "  size += com.google.protobuf.CodedOutputStream\n"
+    "    .computeBytesSize($number$, get$capitalized_name$Bytes());\n"
+    "}\n");
+}
+
+void StringFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "result = result && get$capitalized_name$()\n"
+    "    .equals(other.get$capitalized_name$());\n");
+}
+
+void StringFieldGenerator::
+GenerateHashCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "hash = (37 * hash) + $constant_name$;\n");
+  printer->Print(variables_,
+    "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
+}
+
+string StringFieldGenerator::GetBoxedType() const {
+  return "String";
+}
+
+
+// ===================================================================
+
+RepeatedStringFieldGenerator::
+RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
+                             int messageBitIndex,
+                             int builderBitIndex)
+  : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+    builderBitIndex_(builderBitIndex) {
+  SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
+                        &variables_);
+}
+
+RepeatedStringFieldGenerator::~RepeatedStringFieldGenerator() {}
+
+int RepeatedStringFieldGenerator::GetNumBitsForMessage() const {
+  return 0;
+}
+
+int RepeatedStringFieldGenerator::GetNumBitsForBuilder() const {
+  return 1;
+}
+
+void RepeatedStringFieldGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$deprecation$java.util.List<String> get$capitalized_name$List();\n"
+    "$deprecation$int get$capitalized_name$Count();\n"
+    "$deprecation$String get$capitalized_name$(int index);\n");
+}
+
+
+void RepeatedStringFieldGenerator::
+GenerateMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "private com.google.protobuf.LazyStringList $name$_;\n"
+    "$deprecation$public java.util.List<String>\n"
+    "    get$capitalized_name$List() {\n"
+    "  return $name$_;\n"   // note:  unmodifiable list
+    "}\n"
+    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "  return $name$_.size();\n"
+    "}\n"
+    "$deprecation$public String get$capitalized_name$(int index) {\n"
+    "  return $name$_.get(index);\n"
+    "}\n");
+
+  if (descriptor_->options().packed() &&
+      HasGeneratedMethods(descriptor_->containing_type())) {
+    printer->Print(variables_,
+      "private int $name$MemoizedSerializedSize = -1;\n");
+  }
+}
+
+void RepeatedStringFieldGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+  // One field is the list and the bit field keeps track of whether the
+  // list is immutable. If it's immutable, the invariant is that it must
+  // either an instance of Collections.emptyList() or it's an ArrayList
+  // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
+  // a refererence to the underlying ArrayList. This invariant allows us to
+  // share instances of lists between protocol buffers avoiding expensive
+  // memory allocations. Note, immutable is a strong guarantee here -- not
+  // just that the list cannot be modified via the reference but that the
+  // list can never be modified.
+  printer->Print(variables_,
+    "private com.google.protobuf.LazyStringList $name$_ = $empty_list$;\n");
+
+  printer->Print(variables_,
+    "private void ensure$capitalized_name$IsMutable() {\n"
+    "  if (!$get_mutable_bit_builder$) {\n"
+    "    $name$_ = new com.google.protobuf.LazyStringArrayList($name$_);\n"
+    "    $set_mutable_bit_builder$;\n"
+    "   }\n"
+    "}\n");
+
+    // Note:  We return an unmodifiable list because otherwise the caller
+    //   could hold on to the returned list and modify it after the message
+    //   has been built, thus mutating the message which is supposed to be
+    //   immutable.
+  printer->Print(variables_,
+    "$deprecation$public java.util.List<String>\n"
+    "    get$capitalized_name$List() {\n"
+    "  return java.util.Collections.unmodifiableList($name$_);\n"
+    "}\n"
+    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "  return $name$_.size();\n"
+    "}\n"
+    "$deprecation$public String get$capitalized_name$(int index) {\n"
+    "  return $name$_.get(index);\n"
+    "}\n"
+    "$deprecation$public Builder set$capitalized_name$(\n"
+    "    int index, String value) {\n"
+    "$null_check$"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.set(index, value);\n"
+    "  $on_changed$\n"
+    "  return this;\n"
+    "}\n"
+    "$deprecation$public Builder add$capitalized_name$(String value) {\n"
+    "$null_check$"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.add(value);\n"
+    "  $on_changed$\n"
+    "  return this;\n"
+    "}\n"
+    "$deprecation$public Builder addAll$capitalized_name$(\n"
+    "    java.lang.Iterable<String> values) {\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  super.addAll(values, $name$_);\n"
+    "  $on_changed$\n"
+    "  return this;\n"
+    "}\n"
+    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "  $name$_ = $empty_list$;\n"
+    "  $clear_mutable_bit_builder$;\n"
+    "  $on_changed$\n"
+    "  return this;\n"
+    "}\n");
+
+  printer->Print(variables_,
+    "void add$capitalized_name$(com.google.protobuf.ByteString value) {\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.add(value);\n"
+    "  $on_changed$\n"
+    "}\n");
+}
+
+void RepeatedStringFieldGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
+  // noop for primitives
+}
+
+void RepeatedStringFieldGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_ = $empty_list$;\n");
+}
+
+void RepeatedStringFieldGenerator::
+GenerateBuilderClearCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$name$_ = $empty_list$;\n"
+    "$clear_mutable_bit_builder$;\n");
+}
+
+void RepeatedStringFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  // The code below does two optimizations:
+  //   1. If the other list is empty, there's nothing to do. This ensures we
+  //      don't allocate a new array if we already have an immutable one.
+  //   2. If the other list is non-empty and our current list is empty, we can
+  //      reuse the other list which is guaranteed to be immutable.
+  printer->Print(variables_,
+    "if (!other.$name$_.isEmpty()) {\n"
+    "  if ($name$_.isEmpty()) {\n"
+    "    $name$_ = other.$name$_;\n"
+    "    $clear_mutable_bit_builder$;\n"
+    "  } else {\n"
+    "    ensure$capitalized_name$IsMutable();\n"
+    "    $name$_.addAll(other.$name$_);\n"
+    "  }\n"
+    "  $on_changed$\n"
+    "}\n");
+}
+
+void RepeatedStringFieldGenerator::
+GenerateBuildingCode(io::Printer* printer) const {
+  // The code below ensures that the result has an immutable list. If our
+  // list is immutable, we can just reuse it. If not, we make it immutable.
+
+  printer->Print(variables_,
+    "if ($get_mutable_bit_builder$) {\n"
+    "  $name$_ = new com.google.protobuf.UnmodifiableLazyStringList(\n"
+    "      $name$_);\n"
+    "  $clear_mutable_bit_builder$;\n"
+    "}\n"
+    "result.$name$_ = $name$_;\n");
+}
+
+void RepeatedStringFieldGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "ensure$capitalized_name$IsMutable();\n"
+    "$name$_.add(input.readBytes());\n");
+}
+
+void RepeatedStringFieldGenerator::
+GenerateParsingCodeFromPacked(io::Printer* printer) const {
+  printer->Print(variables_,
+    "int length = input.readRawVarint32();\n"
+    "int limit = input.pushLimit(length);\n"
+    "while (input.getBytesUntilLimit() > 0) {\n"
+    "  add$capitalized_name$(input.read$capitalized_type$());\n"
+    "}\n"
+    "input.popLimit(limit);\n");
+}
+
+void RepeatedStringFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  if (descriptor_->options().packed()) {
+    printer->Print(variables_,
+      "if (get$capitalized_name$List().size() > 0) {\n"
+      "  output.writeRawVarint32($tag$);\n"
+      "  output.writeRawVarint32($name$MemoizedSerializedSize);\n"
+      "}\n"
+      "for (int i = 0; i < $name$_.size(); i++) {\n"
+      "  output.write$capitalized_type$NoTag($name$_.get(i));\n"
+      "}\n");
+  } else {
+    printer->Print(variables_,
+      "for (int i = 0; i < $name$_.size(); i++) {\n"
+      "  output.writeBytes($number$, $name$_.getByteString(i));\n"
+      "}\n");
+  }
+}
+
+void RepeatedStringFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "{\n"
+    "  int dataSize = 0;\n");
+  printer->Indent();
+
+  printer->Print(variables_,
+    "for (int i = 0; i < $name$_.size(); i++) {\n"
+    "  dataSize += com.google.protobuf.CodedOutputStream\n"
+    "    .computeBytesSizeNoTag($name$_.getByteString(i));\n"
+    "}\n");
+
+  printer->Print(
+      "size += dataSize;\n");
+
+  if (descriptor_->options().packed()) {
+    printer->Print(variables_,
+      "if (!get$capitalized_name$List().isEmpty()) {\n"
+      "  size += $tag_size$;\n"
+      "  size += com.google.protobuf.CodedOutputStream\n"
+      "      .computeInt32SizeNoTag(dataSize);\n"
+      "}\n");
+  } else {
+    printer->Print(variables_,
+      "size += $tag_size$ * get$capitalized_name$List().size();\n");
+  }
+
+  // cache the data size for packed fields.
+  if (descriptor_->options().packed()) {
+    printer->Print(variables_,
+      "$name$MemoizedSerializedSize = dataSize;\n");
+  }
+
+  printer->Outdent();
+  printer->Print("}\n");
+}
+
+void RepeatedStringFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "result = result && get$capitalized_name$List()\n"
+    "    .equals(other.get$capitalized_name$List());\n");
+}
+
+void RepeatedStringFieldGenerator::
+GenerateHashCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (get$capitalized_name$Count() > 0) {\n"
+    "  hash = (37 * hash) + $constant_name$;\n"
+    "  hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
+    "}\n");
+}
+
+string RepeatedStringFieldGenerator::GetBoxedType() const {
+  return "String";
+}
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/java/java_string_field.h b/src/google/protobuf/compiler/java/java_string_field.h
new file mode 100644
index 0000000..8cb4146
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_string_field.h
@@ -0,0 +1,120 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Author: jonp@google.com (Jon Perlow)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class StringFieldGenerator : public FieldGenerator {
+ public:
+  explicit StringFieldGenerator(const FieldDescriptor* descriptor,
+      int messageBitIndex, int builderBitIndex);
+  ~StringFieldGenerator();
+
+  // implements FieldGenerator ---------------------------------------
+  int GetNumBitsForMessage() const;
+  int GetNumBitsForBuilder() const;
+  void GenerateInterfaceMembers(io::Printer* printer) const;
+  void GenerateMembers(io::Printer* printer) const;
+  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateInitializationCode(io::Printer* printer) const;
+  void GenerateBuilderClearCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateBuildingCode(io::Printer* printer) const;
+  void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCode(io::Printer* printer) const;
+  string GetBoxedType() const;
+
+ private:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+  const int messageBitIndex_;
+  const int builderBitIndex_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringFieldGenerator);
+};
+
+class RepeatedStringFieldGenerator : public FieldGenerator {
+ public:
+  explicit RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
+      int messageBitIndex, int builderBitIndex);
+  ~RepeatedStringFieldGenerator();
+
+  // implements FieldGenerator ---------------------------------------
+  int GetNumBitsForMessage() const;
+  int GetNumBitsForBuilder() const;
+  void GenerateInterfaceMembers(io::Printer* printer) const;
+  void GenerateMembers(io::Printer* printer) const;
+  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateInitializationCode(io::Printer* printer) const;
+  void GenerateBuilderClearCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateBuildingCode(io::Printer* printer) const;
+  void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateParsingCodeFromPacked(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCode(io::Printer* printer) const;
+  string GetBoxedType() const;
+
+ private:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+  const int messageBitIndex_;
+  const int builderBitIndex_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedStringFieldGenerator);
+};
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_H__
diff --git a/src/google/protobuf/compiler/mock_code_generator.cc b/src/google/protobuf/compiler/mock_code_generator.cc
index 83d5a4e..5b76af2 100644
--- a/src/google/protobuf/compiler/mock_code_generator.cc
+++ b/src/google/protobuf/compiler/mock_code_generator.cc
@@ -45,6 +45,16 @@
 namespace protobuf {
 namespace compiler {
 
+// Returns the list of the names of files in all_files in the form of a
+// comma-separated string.
+string CommaSeparatedList(const vector<const FileDescriptor*> all_files) {
+  vector<string> names;
+  for (int i = 0; i < all_files.size(); i++) {
+    names.push_back(all_files[i]->name());
+  }
+  return JoinStrings(names, ",");
+}
+
 static const char* kFirstInsertionPointName = "first_mock_insertion_point";
 static const char* kSecondInsertionPointName = "second_mock_insertion_point";
 static const char* kFirstInsertionPoint =
@@ -63,6 +73,7 @@
     const string& insertions,
     const string& file,
     const string& first_message_name,
+    const string& first_parsed_file_name,
     const string& output_directory) {
   string content;
   ASSERT_TRUE(File::ReadFileToString(
@@ -84,7 +95,8 @@
   }
 
   ASSERT_EQ(lines.size(), 3 + insertion_list.size() * 2);
-  EXPECT_EQ(GetOutputFileContent(name, parameter, file, first_message_name),
+  EXPECT_EQ(GetOutputFileContent(name, parameter, file,
+                                 first_parsed_file_name, first_message_name),
             lines[0]);
 
   EXPECT_EQ(kFirstInsertionPoint, lines[1 + insertion_list.size()]);
@@ -92,12 +104,12 @@
 
   for (int i = 0; i < insertion_list.size(); i++) {
     EXPECT_EQ(GetOutputFileContent(insertion_list[i], "first_insert",
-                                   file, first_message_name),
+                                   file, file, first_message_name),
               lines[1 + i]);
     // Second insertion point is indented, so the inserted text should
     // automatically be indented too.
     EXPECT_EQ("  " + GetOutputFileContent(insertion_list[i], "second_insert",
-                                          file, first_message_name),
+                                          file, file, first_message_name),
               lines[2 + insertion_list.size() + i]);
   }
 }
@@ -105,7 +117,7 @@
 bool MockCodeGenerator::Generate(
     const FileDescriptor* file,
     const string& parameter,
-    OutputDirectory* output_directory,
+    GeneratorContext* context,
     string* error) const {
   for (int i = 0; i < file->message_type_count(); i++) {
     if (HasPrefixString(file->message_type(i)->name(), "MockCodeGenerator_")) {
@@ -134,11 +146,12 @@
     for (int i = 0; i < insert_into.size(); i++) {
       {
         scoped_ptr<io::ZeroCopyOutputStream> output(
-            output_directory->OpenForInsert(
+            context->OpenForInsert(
               GetOutputFileName(insert_into[i], file),
               kFirstInsertionPointName));
         io::Printer printer(output.get(), '$');
-        printer.PrintRaw(GetOutputFileContent(name_, "first_insert", file));
+        printer.PrintRaw(GetOutputFileContent(name_, "first_insert",
+                                              file, context));
         if (printer.failed()) {
           *error = "MockCodeGenerator detected write error.";
           return false;
@@ -147,11 +160,12 @@
 
       {
         scoped_ptr<io::ZeroCopyOutputStream> output(
-            output_directory->OpenForInsert(
+            context->OpenForInsert(
               GetOutputFileName(insert_into[i], file),
               kSecondInsertionPointName));
         io::Printer printer(output.get(), '$');
-        printer.PrintRaw(GetOutputFileContent(name_, "second_insert", file));
+        printer.PrintRaw(GetOutputFileContent(name_, "second_insert",
+                                              file, context));
         if (printer.failed()) {
           *error = "MockCodeGenerator detected write error.";
           return false;
@@ -160,10 +174,11 @@
     }
   } else {
     scoped_ptr<io::ZeroCopyOutputStream> output(
-        output_directory->Open(GetOutputFileName(name_, file)));
+        context->Open(GetOutputFileName(name_, file)));
 
     io::Printer printer(output.get(), '$');
-    printer.PrintRaw(GetOutputFileContent(name_, parameter, file));
+    printer.PrintRaw(GetOutputFileContent(name_, parameter,
+                                          file, context));
     printer.PrintRaw(kFirstInsertionPoint);
     printer.PrintRaw(kSecondInsertionPoint);
 
@@ -186,11 +201,16 @@
   return file + ".MockCodeGenerator." + generator_name;
 }
 
-string MockCodeGenerator::GetOutputFileContent(const string& generator_name,
-                                               const string& parameter,
-                                               const FileDescriptor* file) {
+string MockCodeGenerator::GetOutputFileContent(
+    const string& generator_name,
+    const string& parameter,
+    const FileDescriptor* file,
+    GeneratorContext *context) {
+  vector<const FileDescriptor*> all_files;
+  context->ListParsedFiles(&all_files);
   return GetOutputFileContent(
       generator_name, parameter, file->name(),
+      CommaSeparatedList(all_files),
       file->message_type_count() > 0 ?
           file->message_type(0)->name() : "(none)");
 }
@@ -199,9 +219,11 @@
     const string& generator_name,
     const string& parameter,
     const string& file,
+    const string& parsed_file_list,
     const string& first_message_name) {
-  return strings::Substitute("$0: $1, $2, $3\n",
-      generator_name, parameter, file, first_message_name);
+  return strings::Substitute("$0: $1, $2, $3, $4\n",
+      generator_name, parameter, file,
+      first_message_name, parsed_file_list);
 }
 
 }  // namespace compiler
diff --git a/src/google/protobuf/compiler/mock_code_generator.h b/src/google/protobuf/compiler/mock_code_generator.h
index 01d69dd..5c7942b 100644
--- a/src/google/protobuf/compiler/mock_code_generator.h
+++ b/src/google/protobuf/compiler/mock_code_generator.h
@@ -69,11 +69,14 @@
   //
   // |insertions| is a comma-separated list of names of MockCodeGenerators which
   // should have inserted lines into this file.
+  // |parsed_file_list| is a comma-separated list of names of the files
+  // that are being compiled together in this run.
   static void ExpectGenerated(const string& name,
                               const string& parameter,
                               const string& insertions,
                               const string& file,
                               const string& first_message_name,
+                              const string& parsed_file_list,
                               const string& output_directory);
 
   // Get the name of the file which would be written by the given generator.
@@ -86,7 +89,7 @@
 
   virtual bool Generate(const FileDescriptor* file,
                         const string& parameter,
-                        OutputDirectory* output_directory,
+                        GeneratorContext* context,
                         string* error) const;
 
  private:
@@ -94,10 +97,12 @@
 
   static string GetOutputFileContent(const string& generator_name,
                                      const string& parameter,
-                                     const FileDescriptor* file);
+                                     const FileDescriptor* file,
+                                     GeneratorContext *context);
   static string GetOutputFileContent(const string& generator_name,
                                      const string& parameter,
                                      const string& file,
+                                     const string& parsed_file_list,
                                      const string& first_message_name);
 };
 
diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc
index 9fcb131..34317b1 100644
--- a/src/google/protobuf/compiler/parser.cc
+++ b/src/google/protobuf/compiler/parser.cc
@@ -250,20 +250,69 @@
   AddError(input_->current().line, input_->current().column, error);
 }
 
-void Parser::RecordLocation(
-    const Message* descriptor,
-    DescriptorPool::ErrorCollector::ErrorLocation location,
-    int line, int column) {
-  if (source_location_table_ != NULL) {
-    source_location_table_->Add(descriptor, location, line, column);
+// -------------------------------------------------------------------
+
+Parser::LocationRecorder::LocationRecorder(Parser* parser)
+  : parser_(parser),
+    location_(parser_->source_code_info_->add_location()) {
+  location_->add_span(parser_->input_->current().line);
+  location_->add_span(parser_->input_->current().column);
+}
+
+Parser::LocationRecorder::LocationRecorder(const LocationRecorder& parent) {
+  Init(parent);
+}
+
+Parser::LocationRecorder::LocationRecorder(const LocationRecorder& parent,
+                                           int path1) {
+  Init(parent);
+  AddPath(path1);
+}
+
+Parser::LocationRecorder::LocationRecorder(const LocationRecorder& parent,
+                                           int path1, int path2) {
+  Init(parent);
+  AddPath(path1);
+  AddPath(path2);
+}
+
+void Parser::LocationRecorder::Init(const LocationRecorder& parent) {
+  parser_ = parent.parser_;
+  location_ = parser_->source_code_info_->add_location();
+  location_->mutable_path()->CopyFrom(parent.location_->path());
+
+  location_->add_span(parser_->input_->current().line);
+  location_->add_span(parser_->input_->current().column);
+}
+
+Parser::LocationRecorder::~LocationRecorder() {
+  if (location_->span_size() <= 2) {
+    EndAt(parser_->input_->previous());
   }
 }
 
-void Parser::RecordLocation(
-    const Message* descriptor,
+void Parser::LocationRecorder::AddPath(int path_component) {
+  location_->add_path(path_component);
+}
+
+void Parser::LocationRecorder::StartAt(const io::Tokenizer::Token& token) {
+  location_->set_span(0, token.line);
+  location_->set_span(1, token.column);
+}
+
+void Parser::LocationRecorder::EndAt(const io::Tokenizer::Token& token) {
+  if (token.line != location_->span(0)) {
+    location_->add_span(token.line);
+  }
+  location_->add_span(token.end_column);
+}
+
+void Parser::LocationRecorder::RecordLegacyLocation(const Message* descriptor,
     DescriptorPool::ErrorCollector::ErrorLocation location) {
-  RecordLocation(descriptor, location,
-                 input_->current().line, input_->current().column);
+  if (parser_->source_location_table_ != NULL) {
+    parser_->source_location_table_->Add(
+        descriptor, location, location_->span(0), location_->span(1));
+  }
 }
 
 // -------------------------------------------------------------------
@@ -308,38 +357,51 @@
   had_errors_ = false;
   syntax_identifier_.clear();
 
+  // Note that |file| could be NULL at this point if
+  // stop_after_syntax_identifier_ is true.  So, we conservatively allocate
+  // SourceCodeInfo on the stack, then swap it into the FileDescriptorProto
+  // later on.
+  SourceCodeInfo source_code_info;
+  source_code_info_ = &source_code_info;
+
   if (LookingAtType(io::Tokenizer::TYPE_START)) {
     // Advance to first token.
     input_->Next();
   }
 
-  if (require_syntax_identifier_ || LookingAt("syntax")) {
-    if (!ParseSyntaxIdentifier()) {
-      // Don't attempt to parse the file if we didn't recognize the syntax
-      // identifier.
-      return false;
+  {
+    LocationRecorder root_location(this);
+
+    if (require_syntax_identifier_ || LookingAt("syntax")) {
+      if (!ParseSyntaxIdentifier()) {
+        // Don't attempt to parse the file if we didn't recognize the syntax
+        // identifier.
+        return false;
+      }
+    } else if (!stop_after_syntax_identifier_) {
+      syntax_identifier_ = "proto2";
     }
-  } else if (!stop_after_syntax_identifier_) {
-    syntax_identifier_ = "proto2";
-  }
 
-  if (stop_after_syntax_identifier_) return !had_errors_;
+    if (stop_after_syntax_identifier_) return !had_errors_;
 
-  // Repeatedly parse statements until we reach the end of the file.
-  while (!AtEnd()) {
-    if (!ParseTopLevelStatement(file)) {
-      // This statement failed to parse.  Skip it, but keep looping to parse
-      // other statements.
-      SkipStatement();
+    // Repeatedly parse statements until we reach the end of the file.
+    while (!AtEnd()) {
+      if (!ParseTopLevelStatement(file, root_location)) {
+        // This statement failed to parse.  Skip it, but keep looping to parse
+        // other statements.
+        SkipStatement();
 
-      if (LookingAt("}")) {
-        AddError("Unmatched \"}\".");
-        input_->Next();
+        if (LookingAt("}")) {
+          AddError("Unmatched \"}\".");
+          input_->Next();
+        }
       }
     }
   }
 
   input_ = NULL;
+  source_code_info_ = NULL;
+  source_code_info.Swap(file->mutable_source_code_info());
   return !had_errors_;
 }
 
@@ -363,25 +425,40 @@
   return true;
 }
 
-bool Parser::ParseTopLevelStatement(FileDescriptorProto* file) {
+bool Parser::ParseTopLevelStatement(FileDescriptorProto* file,
+                                    const LocationRecorder& root_location) {
   if (TryConsume(";")) {
     // empty statement; ignore
     return true;
   } else if (LookingAt("message")) {
-    return ParseMessageDefinition(file->add_message_type());
+    LocationRecorder location(root_location,
+      FileDescriptorProto::kMessageTypeFieldNumber, file->message_type_size());
+    return ParseMessageDefinition(file->add_message_type(), location);
   } else if (LookingAt("enum")) {
-    return ParseEnumDefinition(file->add_enum_type());
+    LocationRecorder location(root_location,
+      FileDescriptorProto::kEnumTypeFieldNumber, file->enum_type_size());
+    return ParseEnumDefinition(file->add_enum_type(), location);
   } else if (LookingAt("service")) {
-    return ParseServiceDefinition(file->add_service());
+    LocationRecorder location(root_location,
+      FileDescriptorProto::kServiceFieldNumber, file->service_size());
+    return ParseServiceDefinition(file->add_service(), location);
   } else if (LookingAt("extend")) {
+    LocationRecorder location(root_location,
+        FileDescriptorProto::kExtensionFieldNumber);
     return ParseExtend(file->mutable_extension(),
-                       file->mutable_message_type());
+                       file->mutable_message_type(),
+                       root_location,
+                       FileDescriptorProto::kMessageTypeFieldNumber,
+                       location);
   } else if (LookingAt("import")) {
-    return ParseImport(file->add_dependency());
+    int index = file->dependency_size();
+    return ParseImport(file->add_dependency(), root_location, index);
   } else if (LookingAt("package")) {
-    return ParsePackage(file);
+    return ParsePackage(file, root_location);
   } else if (LookingAt("option")) {
-    return ParseOption(file->mutable_options());
+    LocationRecorder location(root_location,
+        FileDescriptorProto::kOptionsFieldNumber);
+    return ParseOption(file->mutable_options(), location);
   } else {
     AddError("Expected top-level statement (e.g. \"message\").");
     return false;
@@ -391,15 +468,22 @@
 // -------------------------------------------------------------------
 // Messages
 
-bool Parser::ParseMessageDefinition(DescriptorProto* message) {
+bool Parser::ParseMessageDefinition(DescriptorProto* message,
+                                    const LocationRecorder& message_location) {
   DO(Consume("message"));
-  RecordLocation(message, DescriptorPool::ErrorCollector::NAME);
-  DO(ConsumeIdentifier(message->mutable_name(), "Expected message name."));
-  DO(ParseMessageBlock(message));
+  {
+    LocationRecorder location(message_location,
+                              DescriptorProto::kNameFieldNumber);
+    location.RecordLegacyLocation(
+        message, DescriptorPool::ErrorCollector::NAME);
+    DO(ConsumeIdentifier(message->mutable_name(), "Expected message name."));
+  }
+  DO(ParseMessageBlock(message, message_location));
   return true;
 }
 
-bool Parser::ParseMessageBlock(DescriptorProto* message) {
+bool Parser::ParseMessageBlock(DescriptorProto* message,
+                               const LocationRecorder& message_location) {
   DO(Consume("{"));
 
   while (!TryConsume("}")) {
@@ -408,7 +492,7 @@
       return false;
     }
 
-    if (!ParseMessageStatement(message)) {
+    if (!ParseMessageStatement(message, message_location)) {
       // This statement failed to parse.  Skip it, but keep looping to parse
       // other statements.
       SkipStatement();
@@ -418,66 +502,133 @@
   return true;
 }
 
-bool Parser::ParseMessageStatement(DescriptorProto* message) {
+bool Parser::ParseMessageStatement(DescriptorProto* message,
+                                   const LocationRecorder& message_location) {
   if (TryConsume(";")) {
     // empty statement; ignore
     return true;
   } else if (LookingAt("message")) {
-    return ParseMessageDefinition(message->add_nested_type());
+    LocationRecorder location(message_location,
+                              DescriptorProto::kNestedTypeFieldNumber,
+                              message->nested_type_size());
+    return ParseMessageDefinition(message->add_nested_type(), location);
   } else if (LookingAt("enum")) {
-    return ParseEnumDefinition(message->add_enum_type());
+    LocationRecorder location(message_location,
+                              DescriptorProto::kEnumTypeFieldNumber,
+                              message->enum_type_size());
+    return ParseEnumDefinition(message->add_enum_type(), location);
   } else if (LookingAt("extensions")) {
-    return ParseExtensions(message);
+    LocationRecorder location(message_location,
+                              DescriptorProto::kExtensionRangeFieldNumber);
+    return ParseExtensions(message, location);
   } else if (LookingAt("extend")) {
+    LocationRecorder location(message_location,
+                              DescriptorProto::kExtensionFieldNumber);
     return ParseExtend(message->mutable_extension(),
-                       message->mutable_nested_type());
+                       message->mutable_nested_type(),
+                       message_location,
+                       DescriptorProto::kNestedTypeFieldNumber,
+                       location);
   } else if (LookingAt("option")) {
-    return ParseOption(message->mutable_options());
+    LocationRecorder location(message_location,
+                              DescriptorProto::kOptionsFieldNumber);
+    return ParseOption(message->mutable_options(), location);
   } else {
+    LocationRecorder location(message_location,
+                              DescriptorProto::kFieldFieldNumber,
+                              message->field_size());
     return ParseMessageField(message->add_field(),
-                             message->mutable_nested_type());
+                             message->mutable_nested_type(),
+                             message_location,
+                             DescriptorProto::kNestedTypeFieldNumber,
+                             location);
   }
 }
 
 bool Parser::ParseMessageField(FieldDescriptorProto* field,
-                               RepeatedPtrField<DescriptorProto>* messages) {
+                               RepeatedPtrField<DescriptorProto>* messages,
+                               const LocationRecorder& parent_location,
+                               int location_field_number_for_nested_type,
+                               const LocationRecorder& field_location) {
   // Parse label and type.
-  FieldDescriptorProto::Label label;
-  DO(ParseLabel(&label));
-  field->set_label(label);
+  io::Tokenizer::Token label_token = input_->current();
+  {
+    LocationRecorder location(field_location,
+                              FieldDescriptorProto::kLabelFieldNumber);
+    FieldDescriptorProto::Label label;
+    DO(ParseLabel(&label));
+    field->set_label(label);
+  }
 
-  RecordLocation(field, DescriptorPool::ErrorCollector::TYPE);
-  FieldDescriptorProto::Type type = FieldDescriptorProto::TYPE_INT32;
-  string type_name;
-  DO(ParseType(&type, &type_name));
-  if (type_name.empty()) {
-    field->set_type(type);
-  } else {
-    field->set_type_name(type_name);
+  {
+    LocationRecorder location(field_location);  // add path later
+    location.RecordLegacyLocation(field, DescriptorPool::ErrorCollector::TYPE);
+
+    FieldDescriptorProto::Type type = FieldDescriptorProto::TYPE_INT32;
+    string type_name;
+    DO(ParseType(&type, &type_name));
+    if (type_name.empty()) {
+      location.AddPath(FieldDescriptorProto::kTypeFieldNumber);
+      field->set_type(type);
+    } else {
+      location.AddPath(FieldDescriptorProto::kTypeNameFieldNumber);
+      field->set_type_name(type_name);
+    }
   }
 
   // Parse name and '='.
-  RecordLocation(field, DescriptorPool::ErrorCollector::NAME);
   io::Tokenizer::Token name_token = input_->current();
-  DO(ConsumeIdentifier(field->mutable_name(), "Expected field name."));
+  {
+    LocationRecorder location(field_location,
+                              FieldDescriptorProto::kNameFieldNumber);
+    location.RecordLegacyLocation(field, DescriptorPool::ErrorCollector::NAME);
+    DO(ConsumeIdentifier(field->mutable_name(), "Expected field name."));
+  }
   DO(Consume("=", "Missing field number."));
 
   // Parse field number.
-  RecordLocation(field, DescriptorPool::ErrorCollector::NUMBER);
-  int number;
-  DO(ConsumeInteger(&number, "Expected field number."));
-  field->set_number(number);
+  {
+    LocationRecorder location(field_location,
+                              FieldDescriptorProto::kNumberFieldNumber);
+    location.RecordLegacyLocation(
+        field, DescriptorPool::ErrorCollector::NUMBER);
+    int number;
+    DO(ConsumeInteger(&number, "Expected field number."));
+    field->set_number(number);
+  }
 
   // Parse options.
-  DO(ParseFieldOptions(field));
+  DO(ParseFieldOptions(field, field_location));
 
   // Deal with groups.
-  if (type_name.empty() && type == FieldDescriptorProto::TYPE_GROUP) {
+  if (field->has_type() && field->type() == FieldDescriptorProto::TYPE_GROUP) {
+    // Awkward:  Since a group declares both a message type and a field, we
+    //   have to create overlapping locations.
+    LocationRecorder group_location(parent_location);
+    group_location.StartAt(label_token);
+    group_location.AddPath(location_field_number_for_nested_type);
+    group_location.AddPath(messages->size());
+
     DescriptorProto* group = messages->Add();
     group->set_name(field->name());
+
     // Record name location to match the field name's location.
-    RecordLocation(group, DescriptorPool::ErrorCollector::NAME,
-                   name_token.line, name_token.column);
+    {
+      LocationRecorder location(group_location,
+                                DescriptorProto::kNameFieldNumber);
+      location.StartAt(name_token);
+      location.EndAt(name_token);
+      location.RecordLegacyLocation(
+          group, DescriptorPool::ErrorCollector::NAME);
+    }
+
+    // The field's type_name also comes from the name.  Confusing!
+    {
+      LocationRecorder location(field_location,
+                                FieldDescriptorProto::kTypeNameFieldNumber);
+      location.StartAt(name_token);
+      location.EndAt(name_token);
+    }
 
     // As a hack for backwards-compatibility, we force the group name to start
     // with a capital letter and lower-case the field name.  New code should
@@ -490,7 +641,7 @@
 
     field->set_type_name(group->name());
     if (LookingAt("{")) {
-      DO(ParseMessageBlock(group));
+      DO(ParseMessageBlock(group, group_location));
     } else {
       AddError("Missing group body.");
       return false;
@@ -502,15 +653,23 @@
   return true;
 }
 
-bool Parser::ParseFieldOptions(FieldDescriptorProto* field) {
-  if (!TryConsume("[")) return true;
+bool Parser::ParseFieldOptions(FieldDescriptorProto* field,
+                               const LocationRecorder& field_location) {
+  if (!LookingAt("[")) return true;
+
+  LocationRecorder location(field_location,
+                            FieldDescriptorProto::kOptionsFieldNumber);
+
+  DO(Consume("["));
 
   // Parse field options.
   do {
     if (LookingAt("default")) {
-      DO(ParseDefaultAssignment(field));
+      // We intentionally pass field_location rather than location here, since
+      // the default value is not actually an option.
+      DO(ParseDefaultAssignment(field, field_location));
     } else {
-      DO(ParseOptionAssignment(field->mutable_options()));
+      DO(ParseOptionAssignment(field->mutable_options(), location));
     }
   } while (TryConsume(","));
 
@@ -518,7 +677,8 @@
   return true;
 }
 
-bool Parser::ParseDefaultAssignment(FieldDescriptorProto* field) {
+bool Parser::ParseDefaultAssignment(FieldDescriptorProto* field,
+                                    const LocationRecorder& field_location) {
   if (field->has_default_value()) {
     AddError("Already set option \"default\".");
     field->clear_default_value();
@@ -527,7 +687,10 @@
   DO(Consume("default"));
   DO(Consume("="));
 
-  RecordLocation(field, DescriptorPool::ErrorCollector::DEFAULT_VALUE);
+  LocationRecorder location(field_location,
+                            FieldDescriptorProto::kDefaultValueFieldNumber);
+  location.RecordLegacyLocation(
+      field, DescriptorPool::ErrorCollector::DEFAULT_VALUE);
   string* default_value = field->mutable_default_value();
 
   if (!field->has_type()) {
@@ -634,26 +797,35 @@
   return true;
 }
 
-bool Parser::ParseOptionNamePart(UninterpretedOption* uninterpreted_option) {
+bool Parser::ParseOptionNamePart(UninterpretedOption* uninterpreted_option,
+                                 const LocationRecorder& part_location) {
   UninterpretedOption::NamePart* name = uninterpreted_option->add_name();
   string identifier;  // We parse identifiers into this string.
   if (LookingAt("(")) {  // This is an extension.
     DO(Consume("("));
-    // An extension name consists of dot-separated identifiers, and may begin
-    // with a dot.
-    if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) {
-      DO(ConsumeIdentifier(&identifier, "Expected identifier."));
-      name->mutable_name_part()->append(identifier);
+
+    {
+      LocationRecorder location(
+          part_location, UninterpretedOption::NamePart::kNamePartFieldNumber);
+      // An extension name consists of dot-separated identifiers, and may begin
+      // with a dot.
+      if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) {
+        DO(ConsumeIdentifier(&identifier, "Expected identifier."));
+        name->mutable_name_part()->append(identifier);
+      }
+      while (LookingAt(".")) {
+        DO(Consume("."));
+        name->mutable_name_part()->append(".");
+        DO(ConsumeIdentifier(&identifier, "Expected identifier."));
+        name->mutable_name_part()->append(identifier);
+      }
     }
-    while (LookingAt(".")) {
-      DO(Consume("."));
-      name->mutable_name_part()->append(".");
-      DO(ConsumeIdentifier(&identifier, "Expected identifier."));
-      name->mutable_name_part()->append(identifier);
-    }
+
     DO(Consume(")"));
     name->set_is_extension(true);
   } else {  // This is a regular field.
+    LocationRecorder location(
+        part_location, UninterpretedOption::NamePart::kNamePartFieldNumber);
     DO(ConsumeIdentifier(&identifier, "Expected identifier."));
     name->mutable_name_part()->append(identifier);
     name->set_is_extension(false);
@@ -661,34 +833,75 @@
   return true;
 }
 
+bool Parser::ParseUninterpretedBlock(string* value) {
+  // Note that enclosing braces are not added to *value.
+  DO(Consume("{"));
+  int brace_depth = 1;
+  while (!AtEnd()) {
+    if (LookingAt("{")) {
+      brace_depth++;
+    } else if (LookingAt("}")) {
+      brace_depth--;
+      if (brace_depth == 0) {
+        input_->Next();
+        return true;
+      }
+    }
+    // TODO(sanjay): Interpret line/column numbers to preserve formatting
+    if (!value->empty()) value->push_back(' ');
+    value->append(input_->current().text);
+    input_->Next();
+  }
+  AddError("Unexpected end of stream while parsing aggregate value.");
+  return false;
+}
+
 // We don't interpret the option here. Instead we store it in an
 // UninterpretedOption, to be interpreted later.
-bool Parser::ParseOptionAssignment(Message* options) {
+bool Parser::ParseOptionAssignment(Message* options,
+                                   const LocationRecorder& options_location) {
   // Create an entry in the uninterpreted_option field.
   const FieldDescriptor* uninterpreted_option_field = options->GetDescriptor()->
       FindFieldByName("uninterpreted_option");
   GOOGLE_CHECK(uninterpreted_option_field != NULL)
       << "No field named \"uninterpreted_option\" in the Options proto.";
 
+  const Reflection* reflection = options->GetReflection();
+
+  LocationRecorder location(
+      options_location, uninterpreted_option_field->number(),
+      reflection->FieldSize(*options, uninterpreted_option_field));
+
   UninterpretedOption* uninterpreted_option = down_cast<UninterpretedOption*>(
       options->GetReflection()->AddMessage(options,
                                            uninterpreted_option_field));
 
   // Parse dot-separated name.
-  RecordLocation(uninterpreted_option,
-                 DescriptorPool::ErrorCollector::OPTION_NAME);
+  {
+    LocationRecorder name_location(location,
+                                   UninterpretedOption::kNameFieldNumber);
+    name_location.RecordLegacyLocation(
+        uninterpreted_option, DescriptorPool::ErrorCollector::OPTION_NAME);
 
-  DO(ParseOptionNamePart(uninterpreted_option));
+    {
+      LocationRecorder part_location(name_location,
+                                     uninterpreted_option->name_size());
+      DO(ParseOptionNamePart(uninterpreted_option, part_location));
+    }
 
-  while (LookingAt(".")) {
-    DO(Consume("."));
-    DO(ParseOptionNamePart(uninterpreted_option));
+    while (LookingAt(".")) {
+      DO(Consume("."));
+      LocationRecorder part_location(name_location,
+                                     uninterpreted_option->name_size());
+      DO(ParseOptionNamePart(uninterpreted_option, part_location));
+    }
   }
 
   DO(Consume("="));
 
-  RecordLocation(uninterpreted_option,
-                 DescriptorPool::ErrorCollector::OPTION_VALUE);
+  LocationRecorder value_location(location);
+  value_location.RecordLegacyLocation(
+      uninterpreted_option, DescriptorPool::ErrorCollector::OPTION_VALUE);
 
   // All values are a single token, except for negative numbers, which consist
   // of a single '-' symbol, followed by a positive number.
@@ -704,6 +917,7 @@
       return false;
 
     case io::Tokenizer::TYPE_IDENTIFIER: {
+      value_location.AddPath(UninterpretedOption::kIdentifierValueFieldNumber);
       if (is_negative) {
         AddError("Invalid '-' symbol before identifier.");
         return false;
@@ -720,15 +934,19 @@
           is_negative ? static_cast<uint64>(kint64max) + 1 : kuint64max;
       DO(ConsumeInteger64(max_value, &value, "Expected integer."));
       if (is_negative) {
-        uninterpreted_option->set_negative_int_value(
-            -static_cast<int64>(value));
+        value_location.AddPath(
+            UninterpretedOption::kNegativeIntValueFieldNumber);
+        uninterpreted_option->set_negative_int_value(-static_cast<int64>(value));
       } else {
+        value_location.AddPath(
+            UninterpretedOption::kPositiveIntValueFieldNumber);
         uninterpreted_option->set_positive_int_value(value);
       }
       break;
     }
 
     case io::Tokenizer::TYPE_FLOAT: {
+      value_location.AddPath(UninterpretedOption::kDoubleValueFieldNumber);
       double value;
       DO(ConsumeNumber(&value, "Expected number."));
       uninterpreted_option->set_double_value(is_negative ? -value : value);
@@ -736,6 +954,7 @@
     }
 
     case io::Tokenizer::TYPE_STRING: {
+      value_location.AddPath(UninterpretedOption::kStringValueFieldNumber);
       if (is_negative) {
         AddError("Invalid '-' symbol before string.");
         return false;
@@ -747,31 +966,57 @@
     }
 
     case io::Tokenizer::TYPE_SYMBOL:
-      AddError("Expected option value.");
-      return false;
+      if (LookingAt("{")) {
+        value_location.AddPath(UninterpretedOption::kAggregateValueFieldNumber);
+        DO(ParseUninterpretedBlock(
+            uninterpreted_option->mutable_aggregate_value()));
+      } else {
+        AddError("Expected option value.");
+        return false;
+      }
+      break;
   }
 
   return true;
 }
 
-bool Parser::ParseExtensions(DescriptorProto* message) {
+bool Parser::ParseExtensions(DescriptorProto* message,
+                             const LocationRecorder& extensions_location) {
   // Parse the declaration.
   DO(Consume("extensions"));
 
   do {
+    // Note that kExtensionRangeFieldNumber was already pushed by the parent.
+    LocationRecorder location(extensions_location,
+                              message->extension_range_size());
+
     DescriptorProto::ExtensionRange* range = message->add_extension_range();
-    RecordLocation(range, DescriptorPool::ErrorCollector::NUMBER);
+    location.RecordLegacyLocation(
+        range, DescriptorPool::ErrorCollector::NUMBER);
 
     int start, end;
-    DO(ConsumeInteger(&start, "Expected field number range."));
+    io::Tokenizer::Token start_token;
+
+    {
+      LocationRecorder start_location(
+          location, DescriptorProto::ExtensionRange::kStartFieldNumber);
+      start_token = input_->current();
+      DO(ConsumeInteger(&start, "Expected field number range."));
+    }
 
     if (TryConsume("to")) {
+      LocationRecorder end_location(
+          location, DescriptorProto::ExtensionRange::kEndFieldNumber);
       if (TryConsume("max")) {
         end = FieldDescriptor::kMaxNumber;
       } else {
         DO(ConsumeInteger(&end, "Expected integer."));
       }
     } else {
+      LocationRecorder end_location(
+          location, DescriptorProto::ExtensionRange::kEndFieldNumber);
+      end_location.StartAt(start_token);
+      end_location.EndAt(start_token);
       end = start;
     }
 
@@ -788,16 +1033,17 @@
 }
 
 bool Parser::ParseExtend(RepeatedPtrField<FieldDescriptorProto>* extensions,
-                         RepeatedPtrField<DescriptorProto>* messages) {
+                         RepeatedPtrField<DescriptorProto>* messages,
+                         const LocationRecorder& parent_location,
+                         int location_field_number_for_nested_type,
+                         const LocationRecorder& extend_location) {
   DO(Consume("extend"));
 
-  // We expect to see at least one extension field defined in the extend block.
-  // We need to create it now so we can record the extendee's location.
-  FieldDescriptorProto* first_field = extensions->Add();
-
   // Parse the extendee type.
-  RecordLocation(first_field, DescriptorPool::ErrorCollector::EXTENDEE);
-  DO(ParseUserDefinedType(first_field->mutable_extendee()));
+  io::Tokenizer::Token extendee_start = input_->current();
+  string extendee;
+  DO(ParseUserDefinedType(&extendee));
+  io::Tokenizer::Token extendee_end = input_->previous();
 
   // Parse the block.
   DO(Consume("{"));
@@ -810,16 +1056,29 @@
       return false;
     }
 
-    FieldDescriptorProto* field;
-    if (is_first) {
-      field = first_field;
-      is_first = false;
-    } else {
-      field = extensions->Add();
-      field->set_extendee(first_field->extendee());
+    // Note that kExtensionFieldNumber was already pushed by the parent.
+    LocationRecorder location(extend_location, extensions->size());
+
+    FieldDescriptorProto* field = extensions->Add();
+
+    {
+      LocationRecorder extendee_location(
+          location, FieldDescriptorProto::kExtendeeFieldNumber);
+      extendee_location.StartAt(extendee_start);
+      extendee_location.EndAt(extendee_end);
+
+      if (is_first) {
+        extendee_location.RecordLegacyLocation(
+            field, DescriptorPool::ErrorCollector::EXTENDEE);
+        is_first = false;
+      }
     }
 
-    if (!ParseMessageField(field, messages)) {
+    field->set_extendee(extendee);
+
+    if (!ParseMessageField(field, messages, parent_location,
+                           location_field_number_for_nested_type,
+                           location)) {
       // This statement failed to parse.  Skip it, but keep looping to parse
       // other statements.
       SkipStatement();
@@ -832,15 +1091,24 @@
 // -------------------------------------------------------------------
 // Enums
 
-bool Parser::ParseEnumDefinition(EnumDescriptorProto* enum_type) {
+bool Parser::ParseEnumDefinition(EnumDescriptorProto* enum_type,
+                                 const LocationRecorder& enum_location) {
   DO(Consume("enum"));
-  RecordLocation(enum_type, DescriptorPool::ErrorCollector::NAME);
-  DO(ConsumeIdentifier(enum_type->mutable_name(), "Expected enum name."));
-  DO(ParseEnumBlock(enum_type));
+
+  {
+    LocationRecorder location(enum_location,
+                              EnumDescriptorProto::kNameFieldNumber);
+    location.RecordLegacyLocation(
+        enum_type, DescriptorPool::ErrorCollector::NAME);
+    DO(ConsumeIdentifier(enum_type->mutable_name(), "Expected enum name."));
+  }
+
+  DO(ParseEnumBlock(enum_type, enum_location));
   return true;
 }
 
-bool Parser::ParseEnumBlock(EnumDescriptorProto* enum_type) {
+bool Parser::ParseEnumBlock(EnumDescriptorProto* enum_type,
+                            const LocationRecorder& enum_location) {
   DO(Consume("{"));
 
   while (!TryConsume("}")) {
@@ -849,7 +1117,7 @@
       return false;
     }
 
-    if (!ParseEnumStatement(enum_type)) {
+    if (!ParseEnumStatement(enum_type, enum_location)) {
       // This statement failed to parse.  Skip it, but keep looping to parse
       // other statements.
       SkipStatement();
@@ -859,41 +1127,69 @@
   return true;
 }
 
-bool Parser::ParseEnumStatement(EnumDescriptorProto* enum_type) {
+bool Parser::ParseEnumStatement(EnumDescriptorProto* enum_type,
+                                const LocationRecorder& enum_location) {
   if (TryConsume(";")) {
     // empty statement; ignore
     return true;
   } else if (LookingAt("option")) {
-    return ParseOption(enum_type->mutable_options());
+    LocationRecorder location(enum_location,
+                              EnumDescriptorProto::kOptionsFieldNumber);
+    return ParseOption(enum_type->mutable_options(), location);
   } else {
-    return ParseEnumConstant(enum_type->add_value());
+    LocationRecorder location(enum_location,
+        EnumDescriptorProto::kValueFieldNumber, enum_type->value_size());
+    return ParseEnumConstant(enum_type->add_value(), location);
   }
 }
 
-bool Parser::ParseEnumConstant(EnumValueDescriptorProto* enum_value) {
-  RecordLocation(enum_value, DescriptorPool::ErrorCollector::NAME);
-  DO(ConsumeIdentifier(enum_value->mutable_name(),
-                       "Expected enum constant name."));
+bool Parser::ParseEnumConstant(EnumValueDescriptorProto* enum_value,
+                               const LocationRecorder& enum_value_location) {
+  // Parse name.
+  {
+    LocationRecorder location(enum_value_location,
+                              EnumValueDescriptorProto::kNameFieldNumber);
+    location.RecordLegacyLocation(
+        enum_value, DescriptorPool::ErrorCollector::NAME);
+    DO(ConsumeIdentifier(enum_value->mutable_name(),
+                         "Expected enum constant name."));
+  }
+
   DO(Consume("=", "Missing numeric value for enum constant."));
 
-  bool is_negative = TryConsume("-");
-  int number;
-  DO(ConsumeInteger(&number, "Expected integer."));
-  if (is_negative) number *= -1;
-  enum_value->set_number(number);
+  // Parse value.
+  {
+    LocationRecorder location(
+        enum_value_location, EnumValueDescriptorProto::kNumberFieldNumber);
+    location.RecordLegacyLocation(
+        enum_value, DescriptorPool::ErrorCollector::NUMBER);
 
-  DO(ParseEnumConstantOptions(enum_value));
+    bool is_negative = TryConsume("-");
+    int number;
+    DO(ConsumeInteger(&number, "Expected integer."));
+    if (is_negative) number *= -1;
+    enum_value->set_number(number);
+  }
+
+  DO(ParseEnumConstantOptions(enum_value, enum_value_location));
 
   DO(Consume(";"));
 
   return true;
 }
 
-bool Parser::ParseEnumConstantOptions(EnumValueDescriptorProto* value) {
-  if (!TryConsume("[")) return true;
+bool Parser::ParseEnumConstantOptions(
+    EnumValueDescriptorProto* value,
+    const LocationRecorder& enum_value_location) {
+  if (!LookingAt("[")) return true;
+
+  LocationRecorder location(
+      enum_value_location, EnumValueDescriptorProto::kOptionsFieldNumber);
+
+  DO(Consume("["));
 
   do {
-    DO(ParseOptionAssignment(value->mutable_options()));
+    DO(ParseOptionAssignment(value->mutable_options(), location));
   } while (TryConsume(","));
 
   DO(Consume("]"));
@@ -903,15 +1199,24 @@
 // -------------------------------------------------------------------
 // Services
 
-bool Parser::ParseServiceDefinition(ServiceDescriptorProto* service) {
+bool Parser::ParseServiceDefinition(ServiceDescriptorProto* service,
+                                    const LocationRecorder& service_location) {
   DO(Consume("service"));
-  RecordLocation(service, DescriptorPool::ErrorCollector::NAME);
-  DO(ConsumeIdentifier(service->mutable_name(), "Expected service name."));
-  DO(ParseServiceBlock(service));
+
+  {
+    LocationRecorder location(service_location,
+                              ServiceDescriptorProto::kNameFieldNumber);
+    location.RecordLegacyLocation(
+        service, DescriptorPool::ErrorCollector::NAME);
+    DO(ConsumeIdentifier(service->mutable_name(), "Expected service name."));
+  }
+
+  DO(ParseServiceBlock(service, service_location));
   return true;
 }
 
-bool Parser::ParseServiceBlock(ServiceDescriptorProto* service) {
+bool Parser::ParseServiceBlock(ServiceDescriptorProto* service,
+                               const LocationRecorder& service_location) {
   DO(Consume("{"));
 
   while (!TryConsume("}")) {
@@ -920,7 +1225,7 @@
       return false;
     }
 
-    if (!ParseServiceStatement(service)) {
+    if (!ParseServiceStatement(service, service_location)) {
       // This statement failed to parse.  Skip it, but keep looping to parse
       // other statements.
       SkipStatement();
@@ -930,33 +1235,55 @@
   return true;
 }
 
-bool Parser::ParseServiceStatement(ServiceDescriptorProto* service) {
+bool Parser::ParseServiceStatement(ServiceDescriptorProto* service,
+                                   const LocationRecorder& service_location) {
   if (TryConsume(";")) {
     // empty statement; ignore
     return true;
   } else if (LookingAt("option")) {
-    return ParseOption(service->mutable_options());
+    LocationRecorder location(
+        service_location, ServiceDescriptorProto::kOptionsFieldNumber);
+    return ParseOption(service->mutable_options(), location);
   } else {
-    return ParseServiceMethod(service->add_method());
+    LocationRecorder location(service_location,
+        ServiceDescriptorProto::kMethodFieldNumber, service->method_size());
+    return ParseServiceMethod(service->add_method(), location);
   }
 }
 
-bool Parser::ParseServiceMethod(MethodDescriptorProto* method) {
+bool Parser::ParseServiceMethod(MethodDescriptorProto* method,
+                                const LocationRecorder& method_location) {
   DO(Consume("rpc"));
-  RecordLocation(method, DescriptorPool::ErrorCollector::NAME);
-  DO(ConsumeIdentifier(method->mutable_name(), "Expected method name."));
+
+  {
+    LocationRecorder location(method_location,
+                              MethodDescriptorProto::kNameFieldNumber);
+    location.RecordLegacyLocation(
+        method, DescriptorPool::ErrorCollector::NAME);
+    DO(ConsumeIdentifier(method->mutable_name(), "Expected method name."));
+  }
 
   // Parse input type.
   DO(Consume("("));
-  RecordLocation(method, DescriptorPool::ErrorCollector::INPUT_TYPE);
-  DO(ParseUserDefinedType(method->mutable_input_type()));
+  {
+    LocationRecorder location(method_location,
+                              MethodDescriptorProto::kInputTypeFieldNumber);
+    location.RecordLegacyLocation(
+        method, DescriptorPool::ErrorCollector::INPUT_TYPE);
+    DO(ParseUserDefinedType(method->mutable_input_type()));
+  }
   DO(Consume(")"));
 
   // Parse output type.
   DO(Consume("returns"));
   DO(Consume("("));
-  RecordLocation(method, DescriptorPool::ErrorCollector::OUTPUT_TYPE);
-  DO(ParseUserDefinedType(method->mutable_output_type()));
+  {
+    LocationRecorder location(method_location,
+                              MethodDescriptorProto::kOutputTypeFieldNumber);
+    location.RecordLegacyLocation(
+        method, DescriptorPool::ErrorCollector::OUTPUT_TYPE);
+    DO(ParseUserDefinedType(method->mutable_output_type()));
+  }
   DO(Consume(")"));
 
   if (TryConsume("{")) {
@@ -970,7 +1297,9 @@
       if (TryConsume(";")) {
         // empty statement; ignore
       } else {
-        if (!ParseOption(method->mutable_options())) {
+        LocationRecorder location(method_location,
+                                  MethodDescriptorProto::kOptionsFieldNumber);
+        if (!ParseOption(method->mutable_options(), location)) {
           // This statement failed to parse.  Skip it, but keep looping to
           // parse other statements.
           SkipStatement();
@@ -1054,7 +1383,8 @@
 
 // ===================================================================
 
-bool Parser::ParsePackage(FileDescriptorProto* file) {
+bool Parser::ParsePackage(FileDescriptorProto* file,
+                          const LocationRecorder& root_location) {
   if (file->has_package()) {
     AddError("Multiple package definitions.");
     // Don't append the new package to the old one.  Just replace it.  Not
@@ -1064,31 +1394,43 @@
 
   DO(Consume("package"));
 
-  RecordLocation(file, DescriptorPool::ErrorCollector::NAME);
+  {
+    LocationRecorder location(root_location,
+                              FileDescriptorProto::kPackageFieldNumber);
+    location.RecordLegacyLocation(file, DescriptorPool::ErrorCollector::NAME);
 
-  while (true) {
-    string identifier;
-    DO(ConsumeIdentifier(&identifier, "Expected identifier."));
-    file->mutable_package()->append(identifier);
-    if (!TryConsume(".")) break;
-    file->mutable_package()->append(".");
+    while (true) {
+      string identifier;
+      DO(ConsumeIdentifier(&identifier, "Expected identifier."));
+      file->mutable_package()->append(identifier);
+      if (!TryConsume(".")) break;
+      file->mutable_package()->append(".");
+    }
   }
 
   DO(Consume(";"));
   return true;
 }
 
-bool Parser::ParseImport(string* import_filename) {
+bool Parser::ParseImport(string* import_filename,
+                         const LocationRecorder& root_location,
+                         int index) {
   DO(Consume("import"));
-  DO(ConsumeString(import_filename,
-    "Expected a string naming the file to import."));
+  {
+    LocationRecorder location(root_location,
+                              FileDescriptorProto::kDependencyFieldNumber,
+                              index);
+    DO(ConsumeString(import_filename,
+      "Expected a string naming the file to import."));
+  }
   DO(Consume(";"));
   return true;
 }
 
-bool Parser::ParseOption(Message* options) {
+bool Parser::ParseOption(Message* options,
+                         const LocationRecorder& options_location) {
   DO(Consume("option"));
-  DO(ParseOptionAssignment(options));
+  DO(ParseOptionAssignment(options, options_location));
   DO(Consume(";"));
   return true;
 }
diff --git a/src/google/protobuf/compiler/parser.h b/src/google/protobuf/compiler/parser.h
index 72c96d0..4cc90a2 100644
--- a/src/google/protobuf/compiler/parser.h
+++ b/src/google/protobuf/compiler/parser.h
@@ -74,6 +74,9 @@
 
   // Optional fetaures:
 
+  // DEPRECATED:  New code should use the SourceCodeInfo embedded in the
+  //   FileDescriptorProto.
+  //
   // Requests that locations of certain definitions be recorded to the given
   // SourceLocationTable while parsing.  This can be used to look up exact line
   // and column numbers for errors reported by DescriptorPool during validation.
@@ -82,7 +85,7 @@
     source_location_table_ = location_table;
   }
 
-  // Requsets that errors be recorded to the given ErrorCollector while
+  // Requests that errors be recorded to the given ErrorCollector while
   // parsing.  Set to NULL (the default) to discard error messages.
   void RecordErrorsTo(io::ErrorCollector* error_collector) {
     error_collector_ = error_collector;
@@ -180,16 +183,56 @@
   // of the current token.
   void AddError(const string& error);
 
-  // Record the given line and column and associate it with this descriptor
-  // in the SourceLocationTable.
-  void RecordLocation(const Message* descriptor,
-                      DescriptorPool::ErrorCollector::ErrorLocation location,
-                      int line, int column);
+  // Records a location in the SourceCodeInfo.location table (see
+  // descriptor.proto).  We use RAII to ensure that the start and end locations
+  // are recorded -- the constructor records the start location and the
+  // destructor records the end location.  Since the parser is
+  // recursive-descent, this works out beautifully.
+  class LIBPROTOBUF_EXPORT LocationRecorder {
+   public:
+    // Construct the file's "root" location.
+    LocationRecorder(Parser* parser);
 
-  // Record the current line and column and associate it with this descriptor
-  // in the SourceLocationTable.
-  void RecordLocation(const Message* descriptor,
-                      DescriptorPool::ErrorCollector::ErrorLocation location);
+    // Construct a location that represents a declaration nested within the
+    // given parent.  E.g. a field's location is nested within the location
+    // for a message type.  The parent's path will be copied, so you should
+    // call AddPath() only to add the path components leading from the parent
+    // to the child (as opposed to leading from the root to the child).
+    LocationRecorder(const LocationRecorder& parent);
+
+    // Convenience constructors that call AddPath() one or two times.
+    LocationRecorder(const LocationRecorder& parent, int path1);
+    LocationRecorder(const LocationRecorder& parent, int path1, int path2);
+
+    ~LocationRecorder();
+
+    // Add a path component.  See SourceCodeInfo.Location.path in
+    // descriptor.proto.
+    void AddPath(int path_component);
+
+    // By default the location is considered to start at the current token at
+    // the time the LocationRecorder is created.  StartAt() sets the start
+    // location to the given token instead.
+    void StartAt(const io::Tokenizer::Token& token);
+
+    // By default the location is considered to end at the previous token at
+    // the time the LocationRecorder is destroyed.  EndAt() sets the end
+    // location to the given token instead.
+    void EndAt(const io::Tokenizer::Token& token);
+
+    // Records the start point of this location to the SourceLocationTable that
+    // was passed to RecordSourceLocationsTo(), if any.  SourceLocationTable
+    // is an older way of keeping track of source locations which is still
+    // used in some places.
+    void RecordLegacyLocation(const Message* descriptor,
+        DescriptorPool::ErrorCollector::ErrorLocation location);
+
+   private:
+    Parser* parser_;
+    SourceCodeInfo::Location* location_;
+
+    void Init(const LocationRecorder& parent);
+  };
 
   // =================================================================
   // Parsers for various language constructs
@@ -210,50 +253,81 @@
   // makes logic much simpler for the caller.
 
   // Parse a top-level message, enum, service, etc.
-  bool ParseTopLevelStatement(FileDescriptorProto* file);
+  bool ParseTopLevelStatement(FileDescriptorProto* file,
+                              const LocationRecorder& root_location);
 
   // Parse various language high-level language construrcts.
-  bool ParseMessageDefinition(DescriptorProto* message);
-  bool ParseEnumDefinition(EnumDescriptorProto* enum_type);
-  bool ParseServiceDefinition(ServiceDescriptorProto* service);
-  bool ParsePackage(FileDescriptorProto* file);
-  bool ParseImport(string* import_filename);
-  bool ParseOption(Message* options);
+  bool ParseMessageDefinition(DescriptorProto* message,
+                              const LocationRecorder& message_location);
+  bool ParseEnumDefinition(EnumDescriptorProto* enum_type,
+                           const LocationRecorder& enum_location);
+  bool ParseServiceDefinition(ServiceDescriptorProto* service,
+                              const LocationRecorder& service_location);
+  bool ParsePackage(FileDescriptorProto* file,
+                    const LocationRecorder& root_location);
+  bool ParseImport(string* import_filename,
+                   const LocationRecorder& root_location,
+                   int index);
+  bool ParseOption(Message* options,
+                   const LocationRecorder& options_location);
 
   // These methods parse the contents of a message, enum, or service type and
   // add them to the given object.  They consume the entire block including
   // the beginning and ending brace.
-  bool ParseMessageBlock(DescriptorProto* message);
-  bool ParseEnumBlock(EnumDescriptorProto* enum_type);
-  bool ParseServiceBlock(ServiceDescriptorProto* service);
+  bool ParseMessageBlock(DescriptorProto* message,
+                         const LocationRecorder& message_location);
+  bool ParseEnumBlock(EnumDescriptorProto* enum_type,
+                      const LocationRecorder& enum_location);
+  bool ParseServiceBlock(ServiceDescriptorProto* service,
+                         const LocationRecorder& service_location);
 
   // Parse one statement within a message, enum, or service block, inclunding
   // final semicolon.
-  bool ParseMessageStatement(DescriptorProto* message);
-  bool ParseEnumStatement(EnumDescriptorProto* message);
-  bool ParseServiceStatement(ServiceDescriptorProto* message);
+  bool ParseMessageStatement(DescriptorProto* message,
+                             const LocationRecorder& message_location);
+  bool ParseEnumStatement(EnumDescriptorProto* message,
+                          const LocationRecorder& enum_location);
+  bool ParseServiceStatement(ServiceDescriptorProto* message,
+                             const LocationRecorder& service_location);
 
   // Parse a field of a message.  If the field is a group, its type will be
   // added to "messages".
+  //
+  // parent_location and location_field_number_for_nested_type are needed when
+  // parsing groups -- we need to generate a nested message type within the
+  // parent and record its location accordingly.  Since the parent could be
+  // either a FileDescriptorProto or a DescriptorProto, we must pass in the
+  // correct field number to use.
   bool ParseMessageField(FieldDescriptorProto* field,
-                         RepeatedPtrField<DescriptorProto>* messages);
+                         RepeatedPtrField<DescriptorProto>* messages,
+                         const LocationRecorder& parent_location,
+                         int location_field_number_for_nested_type,
+                         const LocationRecorder& field_location);
 
   // Parse an "extensions" declaration.
-  bool ParseExtensions(DescriptorProto* message);
+  bool ParseExtensions(DescriptorProto* message,
+                       const LocationRecorder& extensions_location);
 
-  // Parse an "extend" declaration.
+  // Parse an "extend" declaration.  (See also comments for
+  // ParseMessageField().)
   bool ParseExtend(RepeatedPtrField<FieldDescriptorProto>* extensions,
-                   RepeatedPtrField<DescriptorProto>* messages);
+                   RepeatedPtrField<DescriptorProto>* messages,
+                   const LocationRecorder& parent_location,
+                   int location_field_number_for_nested_type,
+                   const LocationRecorder& extend_location);
 
   // Parse a single enum value within an enum block.
-  bool ParseEnumConstant(EnumValueDescriptorProto* enum_value);
+  bool ParseEnumConstant(EnumValueDescriptorProto* enum_value,
+                         const LocationRecorder& enum_value_location);
 
   // Parse enum constant options, i.e. the list in square brackets at the end
   // of the enum constant value definition.
-  bool ParseEnumConstantOptions(EnumValueDescriptorProto* value);
+  bool ParseEnumConstantOptions(EnumValueDescriptorProto* value,
+                                const LocationRecorder& enum_value_location);
 
   // Parse a single method within a service definition.
-  bool ParseServiceMethod(MethodDescriptorProto* method);
+  bool ParseServiceMethod(MethodDescriptorProto* method,
+                          const LocationRecorder& method_location);
 
   // Parse "required", "optional", or "repeated" and fill in "label"
   // with the value.
@@ -269,28 +343,45 @@
 
   // Parses field options, i.e. the stuff in square brackets at the end
   // of a field definition.  Also parses default value.
-  bool ParseFieldOptions(FieldDescriptorProto* field);
+  bool ParseFieldOptions(FieldDescriptorProto* field,
+                         const LocationRecorder& field_location);
 
   // Parse the "default" option.  This needs special handling because its
   // type is the field's type.
-  bool ParseDefaultAssignment(FieldDescriptorProto* field);
+  bool ParseDefaultAssignment(FieldDescriptorProto* field,
+                              const LocationRecorder& field_location);
 
   // Parse a single option name/value pair, e.g. "ctype = CORD".  The name
   // identifies a field of the given Message, and the value of that field
   // is set to the parsed value.
-  bool ParseOptionAssignment(Message* options);
+  bool ParseOptionAssignment(Message* options,
+                             const LocationRecorder& options_location);
 
   // Parses a single part of a multipart option name. A multipart name consists
   // of names separated by dots. Each name is either an identifier or a series
   // of identifiers separated by dots and enclosed in parentheses. E.g.,
   // "foo.(bar.baz).qux".
-  bool ParseOptionNamePart(UninterpretedOption* uninterpreted_option);
+  bool ParseOptionNamePart(UninterpretedOption* uninterpreted_option,
+                           const LocationRecorder& part_location);
+
+  // Parses a string surrounded by balanced braces.  Strips off the outer
+  // braces and stores the enclosed string in *value.
+  // E.g.,
+  //     { foo }                     *value gets 'foo'
+  //     { foo { bar: box } }        *value gets 'foo { bar: box }'
+  //     {}                          *value gets ''
+  //
+  // REQUIRES: LookingAt("{")
+  // When finished successfully, we are looking at the first token past
+  // the ending brace.
+  bool ParseUninterpretedBlock(string* value);
 
   // =================================================================
 
   io::Tokenizer* input_;
   io::ErrorCollector* error_collector_;
-  SourceLocationTable* source_location_table_;
+  SourceCodeInfo* source_code_info_;
+  SourceLocationTable* source_location_table_;  // legacy
   bool had_errors_;
   bool require_syntax_identifier_;
   bool stop_after_syntax_identifier_;
@@ -302,6 +393,11 @@
 // A table mapping (descriptor, ErrorLocation) pairs -- as reported by
 // DescriptorPool when validating descriptors -- to line and column numbers
 // within the original source code.
+//
+// This is semi-obsolete:  FileDescriptorProto.source_code_info now contains
+// far more complete information about source locations.  However, as of this
+// writing you still need to use SourceLocationTable when integrating with
+// DescriptorPool.
 class LIBPROTOBUF_EXPORT SourceLocationTable {
  public:
   SourceLocationTable();
diff --git a/src/google/protobuf/compiler/parser_unittest.cc b/src/google/protobuf/compiler/parser_unittest.cc
index e2262b8..156c0dc 100644
--- a/src/google/protobuf/compiler/parser_unittest.cc
+++ b/src/google/protobuf/compiler/parser_unittest.cc
@@ -34,6 +34,7 @@
 
 #include <vector>
 #include <algorithm>
+#include <map>
 
 #include <google/protobuf/compiler/parser.h>
 
@@ -45,6 +46,7 @@
 #include <google/protobuf/unittest.pb.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/substitute.h>
+#include <google/protobuf/stubs/map-util.h>
 
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
@@ -118,6 +120,9 @@
     EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
     ASSERT_EQ("", error_collector_.text_);
 
+    // We don't cover SourceCodeInfo in these tests.
+    actual.clear_source_code_info();
+
     // Parse the ASCII representation in order to canonicalize it.  We could
     // just compare directly to actual.DebugString(), but that would require
     // that the caller precisely match the formatting that DebugString()
@@ -930,6 +935,12 @@
     "3:25: Expected \";\".\n");
 }
 
+TEST_F(ParseErrorTest, EofInAggregateValue) {
+  ExpectHasErrors(
+      "option (fileopt) = { i:100\n",
+      "1:0: Unexpected end of stream while parsing aggregate value.\n");
+}
+
 // -------------------------------------------------------------------
 // Enum errors
 
@@ -1248,6 +1259,861 @@
 }
 
 // ===================================================================
+// SourceCodeInfo tests.
+
+// Follows a path -- as defined by SourceCodeInfo.Location.path -- from a
+// message to a particular sub-field.
+// * If the target is itself a message, sets *output_message to point at it,
+//   *output_field to NULL, and *output_index to -1.
+// * Otherwise, if the target is an element of a repeated field, sets
+//   *output_message to the containing message, *output_field to the descriptor
+//   of the field, and *output_index to the index of the element.
+// * Otherwise, the target is a field (possibly a repeated field, but not any
+//   one element).  Sets *output_message to the containing message,
+//   *output_field to the descriptor of the field, and *output_index to -1.
+// Returns true if the path was valid, false otherwise.  A gTest failure is
+// recorded before returning false.
+bool FollowPath(const Message& root,
+                const int* path_begin, const int* path_end,
+                const Message** output_message,
+                const FieldDescriptor** output_field,
+                int* output_index) {
+  if (path_begin == path_end) {
+    // Path refers to this whole message.
+    *output_message = &root;
+    *output_field = NULL;
+    *output_index = -1;
+    return true;
+  }
+
+  const Descriptor* descriptor = root.GetDescriptor();
+  const Reflection* reflection = root.GetReflection();
+
+  const FieldDescriptor* field = descriptor->FindFieldByNumber(*path_begin);
+
+  if (field == NULL) {
+    ADD_FAILURE() << descriptor->name() << " has no field number: "
+                  << *path_begin;
+    return false;
+  }
+
+  ++path_begin;
+
+  if (field->is_repeated()) {
+    if (path_begin == path_end) {
+      // Path refers to the whole repeated field.
+      *output_message = &root;
+      *output_field = field;
+      *output_index = -1;
+      return true;
+    }
+
+    int index = *path_begin++;
+    int size = reflection->FieldSize(root, field);
+
+    if (index >= size) {
+      ADD_FAILURE() << descriptor->name() << "." << field->name()
+                    << " has size " << size << ", but path contained index: "
+                    << index;
+      return false;
+    }
+
+    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      // Descend into child message.
+      const Message& child = reflection->GetRepeatedMessage(root, field, index);
+      return FollowPath(child, path_begin, path_end,
+                        output_message, output_field, output_index);
+    } else if (path_begin == path_end) {
+      // Path refers to this element.
+      *output_message = &root;
+      *output_field = field;
+      *output_index = index;
+      return true;
+    } else {
+      ADD_FAILURE() << descriptor->name() << "." << field->name()
+                    << " is not a message; cannot descend into it.";
+      return false;
+    }
+  } else {
+    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      const Message& child = reflection->GetMessage(root, field);
+      return FollowPath(child, path_begin, path_end,
+                        output_message, output_field, output_index);
+    } else if (path_begin == path_end) {
+      // Path refers to this field.
+      *output_message = &root;
+      *output_field = field;
+      *output_index = -1;
+      return true;
+    } else {
+      ADD_FAILURE() << descriptor->name() << "." << field->name()
+                    << " is not a message; cannot descend into it.";
+      return false;
+    }
+  }
+}
+
+// Split some text on line breaks.  The line breaks are retained in the output,
+// so each line (except the last) ends with a '\n', and the lines can be
+// concatenated to produce the original text.
+//
+// I couldn't find the proper string utility function for this.  Our
+// split-on-delimiter functions don't include the delimiter in the output.
+void SplitLines(const string& text, vector<string>* lines) {
+  string::size_type pos = 0;
+
+  while (pos != string::npos) {
+    string::size_type last_pos = pos;
+    pos = text.find_first_of('\n', pos);
+    if (pos != string::npos) ++pos;
+    lines->push_back(text.substr(last_pos, pos - last_pos));
+  }
+}
+
+// Look for the given tags in the given text and construct a span (as defined
+// by SourceCodeInfo.Location.span) from them.  E.g. for text like:
+//   /*a*/message /*b*/Foo/*c*/ {}/*d*/
+// There are four tags:  "a", "b", "c", and "d".  The constructed span starts
+// immediately after the start tag's trailing '/' and ends immediately before
+// the end tags leading '/'.
+void MakeExpectedSpan(const vector<string>& lines,
+                      const string& start_tag, const string& end_tag,
+                      RepeatedField<int>* output) {
+  string start_comment = "/*" + start_tag + "*/";
+  string end_comment = "/*" + end_tag + "*/";
+
+  int start_line = -1;
+  int start_column = -1;
+  for (int i = 0; i < lines.size(); i++) {
+    string::size_type pos = lines[i].find(start_comment);
+    if (pos != string::npos) {
+      start_line = i;
+      start_column = pos + start_comment.size();
+      break;
+    }
+  }
+  ASSERT_NE(start_line, -1)
+      << "Tag \"" << start_comment << "\" not found in text.";
+
+  int end_line = -1;
+  int end_column = -1;
+  for (int i = start_line; i < lines.size(); i++) {
+    string::size_type pos = lines[i].find(end_comment);
+    if (pos != string::npos) {
+      end_line = i;
+      end_column = pos;
+      break;
+    }
+  }
+  ASSERT_NE(end_line, -1)
+      << "Tag \"" << end_comment << "\" not found in text.";
+
+  output->Add(start_line);
+  output->Add(start_column);
+  if (end_line != start_line) output->Add(end_line);
+  output->Add(end_column);
+}
+
+// Check if two spans are equal.
+bool CompareSpans(const RepeatedField<int>& span1,
+                  const RepeatedField<int>& span2) {
+  if (span1.size() != span2.size()) return false;
+  for (int i = 0; i < span1.size(); i++) {
+    if (span1.Get(i) != span2.Get(i)) return false;
+  }
+  return true;
+}
+
+// Test fixture for source info tests, which check that source locations are
+// recorded correctly in FileDescriptorProto.source_code_info.location.
+class SourceInfoTest : public ParserTest {
+ protected:
+  // The parsed file (initialized by Parse()).
+  FileDescriptorProto file_;
+
+  // Parse the given text as a .proto file and populate the spans_ map with
+  // all the source location spans in its SourceCodeInfo table.
+  bool Parse(const char* text) {
+    SetupParser(text);
+    SplitLines(text, &lines_);
+    if (!parser_->Parse(input_.get(), &file_)) {
+      return false;
+    }
+
+    const SourceCodeInfo& source_info = file_.source_code_info();
+    for (int i = 0; i < source_info.location_size(); i++) {
+      const SourceCodeInfo::Location& location = source_info.location(i);
+      const Message* descriptor_proto = NULL;
+      const FieldDescriptor* field = NULL;
+      int index = 0;
+      if (!FollowPath(file_, location.path().begin(), location.path().end(),
+                      &descriptor_proto, &field, &index)) {
+        return false;
+      }
+
+      spans_.insert(make_pair(SpanKey(*descriptor_proto, field, index),
+                              &location));
+    }
+
+    return true;
+  }
+
+  virtual void TearDown() {
+    EXPECT_TRUE(spans_.empty())
+        << "Forgot to call HasSpan() for:\n"
+        << spans_.begin()->second->DebugString();
+  }
+
+  // -----------------------------------------------------------------
+  // HasSpan() checks that the span of source code delimited by the given
+  // tags (comments) correspond via the SourceCodeInfo table to the given
+  // part of the FileDescriptorProto.  (If unclear, look at the actual tests;
+  // it should quickly become obvious.)
+
+  bool HasSpan(const char* start_tag, const char* end_tag,
+               const Message& descriptor_proto) {
+    return HasSpan(start_tag, end_tag, descriptor_proto, NULL, -1);
+  }
+
+  bool HasSpan(const char* start_tag, const char* end_tag,
+               const Message& descriptor_proto, const string& field_name) {
+    return HasSpan(start_tag, end_tag, descriptor_proto, field_name, -1);
+  }
+
+  bool HasSpan(const char* start_tag, const char* end_tag,
+               const Message& descriptor_proto, const string& field_name,
+               int index) {
+    const FieldDescriptor* field =
+        descriptor_proto.GetDescriptor()->FindFieldByName(field_name);
+    if (field == NULL) {
+      ADD_FAILURE() << descriptor_proto.GetDescriptor()->name()
+                    << " has no such field: " << field_name;
+      return false;
+    }
+
+    return HasSpan(start_tag, end_tag, descriptor_proto, field, index);
+  }
+
+  bool HasSpan(const Message& descriptor_proto) {
+    return HasSpan(NULL, NULL, descriptor_proto, NULL, -1);
+  }
+
+  bool HasSpan(const Message& descriptor_proto, const string& field_name) {
+    return HasSpan(NULL, NULL, descriptor_proto, field_name, -1);
+  }
+
+  bool HasSpan(const Message& descriptor_proto, const string& field_name,
+               int index) {
+    return HasSpan(NULL, NULL, descriptor_proto, field_name, index);
+  }
+
+  bool HasSpan(const char* start_tag, const char* end_tag,
+               const Message& descriptor_proto, const FieldDescriptor* field,
+               int index) {
+    pair<SpanMap::iterator, SpanMap::iterator> range =
+        spans_.equal_range(SpanKey(descriptor_proto, field, index));
+
+    if (start_tag == NULL) {
+      if (range.first == range.second) {
+        return false;
+      } else {
+        spans_.erase(range.first);
+        return true;
+      }
+    } else {
+      RepeatedField<int> expected_span;
+      MakeExpectedSpan(lines_, start_tag, end_tag, &expected_span);
+
+      for (SpanMap::iterator iter = range.first; iter != range.second; ++iter) {
+        if (CompareSpans(expected_span, iter->second->span())) {
+          spans_.erase(iter);
+          return true;
+        }
+      }
+
+      return false;
+    }
+  }
+
+ private:
+  struct SpanKey {
+    const Message* descriptor_proto;
+    const FieldDescriptor* field;
+    int index;
+
+    inline SpanKey() {}
+    inline SpanKey(const Message& descriptor_proto,
+                   const FieldDescriptor* field,
+                   int index)
+        : descriptor_proto(&descriptor_proto), field(field), index(index) {}
+
+    inline bool operator<(const SpanKey& other) const {
+      if (descriptor_proto < other.descriptor_proto) return true;
+      if (descriptor_proto > other.descriptor_proto) return false;
+      if (field < other.field) return true;
+      if (field > other.field) return false;
+      return index < other.index;
+    }
+  };
+
+  typedef multimap<SpanKey, const SourceCodeInfo::Location*> SpanMap;
+  SpanMap spans_;
+  vector<string> lines_;
+};
+
+TEST_F(SourceInfoTest, BasicFileDecls) {
+  EXPECT_TRUE(Parse(
+      "/*a*/syntax = \"proto2\";\n"
+      "package /*b*/foo.bar/*c*/;\n"
+      "import /*d*/\"baz.proto\"/*e*/;\n"
+      "import /*f*/\"qux.proto\"/*g*/;/*h*/\n"
+      "// comment ignored\n"));
+
+  EXPECT_TRUE(HasSpan("a", "h", file_));
+  EXPECT_TRUE(HasSpan("b", "c", file_, "package"));
+  EXPECT_TRUE(HasSpan("d", "e", file_, "dependency", 0));
+  EXPECT_TRUE(HasSpan("f", "g", file_, "dependency", 1));
+}
+
+TEST_F(SourceInfoTest, Messages) {
+  EXPECT_TRUE(Parse(
+      "/*a*/message /*b*/Foo/*c*/ {}/*d*/\n"
+      "/*e*/message /*f*/Bar/*g*/ {}/*h*/\n"));
+
+  EXPECT_TRUE(HasSpan("a", "d", file_.message_type(0)));
+  EXPECT_TRUE(HasSpan("b", "c", file_.message_type(0), "name"));
+  EXPECT_TRUE(HasSpan("e", "h", file_.message_type(1)));
+  EXPECT_TRUE(HasSpan("f", "g", file_.message_type(1), "name"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+}
+
+TEST_F(SourceInfoTest, Fields) {
+  EXPECT_TRUE(Parse(
+      "message Foo {\n"
+      "  /*a*/optional/*b*/ /*c*/int32/*d*/ /*e*/bar/*f*/ = /*g*/1/*h*/;/*i*/\n"
+      "  /*j*/repeated/*k*/ /*l*/X.Y/*m*/ /*n*/baz/*o*/ = /*p*/2/*q*/;/*r*/\n"
+      "}\n"));
+
+  const FieldDescriptorProto& field1 = file_.message_type(0).field(0);
+  const FieldDescriptorProto& field2 = file_.message_type(0).field(1);
+
+  EXPECT_TRUE(HasSpan("a", "i", field1));
+  EXPECT_TRUE(HasSpan("a", "b", field1, "label"));
+  EXPECT_TRUE(HasSpan("c", "d", field1, "type"));
+  EXPECT_TRUE(HasSpan("e", "f", field1, "name"));
+  EXPECT_TRUE(HasSpan("g", "h", field1, "number"));
+
+  EXPECT_TRUE(HasSpan("j", "r", field2));
+  EXPECT_TRUE(HasSpan("j", "k", field2, "label"));
+  EXPECT_TRUE(HasSpan("l", "m", field2, "type_name"));
+  EXPECT_TRUE(HasSpan("n", "o", field2, "name"));
+  EXPECT_TRUE(HasSpan("p", "q", field2, "number"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(file_.message_type(0)));
+  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
+}
+
+TEST_F(SourceInfoTest, Extensions) {
+  EXPECT_TRUE(Parse(
+      "/*a*/extend /*b*/Foo/*c*/ {\n"
+      "  /*d*/optional/*e*/ int32 bar = 1;/*f*/\n"
+      "  /*g*/repeated/*h*/ X.Y baz = 2;/*i*/\n"
+      "}/*j*/\n"
+      "/*k*/extend /*l*/Bar/*m*/ {\n"
+      "  /*n*/optional int32 qux = 1;/*o*/\n"
+      "}/*p*/\n"));
+
+  const FieldDescriptorProto& field1 = file_.extension(0);
+  const FieldDescriptorProto& field2 = file_.extension(1);
+  const FieldDescriptorProto& field3 = file_.extension(2);
+
+  EXPECT_TRUE(HasSpan("a", "j", file_, "extension"));
+  EXPECT_TRUE(HasSpan("k", "p", file_, "extension"));
+
+  EXPECT_TRUE(HasSpan("d", "f", field1));
+  EXPECT_TRUE(HasSpan("d", "e", field1, "label"));
+  EXPECT_TRUE(HasSpan("b", "c", field1, "extendee"));
+
+  EXPECT_TRUE(HasSpan("g", "i", field2));
+  EXPECT_TRUE(HasSpan("g", "h", field2, "label"));
+  EXPECT_TRUE(HasSpan("b", "c", field2, "extendee"));
+
+  EXPECT_TRUE(HasSpan("n", "o", field3));
+  EXPECT_TRUE(HasSpan("l", "m", field3, "extendee"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(field1, "type"));
+  EXPECT_TRUE(HasSpan(field1, "name"));
+  EXPECT_TRUE(HasSpan(field1, "number"));
+  EXPECT_TRUE(HasSpan(field2, "type_name"));
+  EXPECT_TRUE(HasSpan(field2, "name"));
+  EXPECT_TRUE(HasSpan(field2, "number"));
+  EXPECT_TRUE(HasSpan(field3, "label"));
+  EXPECT_TRUE(HasSpan(field3, "type"));
+  EXPECT_TRUE(HasSpan(field3, "name"));
+  EXPECT_TRUE(HasSpan(field3, "number"));
+}
+
+TEST_F(SourceInfoTest, NestedExtensions) {
+  EXPECT_TRUE(Parse(
+      "message Message {\n"
+      "  /*a*/extend /*b*/Foo/*c*/ {\n"
+      "    /*d*/optional/*e*/ int32 bar = 1;/*f*/\n"
+      "    /*g*/repeated/*h*/ X.Y baz = 2;/*i*/\n"
+      "  }/*j*/\n"
+      "  /*k*/extend /*l*/Bar/*m*/ {\n"
+      "    /*n*/optional int32 qux = 1;/*o*/\n"
+      "  }/*p*/\n"
+      "}\n"));
+
+  const FieldDescriptorProto& field1 = file_.message_type(0).extension(0);
+  const FieldDescriptorProto& field2 = file_.message_type(0).extension(1);
+  const FieldDescriptorProto& field3 = file_.message_type(0).extension(2);
+
+  EXPECT_TRUE(HasSpan("a", "j", file_.message_type(0), "extension"));
+  EXPECT_TRUE(HasSpan("k", "p", file_.message_type(0), "extension"));
+
+  EXPECT_TRUE(HasSpan("d", "f", field1));
+  EXPECT_TRUE(HasSpan("d", "e", field1, "label"));
+  EXPECT_TRUE(HasSpan("b", "c", field1, "extendee"));
+
+  EXPECT_TRUE(HasSpan("g", "i", field2));
+  EXPECT_TRUE(HasSpan("g", "h", field2, "label"));
+  EXPECT_TRUE(HasSpan("b", "c", field2, "extendee"));
+
+  EXPECT_TRUE(HasSpan("n", "o", field3));
+  EXPECT_TRUE(HasSpan("l", "m", field3, "extendee"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(file_.message_type(0)));
+  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
+  EXPECT_TRUE(HasSpan(field1, "type"));
+  EXPECT_TRUE(HasSpan(field1, "name"));
+  EXPECT_TRUE(HasSpan(field1, "number"));
+  EXPECT_TRUE(HasSpan(field2, "type_name"));
+  EXPECT_TRUE(HasSpan(field2, "name"));
+  EXPECT_TRUE(HasSpan(field2, "number"));
+  EXPECT_TRUE(HasSpan(field3, "label"));
+  EXPECT_TRUE(HasSpan(field3, "type"));
+  EXPECT_TRUE(HasSpan(field3, "name"));
+  EXPECT_TRUE(HasSpan(field3, "number"));
+}
+
+TEST_F(SourceInfoTest, ExtensionRanges) {
+  EXPECT_TRUE(Parse(
+      "message Message {\n"
+      "  /*a*/extensions /*b*/1/*c*/ to /*d*/4/*e*/, /*f*/6/*g*/;/*h*/\n"
+      "  /*i*/extensions /*j*/8/*k*/ to /*l*/max/*m*/;/*n*/\n"
+      "}\n"));
+
+  const DescriptorProto::ExtensionRange& range1 =
+      file_.message_type(0).extension_range(0);
+  const DescriptorProto::ExtensionRange& range2 =
+      file_.message_type(0).extension_range(1);
+  const DescriptorProto::ExtensionRange& range3 =
+      file_.message_type(0).extension_range(2);
+
+  EXPECT_TRUE(HasSpan("a", "h", file_.message_type(0), "extension_range"));
+  EXPECT_TRUE(HasSpan("i", "n", file_.message_type(0), "extension_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"));
+
+  EXPECT_TRUE(HasSpan("j", "m", range3));
+  EXPECT_TRUE(HasSpan("j", "k", range3, "start"));
+  EXPECT_TRUE(HasSpan("l", "m", range3, "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, NestedMessages) {
+  EXPECT_TRUE(Parse(
+      "message Foo {\n"
+      "  /*a*/message /*b*/Bar/*c*/ {\n"
+      "    /*d*/message /*e*/Baz/*f*/ {}/*g*/\n"
+      "  }/*h*/\n"
+      "  /*i*/message /*j*/Qux/*k*/ {}/*l*/\n"
+      "}\n"));
+
+  const DescriptorProto& bar = file_.message_type(0).nested_type(0);
+  const DescriptorProto& baz = bar.nested_type(0);
+  const DescriptorProto& qux = file_.message_type(0).nested_type(1);
+
+  EXPECT_TRUE(HasSpan("a", "h", bar));
+  EXPECT_TRUE(HasSpan("b", "c", bar, "name"));
+  EXPECT_TRUE(HasSpan("d", "g", baz));
+  EXPECT_TRUE(HasSpan("e", "f", baz, "name"));
+  EXPECT_TRUE(HasSpan("i", "l", qux));
+  EXPECT_TRUE(HasSpan("j", "k", qux, "name"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(file_.message_type(0)));
+  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
+}
+
+TEST_F(SourceInfoTest, Groups) {
+  EXPECT_TRUE(Parse(
+      "message Foo {\n"
+      "  message Bar {}\n"
+      "  /*a*/optional/*b*/ /*c*/group/*d*/ /*e*/Baz/*f*/ = /*g*/1/*h*/ {\n"
+      "    /*i*/message Qux {}/*j*/\n"
+      "  }/*k*/\n"
+      "}\n"));
+
+  const DescriptorProto& bar = file_.message_type(0).nested_type(0);
+  const DescriptorProto& baz = file_.message_type(0).nested_type(1);
+  const DescriptorProto& qux = baz.nested_type(0);
+  const FieldDescriptorProto& field = file_.message_type(0).field(0);
+
+  EXPECT_TRUE(HasSpan("a", "k", field));
+  EXPECT_TRUE(HasSpan("a", "b", field, "label"));
+  EXPECT_TRUE(HasSpan("c", "d", field, "type"));
+  EXPECT_TRUE(HasSpan("e", "f", field, "name"));
+  EXPECT_TRUE(HasSpan("e", "f", field, "type_name"));
+  EXPECT_TRUE(HasSpan("g", "h", field, "number"));
+
+  EXPECT_TRUE(HasSpan("a", "k", baz));
+  EXPECT_TRUE(HasSpan("e", "f", baz, "name"));
+  EXPECT_TRUE(HasSpan("i", "j", qux));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(file_.message_type(0)));
+  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
+  EXPECT_TRUE(HasSpan(bar));
+  EXPECT_TRUE(HasSpan(bar, "name"));
+  EXPECT_TRUE(HasSpan(qux, "name"));
+}
+
+TEST_F(SourceInfoTest, Enums) {
+  EXPECT_TRUE(Parse(
+      "/*a*/enum /*b*/Foo/*c*/ {}/*d*/\n"
+      "/*e*/enum /*f*/Bar/*g*/ {}/*h*/\n"));
+
+  EXPECT_TRUE(HasSpan("a", "d", file_.enum_type(0)));
+  EXPECT_TRUE(HasSpan("b", "c", file_.enum_type(0), "name"));
+  EXPECT_TRUE(HasSpan("e", "h", file_.enum_type(1)));
+  EXPECT_TRUE(HasSpan("f", "g", file_.enum_type(1), "name"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+}
+
+TEST_F(SourceInfoTest, EnumValues) {
+  EXPECT_TRUE(Parse(
+      "enum Foo {\n"
+      "  /*a*/BAR/*b*/ = /*c*/1/*d*/;/*e*/\n"
+      "  /*f*/BAZ/*g*/ = /*h*/2/*i*/;/*j*/\n"
+      "}"));
+
+  const EnumValueDescriptorProto& bar = file_.enum_type(0).value(0);
+  const EnumValueDescriptorProto& baz = file_.enum_type(0).value(1);
+
+  EXPECT_TRUE(HasSpan("a", "e", bar));
+  EXPECT_TRUE(HasSpan("a", "b", bar, "name"));
+  EXPECT_TRUE(HasSpan("c", "d", bar, "number"));
+  EXPECT_TRUE(HasSpan("f", "j", baz));
+  EXPECT_TRUE(HasSpan("f", "g", baz, "name"));
+  EXPECT_TRUE(HasSpan("h", "i", baz, "number"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(file_.enum_type(0)));
+  EXPECT_TRUE(HasSpan(file_.enum_type(0), "name"));
+}
+
+TEST_F(SourceInfoTest, NestedEnums) {
+  EXPECT_TRUE(Parse(
+      "message Foo {\n"
+      "  /*a*/enum /*b*/Bar/*c*/ {}/*d*/\n"
+      "  /*e*/enum /*f*/Baz/*g*/ {}/*h*/\n"
+      "}\n"));
+
+  const EnumDescriptorProto& bar = file_.message_type(0).enum_type(0);
+  const EnumDescriptorProto& baz = file_.message_type(0).enum_type(1);
+
+  EXPECT_TRUE(HasSpan("a", "d", bar));
+  EXPECT_TRUE(HasSpan("b", "c", bar, "name"));
+  EXPECT_TRUE(HasSpan("e", "h", baz));
+  EXPECT_TRUE(HasSpan("f", "g", baz, "name"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(file_.message_type(0)));
+  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
+}
+
+TEST_F(SourceInfoTest, Services) {
+  EXPECT_TRUE(Parse(
+      "/*a*/service /*b*/Foo/*c*/ {}/*d*/\n"
+      "/*e*/service /*f*/Bar/*g*/ {}/*h*/\n"));
+
+  EXPECT_TRUE(HasSpan("a", "d", file_.service(0)));
+  EXPECT_TRUE(HasSpan("b", "c", file_.service(0), "name"));
+  EXPECT_TRUE(HasSpan("e", "h", file_.service(1)));
+  EXPECT_TRUE(HasSpan("f", "g", file_.service(1), "name"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+}
+
+TEST_F(SourceInfoTest, Methods) {
+  EXPECT_TRUE(Parse(
+      "service Foo {\n"
+      "  /*a*/rpc /*b*/Bar/*c*/(/*d*/X/*e*/) returns(/*f*/Y/*g*/);/*h*/"
+      "  /*i*/rpc /*j*/Baz/*k*/(/*l*/Z/*m*/) returns(/*n*/W/*o*/);/*p*/"
+      "}"));
+
+  const MethodDescriptorProto& bar = file_.service(0).method(0);
+  const MethodDescriptorProto& baz = file_.service(0).method(1);
+
+  EXPECT_TRUE(HasSpan("a", "h", bar));
+  EXPECT_TRUE(HasSpan("b", "c", bar, "name"));
+  EXPECT_TRUE(HasSpan("d", "e", bar, "input_type"));
+  EXPECT_TRUE(HasSpan("f", "g", bar, "output_type"));
+
+  EXPECT_TRUE(HasSpan("i", "p", baz));
+  EXPECT_TRUE(HasSpan("j", "k", baz, "name"));
+  EXPECT_TRUE(HasSpan("l", "m", baz, "input_type"));
+  EXPECT_TRUE(HasSpan("n", "o", baz, "output_type"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(file_.service(0)));
+  EXPECT_TRUE(HasSpan(file_.service(0), "name"));
+}
+
+TEST_F(SourceInfoTest, Options) {
+  EXPECT_TRUE(Parse(
+      "/*a*/option /*b*/foo/*c*/./*d*/(/*e*/bar.baz/*f*/)/*g*/ = "
+          "/*h*/123/*i*/;/*j*/\n"
+      "/*k*/option qux = /*l*/-123/*m*/;/*n*/\n"
+      "/*o*/option corge = /*p*/abc/*q*/;/*r*/\n"
+      "/*s*/option grault = /*t*/'blah'/*u*/;/*v*/\n"
+      "/*w*/option garply = /*x*/{ yadda yadda }/*y*/;/*z*/\n"
+      "/*0*/option waldo = /*1*/123.0/*2*/;/*3*/\n"
+  ));
+
+  const UninterpretedOption& option1 = file_.options().uninterpreted_option(0);
+  const UninterpretedOption& option2 = file_.options().uninterpreted_option(1);
+  const UninterpretedOption& option3 = file_.options().uninterpreted_option(2);
+  const UninterpretedOption& option4 = file_.options().uninterpreted_option(3);
+  const UninterpretedOption& option5 = file_.options().uninterpreted_option(4);
+  const UninterpretedOption& option6 = file_.options().uninterpreted_option(5);
+
+  EXPECT_TRUE(HasSpan("a", "j", file_.options()));
+  EXPECT_TRUE(HasSpan("b", "i", option1));
+  EXPECT_TRUE(HasSpan("b", "g", option1, "name"));
+  EXPECT_TRUE(HasSpan("b", "c", option1.name(0)));
+  EXPECT_TRUE(HasSpan("b", "c", option1.name(0), "name_part"));
+  EXPECT_TRUE(HasSpan("d", "g", option1.name(1)));
+  EXPECT_TRUE(HasSpan("e", "f", option1.name(1), "name_part"));
+  EXPECT_TRUE(HasSpan("h", "i", option1, "positive_int_value"));
+
+  EXPECT_TRUE(HasSpan("k", "n", file_.options()));
+  EXPECT_TRUE(HasSpan("l", "m", option2, "negative_int_value"));
+
+  EXPECT_TRUE(HasSpan("o", "r", file_.options()));
+  EXPECT_TRUE(HasSpan("p", "q", option3, "identifier_value"));
+
+  EXPECT_TRUE(HasSpan("s", "v", file_.options()));
+  EXPECT_TRUE(HasSpan("t", "u", option4, "string_value"));
+
+  EXPECT_TRUE(HasSpan("w", "z", file_.options()));
+  EXPECT_TRUE(HasSpan("x", "y", option5, "aggregate_value"));
+
+  EXPECT_TRUE(HasSpan("0", "3", file_.options()));
+  EXPECT_TRUE(HasSpan("1", "2", option6, "double_value"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(option2));
+  EXPECT_TRUE(HasSpan(option3));
+  EXPECT_TRUE(HasSpan(option4));
+  EXPECT_TRUE(HasSpan(option5));
+  EXPECT_TRUE(HasSpan(option6));
+  EXPECT_TRUE(HasSpan(option2, "name"));
+  EXPECT_TRUE(HasSpan(option3, "name"));
+  EXPECT_TRUE(HasSpan(option4, "name"));
+  EXPECT_TRUE(HasSpan(option5, "name"));
+  EXPECT_TRUE(HasSpan(option6, "name"));
+  EXPECT_TRUE(HasSpan(option2.name(0)));
+  EXPECT_TRUE(HasSpan(option3.name(0)));
+  EXPECT_TRUE(HasSpan(option4.name(0)));
+  EXPECT_TRUE(HasSpan(option5.name(0)));
+  EXPECT_TRUE(HasSpan(option6.name(0)));
+  EXPECT_TRUE(HasSpan(option2.name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(option3.name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(option4.name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(option5.name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(option6.name(0), "name_part"));
+}
+
+TEST_F(SourceInfoTest, ScopedOptions) {
+  EXPECT_TRUE(Parse(
+    "message Foo {\n"
+    "  /*a*/option mopt = 1;/*b*/\n"
+    "}\n"
+    "enum Bar {\n"
+    "  /*c*/option eopt = 1;/*d*/\n"
+    "}\n"
+    "service Baz {\n"
+    "  /*e*/option sopt = 1;/*f*/\n"
+    "  rpc M(X) returns(Y) {\n"
+    "    /*g*/option mopt = 1;/*h*/\n"
+    "  }\n"
+    "}\n"));
+
+  EXPECT_TRUE(HasSpan("a", "b", file_.message_type(0).options()));
+  EXPECT_TRUE(HasSpan("c", "d", file_.enum_type(0).options()));
+  EXPECT_TRUE(HasSpan("e", "f", file_.service(0).options()));
+  EXPECT_TRUE(HasSpan("g", "h", file_.service(0).method(0).options()));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(file_.message_type(0)));
+  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
+  EXPECT_TRUE(HasSpan(file_.message_type(0).options()
+                      .uninterpreted_option(0)));
+  EXPECT_TRUE(HasSpan(file_.message_type(0).options()
+                      .uninterpreted_option(0), "name"));
+  EXPECT_TRUE(HasSpan(file_.message_type(0).options()
+                      .uninterpreted_option(0).name(0)));
+  EXPECT_TRUE(HasSpan(file_.message_type(0).options()
+                      .uninterpreted_option(0).name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(file_.message_type(0).options()
+                      .uninterpreted_option(0), "positive_int_value"));
+  EXPECT_TRUE(HasSpan(file_.enum_type(0)));
+  EXPECT_TRUE(HasSpan(file_.enum_type(0), "name"));
+  EXPECT_TRUE(HasSpan(file_.enum_type(0).options()
+                      .uninterpreted_option(0)));
+  EXPECT_TRUE(HasSpan(file_.enum_type(0).options()
+                      .uninterpreted_option(0), "name"));
+  EXPECT_TRUE(HasSpan(file_.enum_type(0).options()
+                      .uninterpreted_option(0).name(0)));
+  EXPECT_TRUE(HasSpan(file_.enum_type(0).options()
+                      .uninterpreted_option(0).name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(file_.enum_type(0).options()
+                      .uninterpreted_option(0), "positive_int_value"));
+  EXPECT_TRUE(HasSpan(file_.service(0)));
+  EXPECT_TRUE(HasSpan(file_.service(0), "name"));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(0)));
+  EXPECT_TRUE(HasSpan(file_.service(0).options()
+                      .uninterpreted_option(0)));
+  EXPECT_TRUE(HasSpan(file_.service(0).options()
+                      .uninterpreted_option(0), "name"));
+  EXPECT_TRUE(HasSpan(file_.service(0).options()
+                      .uninterpreted_option(0).name(0)));
+  EXPECT_TRUE(HasSpan(file_.service(0).options()
+                      .uninterpreted_option(0).name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(file_.service(0).options()
+                      .uninterpreted_option(0), "positive_int_value"));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(0), "name"));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(0), "input_type"));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(0), "output_type"));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(0).options()
+                      .uninterpreted_option(0)));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(0).options()
+                      .uninterpreted_option(0), "name"));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(0).options()
+                      .uninterpreted_option(0).name(0)));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(0).options()
+                      .uninterpreted_option(0).name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(0).options()
+                      .uninterpreted_option(0), "positive_int_value"));
+}
+
+TEST_F(SourceInfoTest, FieldOptions) {
+  // The actual "name = value" pairs are parsed by the same code as for
+  // top-level options so we won't re-test that -- just make sure that the
+  // syntax used for field options is understood.
+  EXPECT_TRUE(Parse(
+      "message Foo {"
+      "  optional int32 bar = 1 "
+          "/*a*/[default=/*b*/123/*c*/,/*d*/opt1=123/*e*/,"
+          "/*f*/opt2='hi'/*g*/]/*h*/;"
+      "}\n"
+  ));
+
+  const FieldDescriptorProto& field = file_.message_type(0).field(0);
+  const UninterpretedOption& option1 = field.options().uninterpreted_option(0);
+  const UninterpretedOption& option2 = field.options().uninterpreted_option(1);
+
+  EXPECT_TRUE(HasSpan("a", "h", field.options()));
+  EXPECT_TRUE(HasSpan("b", "c", field, "default_value"));
+  EXPECT_TRUE(HasSpan("d", "e", option1));
+  EXPECT_TRUE(HasSpan("f", "g", option2));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(file_.message_type(0)));
+  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
+  EXPECT_TRUE(HasSpan(field));
+  EXPECT_TRUE(HasSpan(field, "label"));
+  EXPECT_TRUE(HasSpan(field, "type"));
+  EXPECT_TRUE(HasSpan(field, "name"));
+  EXPECT_TRUE(HasSpan(field, "number"));
+  EXPECT_TRUE(HasSpan(option1, "name"));
+  EXPECT_TRUE(HasSpan(option2, "name"));
+  EXPECT_TRUE(HasSpan(option1.name(0)));
+  EXPECT_TRUE(HasSpan(option2.name(0)));
+  EXPECT_TRUE(HasSpan(option1.name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(option2.name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(option1, "positive_int_value"));
+  EXPECT_TRUE(HasSpan(option2, "string_value"));
+}
+
+TEST_F(SourceInfoTest, EnumValueOptions) {
+  // The actual "name = value" pairs are parsed by the same code as for
+  // top-level options so we won't re-test that -- just make sure that the
+  // syntax used for enum options is understood.
+  EXPECT_TRUE(Parse(
+      "enum Foo {"
+      "  BAR = 1 /*a*/[/*b*/opt1=123/*c*/,/*d*/opt2='hi'/*e*/]/*f*/;"
+      "}\n"
+  ));
+
+  const EnumValueDescriptorProto& value = file_.enum_type(0).value(0);
+  const UninterpretedOption& option1 = value.options().uninterpreted_option(0);
+  const UninterpretedOption& option2 = value.options().uninterpreted_option(1);
+
+  EXPECT_TRUE(HasSpan("a", "f", value.options()));
+  EXPECT_TRUE(HasSpan("b", "c", option1));
+  EXPECT_TRUE(HasSpan("d", "e", option2));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(file_.enum_type(0)));
+  EXPECT_TRUE(HasSpan(file_.enum_type(0), "name"));
+  EXPECT_TRUE(HasSpan(value));
+  EXPECT_TRUE(HasSpan(value, "name"));
+  EXPECT_TRUE(HasSpan(value, "number"));
+  EXPECT_TRUE(HasSpan(option1, "name"));
+  EXPECT_TRUE(HasSpan(option2, "name"));
+  EXPECT_TRUE(HasSpan(option1.name(0)));
+  EXPECT_TRUE(HasSpan(option2.name(0)));
+  EXPECT_TRUE(HasSpan(option1.name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(option2.name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(option1, "positive_int_value"));
+  EXPECT_TRUE(HasSpan(option2, "string_value"));
+}
+
+// ===================================================================
 
 }  // anonymous namespace
 
diff --git a/src/google/protobuf/compiler/plugin.cc b/src/google/protobuf/compiler/plugin.cc
index a4aedaf..727f942 100644
--- a/src/google/protobuf/compiler/plugin.cc
+++ b/src/google/protobuf/compiler/plugin.cc
@@ -59,13 +59,15 @@
 namespace protobuf {
 namespace compiler {
 
-class GeneratorResponseOutputDirectory : public OutputDirectory {
+class GeneratorResponseContext : public GeneratorContext {
  public:
-  GeneratorResponseOutputDirectory(CodeGeneratorResponse* response)
-      : response_(response) {}
-  virtual ~GeneratorResponseOutputDirectory() {}
+  GeneratorResponseContext(CodeGeneratorResponse* response,
+                           const vector<const FileDescriptor*>& parsed_files)
+      : response_(response),
+        parsed_files_(parsed_files) {}
+  virtual ~GeneratorResponseContext() {}
 
-  // implements OutputDirectory --------------------------------------
+  // implements GeneratorContext --------------------------------------
 
   virtual io::ZeroCopyOutputStream* Open(const string& filename) {
     CodeGeneratorResponse::File* file = response_->add_file();
@@ -81,8 +83,13 @@
     return new io::StringOutputStream(file->mutable_content());
   }
 
+  void ListParsedFiles(vector<const FileDescriptor*>* output) {
+    *output = parsed_files_;
+  }
+
  private:
   CodeGeneratorResponse* response_;
+  const vector<const FileDescriptor*>& parsed_files_;
 };
 
 int PluginMain(int argc, char* argv[], const CodeGenerator* generator) {
@@ -112,22 +119,26 @@
     }
   }
 
-  CodeGeneratorResponse response;
-  GeneratorResponseOutputDirectory output_directory(&response);
-
+  vector<const FileDescriptor*> parsed_files;
   for (int i = 0; i < request.file_to_generate_size(); i++) {
-    const FileDescriptor* file =
-        pool.FindFileByName(request.file_to_generate(i));
-    if (file == NULL) {
+    parsed_files.push_back(pool.FindFileByName(request.file_to_generate(i)));
+    if (parsed_files.back() == NULL) {
       cerr << argv[0] << ": protoc asked plugin to generate a file but "
               "did not provide a descriptor for the file: "
            << request.file_to_generate(i) << endl;
       return 1;
     }
+  }
+
+  CodeGeneratorResponse response;
+  GeneratorResponseContext context(&response, parsed_files);
+
+  for (int i = 0; i < parsed_files.size(); i++) {
+    const FileDescriptor* file = parsed_files[i];
 
     string error;
     bool succeeded = generator->Generate(
-        file, request.parameter(), &output_directory, &error);
+        file, request.parameter(), &context, &error);
 
     if (!succeeded && error.empty()) {
       error = "Code generator returned false but provided no error "
diff --git a/src/google/protobuf/compiler/plugin.h b/src/google/protobuf/compiler/plugin.h
index 7c40333..64dfb1d 100644
--- a/src/google/protobuf/compiler/plugin.h
+++ b/src/google/protobuf/compiler/plugin.h
@@ -64,7 +64,7 @@
 class CodeGenerator;    // code_generator.h
 
 // Implements main() for a protoc plugin exposing the given code generator.
-LIBPROTOC_EXPORT int PluginMain(int argc, char* argv[], const CodeGenerator* generator);
+int PluginMain(int argc, char* argv[], const CodeGenerator* generator);
 
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc
index 13d35c6..ad4b4de 100644
--- a/src/google/protobuf/compiler/plugin.pb.cc
+++ b/src/google/protobuf/compiler/plugin.pb.cc
@@ -158,7 +158,6 @@
 
 // ===================================================================
 
-const ::std::string CodeGeneratorRequest::_default_parameter_;
 #ifndef _MSC_VER
 const int CodeGeneratorRequest::kFileToGenerateFieldNumber;
 const int CodeGeneratorRequest::kParameterFieldNumber;
@@ -181,7 +180,7 @@
 
 void CodeGeneratorRequest::SharedCtor() {
   _cached_size_ = 0;
-  parameter_ = const_cast< ::std::string*>(&_default_parameter_);
+  parameter_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
 }
 
@@ -190,7 +189,7 @@
 }
 
 void CodeGeneratorRequest::SharedDtor() {
-  if (parameter_ != &_default_parameter_) {
+  if (parameter_ != &::google::protobuf::internal::kEmptyString) {
     delete parameter_;
   }
   if (this != default_instance_) {
@@ -219,8 +218,8 @@
 
 void CodeGeneratorRequest::Clear() {
   if (_has_bits_[1 / 32] & (0xffu << (1 % 32))) {
-    if (_has_bit(1)) {
-      if (parameter_ != &_default_parameter_) {
+    if (has_parameter()) {
+      if (parameter_ != &::google::protobuf::internal::kEmptyString) {
         parameter_->clear();
       }
     }
@@ -315,7 +314,7 @@
   }
   
   // optional string parameter = 2;
-  if (_has_bit(1)) {
+  if (has_parameter()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->parameter().data(), this->parameter().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -347,7 +346,7 @@
   }
   
   // optional string parameter = 2;
-  if (_has_bit(1)) {
+  if (has_parameter()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->parameter().data(), this->parameter().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -425,7 +424,7 @@
   file_to_generate_.MergeFrom(from.file_to_generate_);
   proto_file_.MergeFrom(from.proto_file_);
   if (from._has_bits_[1 / 32] & (0xffu << (1 % 32))) {
-    if (from._has_bit(1)) {
+    if (from.has_parameter()) {
       set_parameter(from.parameter());
     }
   }
@@ -474,9 +473,6 @@
 
 // ===================================================================
 
-const ::std::string CodeGeneratorResponse_File::_default_name_;
-const ::std::string CodeGeneratorResponse_File::_default_insertion_point_;
-const ::std::string CodeGeneratorResponse_File::_default_content_;
 #ifndef _MSC_VER
 const int CodeGeneratorResponse_File::kNameFieldNumber;
 const int CodeGeneratorResponse_File::kInsertionPointFieldNumber;
@@ -499,9 +495,9 @@
 
 void CodeGeneratorResponse_File::SharedCtor() {
   _cached_size_ = 0;
-  name_ = const_cast< ::std::string*>(&_default_name_);
-  insertion_point_ = const_cast< ::std::string*>(&_default_insertion_point_);
-  content_ = const_cast< ::std::string*>(&_default_content_);
+  name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  insertion_point_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  content_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
 }
 
@@ -510,13 +506,13 @@
 }
 
 void CodeGeneratorResponse_File::SharedDtor() {
-  if (name_ != &_default_name_) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
     delete name_;
   }
-  if (insertion_point_ != &_default_insertion_point_) {
+  if (insertion_point_ != &::google::protobuf::internal::kEmptyString) {
     delete insertion_point_;
   }
-  if (content_ != &_default_content_) {
+  if (content_ != &::google::protobuf::internal::kEmptyString) {
     delete content_;
   }
   if (this != default_instance_) {
@@ -545,18 +541,18 @@
 
 void CodeGeneratorResponse_File::Clear() {
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (_has_bit(0)) {
-      if (name_ != &_default_name_) {
+    if (has_name()) {
+      if (name_ != &::google::protobuf::internal::kEmptyString) {
         name_->clear();
       }
     }
-    if (_has_bit(1)) {
-      if (insertion_point_ != &_default_insertion_point_) {
+    if (has_insertion_point()) {
+      if (insertion_point_ != &::google::protobuf::internal::kEmptyString) {
         insertion_point_->clear();
       }
     }
-    if (_has_bit(2)) {
-      if (content_ != &_default_content_) {
+    if (has_content()) {
+      if (content_ != &::google::protobuf::internal::kEmptyString) {
         content_->clear();
       }
     }
@@ -640,7 +636,7 @@
 void CodeGeneratorResponse_File::SerializeWithCachedSizes(
     ::google::protobuf::io::CodedOutputStream* output) const {
   // optional string name = 1;
-  if (_has_bit(0)) {
+  if (has_name()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->name().data(), this->name().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -649,7 +645,7 @@
   }
   
   // optional string insertion_point = 2;
-  if (_has_bit(1)) {
+  if (has_insertion_point()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->insertion_point().data(), this->insertion_point().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -658,7 +654,7 @@
   }
   
   // optional string content = 15;
-  if (_has_bit(2)) {
+  if (has_content()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->content().data(), this->content().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -675,7 +671,7 @@
 ::google::protobuf::uint8* CodeGeneratorResponse_File::SerializeWithCachedSizesToArray(
     ::google::protobuf::uint8* target) const {
   // optional string name = 1;
-  if (_has_bit(0)) {
+  if (has_name()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->name().data(), this->name().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -685,7 +681,7 @@
   }
   
   // optional string insertion_point = 2;
-  if (_has_bit(1)) {
+  if (has_insertion_point()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->insertion_point().data(), this->insertion_point().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -695,7 +691,7 @@
   }
   
   // optional string content = 15;
-  if (_has_bit(2)) {
+  if (has_content()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->content().data(), this->content().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -763,13 +759,13 @@
 void CodeGeneratorResponse_File::MergeFrom(const CodeGeneratorResponse_File& from) {
   GOOGLE_CHECK_NE(&from, this);
   if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (from._has_bit(0)) {
+    if (from.has_name()) {
       set_name(from.name());
     }
-    if (from._has_bit(1)) {
+    if (from.has_insertion_point()) {
       set_insertion_point(from.insertion_point());
     }
-    if (from._has_bit(2)) {
+    if (from.has_content()) {
       set_content(from.content());
     }
   }
@@ -815,7 +811,6 @@
 
 // -------------------------------------------------------------------
 
-const ::std::string CodeGeneratorResponse::_default_error_;
 #ifndef _MSC_VER
 const int CodeGeneratorResponse::kErrorFieldNumber;
 const int CodeGeneratorResponse::kFileFieldNumber;
@@ -837,7 +832,7 @@
 
 void CodeGeneratorResponse::SharedCtor() {
   _cached_size_ = 0;
-  error_ = const_cast< ::std::string*>(&_default_error_);
+  error_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
 }
 
@@ -846,7 +841,7 @@
 }
 
 void CodeGeneratorResponse::SharedDtor() {
-  if (error_ != &_default_error_) {
+  if (error_ != &::google::protobuf::internal::kEmptyString) {
     delete error_;
   }
   if (this != default_instance_) {
@@ -875,8 +870,8 @@
 
 void CodeGeneratorResponse::Clear() {
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (_has_bit(0)) {
-      if (error_ != &_default_error_) {
+    if (has_error()) {
+      if (error_ != &::google::protobuf::internal::kEmptyString) {
         error_->clear();
       }
     }
@@ -942,7 +937,7 @@
 void CodeGeneratorResponse::SerializeWithCachedSizes(
     ::google::protobuf::io::CodedOutputStream* output) const {
   // optional string error = 1;
-  if (_has_bit(0)) {
+  if (has_error()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->error().data(), this->error().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -965,7 +960,7 @@
 ::google::protobuf::uint8* CodeGeneratorResponse::SerializeWithCachedSizesToArray(
     ::google::protobuf::uint8* target) const {
   // optional string error = 1;
-  if (_has_bit(0)) {
+  if (has_error()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->error().data(), this->error().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -1035,7 +1030,7 @@
   GOOGLE_CHECK_NE(&from, this);
   file_.MergeFrom(from.file_);
   if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (from._has_bit(0)) {
+    if (from.has_error()) {
       set_error(from.error());
     }
   }
diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h
index bd6bf63..c307bfd 100644
--- a/src/google/protobuf/compiler/plugin.pb.h
+++ b/src/google/protobuf/compiler/plugin.pb.h
@@ -120,6 +120,7 @@
   inline void set_parameter(const char* value);
   inline void set_parameter(const char* value, size_t size);
   inline ::std::string* mutable_parameter();
+  inline ::std::string* release_parameter();
   
   // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
   inline int proto_file_size() const;
@@ -135,30 +136,22 @@
   
   // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorRequest)
  private:
+  inline void set_has_parameter();
+  inline void clear_has_parameter();
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   ::google::protobuf::RepeatedPtrField< ::std::string> file_to_generate_;
   ::std::string* parameter_;
-  static const ::std::string _default_parameter_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > proto_file_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
+  
   friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static CodeGeneratorRequest* default_instance_;
 };
@@ -227,6 +220,7 @@
   inline void set_name(const char* value);
   inline void set_name(const char* value, size_t size);
   inline ::std::string* mutable_name();
+  inline ::std::string* release_name();
   
   // optional string insertion_point = 2;
   inline bool has_insertion_point() const;
@@ -237,6 +231,7 @@
   inline void set_insertion_point(const char* value);
   inline void set_insertion_point(const char* value, size_t size);
   inline ::std::string* mutable_insertion_point();
+  inline ::std::string* release_insertion_point();
   
   // optional string content = 15;
   inline bool has_content() const;
@@ -247,35 +242,30 @@
   inline void set_content(const char* value);
   inline void set_content(const char* value, size_t size);
   inline ::std::string* mutable_content();
+  inline ::std::string* release_content();
   
   // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse.File)
  private:
+  inline void set_has_name();
+  inline void clear_has_name();
+  inline void set_has_insertion_point();
+  inline void clear_has_insertion_point();
+  inline void set_has_content();
+  inline void clear_has_content();
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   ::std::string* name_;
-  static const ::std::string _default_name_;
   ::std::string* insertion_point_;
-  static const ::std::string _default_insertion_point_;
   ::std::string* content_;
-  static const ::std::string _default_content_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
+  
   friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static CodeGeneratorResponse_File* default_instance_;
 };
@@ -346,6 +336,7 @@
   inline void set_error(const char* value);
   inline void set_error(const char* value, size_t size);
   inline ::std::string* mutable_error();
+  inline ::std::string* release_error();
   
   // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
   inline int file_size() const;
@@ -361,29 +352,21 @@
   
   // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse)
  private:
+  inline void set_has_error();
+  inline void clear_has_error();
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   ::std::string* error_;
-  static const ::std::string _default_error_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File > file_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
+  
   friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static CodeGeneratorResponse* default_instance_;
 };
@@ -440,45 +423,61 @@
 
 // optional string parameter = 2;
 inline bool CodeGeneratorRequest::has_parameter() const {
-  return _has_bit(1);
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void CodeGeneratorRequest::set_has_parameter() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void CodeGeneratorRequest::clear_has_parameter() {
+  _has_bits_[0] &= ~0x00000002u;
 }
 inline void CodeGeneratorRequest::clear_parameter() {
-  if (parameter_ != &_default_parameter_) {
+  if (parameter_ != &::google::protobuf::internal::kEmptyString) {
     parameter_->clear();
   }
-  _clear_bit(1);
+  clear_has_parameter();
 }
 inline const ::std::string& CodeGeneratorRequest::parameter() const {
   return *parameter_;
 }
 inline void CodeGeneratorRequest::set_parameter(const ::std::string& value) {
-  _set_bit(1);
-  if (parameter_ == &_default_parameter_) {
+  set_has_parameter();
+  if (parameter_ == &::google::protobuf::internal::kEmptyString) {
     parameter_ = new ::std::string;
   }
   parameter_->assign(value);
 }
 inline void CodeGeneratorRequest::set_parameter(const char* value) {
-  _set_bit(1);
-  if (parameter_ == &_default_parameter_) {
+  set_has_parameter();
+  if (parameter_ == &::google::protobuf::internal::kEmptyString) {
     parameter_ = new ::std::string;
   }
   parameter_->assign(value);
 }
 inline void CodeGeneratorRequest::set_parameter(const char* value, size_t size) {
-  _set_bit(1);
-  if (parameter_ == &_default_parameter_) {
+  set_has_parameter();
+  if (parameter_ == &::google::protobuf::internal::kEmptyString) {
     parameter_ = new ::std::string;
   }
   parameter_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* CodeGeneratorRequest::mutable_parameter() {
-  _set_bit(1);
-  if (parameter_ == &_default_parameter_) {
+  set_has_parameter();
+  if (parameter_ == &::google::protobuf::internal::kEmptyString) {
     parameter_ = new ::std::string;
   }
   return parameter_;
 }
+inline ::std::string* CodeGeneratorRequest::release_parameter() {
+  clear_has_parameter();
+  if (parameter_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = parameter_;
+    parameter_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
 inline int CodeGeneratorRequest::proto_file_size() const {
@@ -511,129 +510,177 @@
 
 // optional string name = 1;
 inline bool CodeGeneratorResponse_File::has_name() const {
-  return _has_bit(0);
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void CodeGeneratorResponse_File::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void CodeGeneratorResponse_File::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
 }
 inline void CodeGeneratorResponse_File::clear_name() {
-  if (name_ != &_default_name_) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
     name_->clear();
   }
-  _clear_bit(0);
+  clear_has_name();
 }
 inline const ::std::string& CodeGeneratorResponse_File::name() const {
   return *name_;
 }
 inline void CodeGeneratorResponse_File::set_name(const ::std::string& value) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(value);
 }
 inline void CodeGeneratorResponse_File::set_name(const char* value) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(value);
 }
 inline void CodeGeneratorResponse_File::set_name(const char* value, size_t size) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* CodeGeneratorResponse_File::mutable_name() {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   return name_;
 }
+inline ::std::string* CodeGeneratorResponse_File::release_name() {
+  clear_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = name_;
+    name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // optional string insertion_point = 2;
 inline bool CodeGeneratorResponse_File::has_insertion_point() const {
-  return _has_bit(1);
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void CodeGeneratorResponse_File::set_has_insertion_point() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void CodeGeneratorResponse_File::clear_has_insertion_point() {
+  _has_bits_[0] &= ~0x00000002u;
 }
 inline void CodeGeneratorResponse_File::clear_insertion_point() {
-  if (insertion_point_ != &_default_insertion_point_) {
+  if (insertion_point_ != &::google::protobuf::internal::kEmptyString) {
     insertion_point_->clear();
   }
-  _clear_bit(1);
+  clear_has_insertion_point();
 }
 inline const ::std::string& CodeGeneratorResponse_File::insertion_point() const {
   return *insertion_point_;
 }
 inline void CodeGeneratorResponse_File::set_insertion_point(const ::std::string& value) {
-  _set_bit(1);
-  if (insertion_point_ == &_default_insertion_point_) {
+  set_has_insertion_point();
+  if (insertion_point_ == &::google::protobuf::internal::kEmptyString) {
     insertion_point_ = new ::std::string;
   }
   insertion_point_->assign(value);
 }
 inline void CodeGeneratorResponse_File::set_insertion_point(const char* value) {
-  _set_bit(1);
-  if (insertion_point_ == &_default_insertion_point_) {
+  set_has_insertion_point();
+  if (insertion_point_ == &::google::protobuf::internal::kEmptyString) {
     insertion_point_ = new ::std::string;
   }
   insertion_point_->assign(value);
 }
 inline void CodeGeneratorResponse_File::set_insertion_point(const char* value, size_t size) {
-  _set_bit(1);
-  if (insertion_point_ == &_default_insertion_point_) {
+  set_has_insertion_point();
+  if (insertion_point_ == &::google::protobuf::internal::kEmptyString) {
     insertion_point_ = new ::std::string;
   }
   insertion_point_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* CodeGeneratorResponse_File::mutable_insertion_point() {
-  _set_bit(1);
-  if (insertion_point_ == &_default_insertion_point_) {
+  set_has_insertion_point();
+  if (insertion_point_ == &::google::protobuf::internal::kEmptyString) {
     insertion_point_ = new ::std::string;
   }
   return insertion_point_;
 }
+inline ::std::string* CodeGeneratorResponse_File::release_insertion_point() {
+  clear_has_insertion_point();
+  if (insertion_point_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = insertion_point_;
+    insertion_point_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // optional string content = 15;
 inline bool CodeGeneratorResponse_File::has_content() const {
-  return _has_bit(2);
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void CodeGeneratorResponse_File::set_has_content() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void CodeGeneratorResponse_File::clear_has_content() {
+  _has_bits_[0] &= ~0x00000004u;
 }
 inline void CodeGeneratorResponse_File::clear_content() {
-  if (content_ != &_default_content_) {
+  if (content_ != &::google::protobuf::internal::kEmptyString) {
     content_->clear();
   }
-  _clear_bit(2);
+  clear_has_content();
 }
 inline const ::std::string& CodeGeneratorResponse_File::content() const {
   return *content_;
 }
 inline void CodeGeneratorResponse_File::set_content(const ::std::string& value) {
-  _set_bit(2);
-  if (content_ == &_default_content_) {
+  set_has_content();
+  if (content_ == &::google::protobuf::internal::kEmptyString) {
     content_ = new ::std::string;
   }
   content_->assign(value);
 }
 inline void CodeGeneratorResponse_File::set_content(const char* value) {
-  _set_bit(2);
-  if (content_ == &_default_content_) {
+  set_has_content();
+  if (content_ == &::google::protobuf::internal::kEmptyString) {
     content_ = new ::std::string;
   }
   content_->assign(value);
 }
 inline void CodeGeneratorResponse_File::set_content(const char* value, size_t size) {
-  _set_bit(2);
-  if (content_ == &_default_content_) {
+  set_has_content();
+  if (content_ == &::google::protobuf::internal::kEmptyString) {
     content_ = new ::std::string;
   }
   content_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* CodeGeneratorResponse_File::mutable_content() {
-  _set_bit(2);
-  if (content_ == &_default_content_) {
+  set_has_content();
+  if (content_ == &::google::protobuf::internal::kEmptyString) {
     content_ = new ::std::string;
   }
   return content_;
 }
+inline ::std::string* CodeGeneratorResponse_File::release_content() {
+  clear_has_content();
+  if (content_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = content_;
+    content_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // -------------------------------------------------------------------
 
@@ -641,45 +688,61 @@
 
 // optional string error = 1;
 inline bool CodeGeneratorResponse::has_error() const {
-  return _has_bit(0);
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void CodeGeneratorResponse::set_has_error() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void CodeGeneratorResponse::clear_has_error() {
+  _has_bits_[0] &= ~0x00000001u;
 }
 inline void CodeGeneratorResponse::clear_error() {
-  if (error_ != &_default_error_) {
+  if (error_ != &::google::protobuf::internal::kEmptyString) {
     error_->clear();
   }
-  _clear_bit(0);
+  clear_has_error();
 }
 inline const ::std::string& CodeGeneratorResponse::error() const {
   return *error_;
 }
 inline void CodeGeneratorResponse::set_error(const ::std::string& value) {
-  _set_bit(0);
-  if (error_ == &_default_error_) {
+  set_has_error();
+  if (error_ == &::google::protobuf::internal::kEmptyString) {
     error_ = new ::std::string;
   }
   error_->assign(value);
 }
 inline void CodeGeneratorResponse::set_error(const char* value) {
-  _set_bit(0);
-  if (error_ == &_default_error_) {
+  set_has_error();
+  if (error_ == &::google::protobuf::internal::kEmptyString) {
     error_ = new ::std::string;
   }
   error_->assign(value);
 }
 inline void CodeGeneratorResponse::set_error(const char* value, size_t size) {
-  _set_bit(0);
-  if (error_ == &_default_error_) {
+  set_has_error();
+  if (error_ == &::google::protobuf::internal::kEmptyString) {
     error_ = new ::std::string;
   }
   error_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* CodeGeneratorResponse::mutable_error() {
-  _set_bit(0);
-  if (error_ == &_default_error_) {
+  set_has_error();
+  if (error_ == &::google::protobuf::internal::kEmptyString) {
     error_ = new ::std::string;
   }
   return error_;
 }
+inline ::std::string* CodeGeneratorResponse::release_error() {
+  clear_has_error();
+  if (error_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = error_;
+    error_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
 inline int CodeGeneratorResponse::file_size() const {
diff --git a/src/google/protobuf/compiler/plugin.proto b/src/google/protobuf/compiler/plugin.proto
index 4e928b0..651ed10 100644
--- a/src/google/protobuf/compiler/plugin.proto
+++ b/src/google/protobuf/compiler/plugin.proto
@@ -131,7 +131,7 @@
     // in order to work correctly in that context.
     //
     // The code generator that generates the initial file and the one which
-    // inserts into it must both run as part of a single invocatino of protoc.
+    // inserts into it must both run as part of a single invocation of protoc.
     // Code generators are executed in the order in which they appear on the
     // command line.
     //
diff --git a/src/google/protobuf/compiler/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc
index fae83a3..9b10937 100644
--- a/src/google/protobuf/compiler/python/python_generator.cc
+++ b/src/google/protobuf/compiler/python/python_generator.cc
@@ -230,7 +230,7 @@
 
 bool Generator::Generate(const FileDescriptor* file,
                          const string& parameter,
-                         OutputDirectory* output_directory,
+                         GeneratorContext* context,
                          string* error) const {
 
   // Completely serialize all Generate() calls on this instance.  The
@@ -252,20 +252,18 @@
   fdp.SerializeToString(&file_descriptor_serialized_);
 
 
-  scoped_ptr<io::ZeroCopyOutputStream> output(output_directory->Open(filename));
+  scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
   GOOGLE_CHECK(output.get());
   io::Printer printer(output.get(), '$');
   printer_ = &printer;
 
   PrintTopBoilerplate(printer_, file_, GeneratingDescriptorProto());
+  PrintImports();
   PrintFileDescriptor();
   PrintTopLevelEnums();
   PrintTopLevelExtensions();
   PrintAllNestedEnumsInFile();
   PrintMessageDescriptors();
-  // We have to print the imports after the descriptors, so that mutually
-  // recursive protos in separate files can successfully reference each other.
-  PrintImports();
   FixForeignFieldsInDescriptors();
   PrintMessages();
   // We have to fix up the extensions after the message classes themselves,
@@ -377,7 +375,7 @@
   printer_->Print("containing_type=None,\n");
   printer_->Print("options=$options_value$,\n",
                   "options_value",
-                  OptionsValue("EnumOptions", CEscape(options_string)));
+                  OptionsValue("EnumOptions", options_string));
   EnumDescriptorProto edp;
   PrintSerializedPbInterval(enum_descriptor, edp);
   printer_->Outdent();
@@ -674,6 +672,17 @@
   }
 }
 
+void Generator::AddMessageToFileDescriptor(const Descriptor& descriptor) const {
+  map<string, string> m;
+  m["descriptor_name"] = kDescriptorKey;
+  m["message_name"] = descriptor.name();
+  m["message_descriptor_name"] = ModuleLevelDescriptorName(descriptor);
+  const char file_descriptor_template[] =
+      "$descriptor_name$.message_types_by_name['$message_name$'] = "
+      "$message_descriptor_name$\n";
+  printer_->Print(m, file_descriptor_template);
+}
+
 // Sets any necessary message_type and enum_type attributes
 // for the Python version of |field|.
 //
@@ -752,6 +761,9 @@
   for (int i = 0; i < file_->message_type_count(); ++i) {
     FixForeignFieldsInDescriptor(*file_->message_type(i), NULL);
   }
+  for (int i = 0; i < file_->message_type_count(); ++i) {
+    AddMessageToFileDescriptor(*file_->message_type(i));
+  }
   printer_->Print("\n");
 }
 
@@ -823,6 +835,8 @@
       "  type=None)");
 }
 
+// Returns a Python expression that calls descriptor._ParseOptions using
+// the given descriptor class name and serialized options protobuf string.
 string Generator::OptionsValue(
     const string& class_name, const string& serialized_options) const {
   if (serialized_options.length() == 0 || GeneratingDescriptorProto()) {
diff --git a/src/google/protobuf/compiler/python/python_generator.h b/src/google/protobuf/compiler/python/python_generator.h
index 43c2087..84eaf8a 100644
--- a/src/google/protobuf/compiler/python/python_generator.h
+++ b/src/google/protobuf/compiler/python/python_generator.h
@@ -66,7 +66,7 @@
   // CodeGenerator methods.
   virtual bool Generate(const FileDescriptor* file,
                         const string& parameter,
-                        OutputDirectory* output_directory,
+                        GeneratorContext* generator_context,
                         string* error) const;
 
  private:
@@ -104,6 +104,7 @@
   void FixForeignFieldsInField(const Descriptor* containing_type,
                                const FieldDescriptor& field,
                                const string& python_dict_name) const;
+  void AddMessageToFileDescriptor(const Descriptor& descriptor) const;
   string FieldReferencingExpression(const Descriptor* containing_type,
                                     const FieldDescriptor& field,
                                     const string& python_dict_name) const;
diff --git a/src/google/protobuf/compiler/python/python_plugin_unittest.cc b/src/google/protobuf/compiler/python/python_plugin_unittest.cc
index fde8876..da619ad 100644
--- a/src/google/protobuf/compiler/python/python_plugin_unittest.cc
+++ b/src/google/protobuf/compiler/python/python_plugin_unittest.cc
@@ -56,19 +56,19 @@
 
   virtual bool Generate(const FileDescriptor* file,
                         const string& parameter,
-                        OutputDirectory* output_directory,
+                        GeneratorContext* context,
                         string* error) const {
-    TryInsert("test_pb2.py", "imports", output_directory);
-    TryInsert("test_pb2.py", "module_scope", output_directory);
-    TryInsert("test_pb2.py", "class_scope:foo.Bar", output_directory);
-    TryInsert("test_pb2.py", "class_scope:foo.Bar.Baz", output_directory);
+    TryInsert("test_pb2.py", "imports", context);
+    TryInsert("test_pb2.py", "module_scope", context);
+    TryInsert("test_pb2.py", "class_scope:foo.Bar", context);
+    TryInsert("test_pb2.py", "class_scope:foo.Bar.Baz", context);
     return true;
   }
 
   void TryInsert(const string& filename, const string& insertion_point,
-                 OutputDirectory* output_directory) const {
+                 GeneratorContext* context) const {
     scoped_ptr<io::ZeroCopyOutputStream> output(
-      output_directory->OpenForInsert(filename, insertion_point));
+      context->OpenForInsert(filename, insertion_point));
     io::Printer printer(output.get(), '$');
     printer.Print("// inserted $name$\n", "name", insertion_point);
   }
diff --git a/src/google/protobuf/compiler/subprocess.cc b/src/google/protobuf/compiler/subprocess.cc
index dbd813e..5fb5d5c 100644
--- a/src/google/protobuf/compiler/subprocess.cc
+++ b/src/google/protobuf/compiler/subprocess.cc
@@ -32,6 +32,8 @@
 
 #include <google/protobuf/compiler/subprocess.h>
 
+#include <algorithm>
+
 #ifndef _WIN32
 #include <errno.h>
 #include <sys/select.h>
@@ -39,7 +41,6 @@
 #include <signal.h>
 #endif
 
-#include <algorithm>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/message.h>
 #include <google/protobuf/stubs/substitute.h>
diff --git a/src/google/protobuf/compiler/subprocess.h b/src/google/protobuf/compiler/subprocess.h
index 7a6fa70..de9fce9 100644
--- a/src/google/protobuf/compiler/subprocess.h
+++ b/src/google/protobuf/compiler/subprocess.h
@@ -40,9 +40,10 @@
 #include <sys/types.h>
 #include <unistd.h>
 #endif  // !_WIN32
+#include <google/protobuf/stubs/common.h>
 
 #include <string>
-#include <google/protobuf/stubs/common.h>
+
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/zip_output_unittest.sh b/src/google/protobuf/compiler/zip_output_unittest.sh
index 259d5d2..3a02436 100755
--- a/src/google/protobuf/compiler/zip_output_unittest.sh
+++ b/src/google/protobuf/compiler/zip_output_unittest.sh
@@ -39,45 +39,51 @@
   exit 1
 }
 
+TEST_TMPDIR=.
+PROTOC=./protoc
+
 echo '
+  syntax = "proto2";
   option java_multiple_files = true;
   option java_package = "test.jar";
   option java_outer_classname = "Outer";
   message Foo {}
   message Bar {}
-' > testzip.proto
+' > $TEST_TMPDIR/testzip.proto
 
-./protoc --cpp_out=testzip.zip --python_out=testzip.zip --java_out=testzip.jar \
-    testzip.proto || fail 'protoc failed.'
+$PROTOC \
+    --cpp_out=$TEST_TMPDIR/testzip.zip --python_out=$TEST_TMPDIR/testzip.zip \
+    --java_out=$TEST_TMPDIR/testzip.jar -I$TEST_TMPDIR testzip.proto \
+    || fail 'protoc failed.'
 
 echo "Testing output to zip..."
 if unzip -h > /dev/null; then
-  unzip -t testzip.zip > testzip.list || fail 'unzip failed.'
+  unzip -t $TEST_TMPDIR/testzip.zip > $TEST_TMPDIR/testzip.list || fail 'unzip failed.'
 
-  grep 'testing: testzip\.pb\.cc *OK$' testzip.list > /dev/null \
+  grep 'testing: testzip\.pb\.cc *OK$' $TEST_TMPDIR/testzip.list > /dev/null \
     || fail 'testzip.pb.cc not found in output zip.'
-  grep 'testing: testzip\.pb\.h *OK$' testzip.list > /dev/null \
+  grep 'testing: testzip\.pb\.h *OK$' $TEST_TMPDIR/testzip.list > /dev/null \
     || fail 'testzip.pb.h not found in output zip.'
-  grep 'testing: testzip_pb2\.py *OK$' testzip.list > /dev/null \
+  grep 'testing: testzip_pb2\.py *OK$' $TEST_TMPDIR/testzip.list > /dev/null \
     || fail 'testzip_pb2.py not found in output zip.'
-  grep -i 'manifest' testzip.list > /dev/null \
+  grep -i 'manifest' $TEST_TMPDIR/testzip.list > /dev/null \
     && fail 'Zip file contained manifest.'
 else
   echo "Warning:  'unzip' command not available.  Skipping test."
 fi
 
 echo "Testing output to jar..."
-if jar c testzip.proto > /dev/null; then
-  jar tf testzip.jar > testzip.list || fail 'jar failed.'
+if jar c $TEST_TMPDIR/testzip.proto > /dev/null; then
+  jar tf $TEST_TMPDIR/testzip.jar > $TEST_TMPDIR/testzip.list || fail 'jar failed.'
 
-  grep '^test/jar/Foo\.java$' testzip.list > /dev/null \
+  grep '^test/jar/Foo\.java$' $TEST_TMPDIR/testzip.list > /dev/null \
     || fail 'Foo.java not found in output jar.'
-  grep '^test/jar/Bar\.java$' testzip.list > /dev/null \
+  grep '^test/jar/Bar\.java$' $TEST_TMPDIR/testzip.list > /dev/null \
     || fail 'Bar.java not found in output jar.'
-  grep '^test/jar/Outer\.java$' testzip.list > /dev/null \
+  grep '^test/jar/Outer\.java$' $TEST_TMPDIR/testzip.list > /dev/null \
     || fail 'Outer.java not found in output jar.'
-  grep '^META-INF/MANIFEST\.MF$' testzip.list > /dev/null \
-    || fail 'Manifest not ofund in output jar.'
+  grep '^META-INF/MANIFEST\.MF$' $TEST_TMPDIR/testzip.list > /dev/null \
+    || fail 'Manifest not found in output jar.'
 else
   echo "Warning:  'jar' command not available.  Skipping test."
 fi
diff --git a/src/google/protobuf/compiler/zip_writer.cc b/src/google/protobuf/compiler/zip_writer.cc
index 53c1877..65d7352 100644
--- a/src/google/protobuf/compiler/zip_writer.cc
+++ b/src/google/protobuf/compiler/zip_writer.cc
@@ -28,6 +28,36 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
 // Author: ambrose@google.com (Ambrose Feinstein),
 //         kenton@google.com (Kenton Varda)
 //
@@ -183,6 +213,6 @@
   return output.HadError();
 }
 
-}  // namespace google
-}  // namespace protobuf
 }  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/zip_writer.h b/src/google/protobuf/compiler/zip_writer.h
index 4289553..be73972 100644
--- a/src/google/protobuf/compiler/zip_writer.h
+++ b/src/google/protobuf/compiler/zip_writer.h
@@ -28,6 +28,36 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
 // Author: kenton@google.com (Kenton Varda)
 
 #include <vector>
@@ -58,6 +88,6 @@
   vector<FileInfo> files_;
 };
 
-}  // namespace google
-}  // namespace protobuf
 }  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc
index 9226dfb..76b7219 100644
--- a/src/google/protobuf/descriptor.cc
+++ b/src/google/protobuf/descriptor.cc
@@ -42,10 +42,12 @@
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/descriptor_database.h>
 #include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/dynamic_message.h>
 #include <google/protobuf/text_format.h>
 #include <google/protobuf/unknown_field_set.h>
 #include <google/protobuf/wire_format.h>
 #include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/tokenizer.h>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/once.h>
@@ -2056,6 +2058,8 @@
     // Otherwise returns true.
     bool InterpretOptions(OptionsToInterpret* options_to_interpret);
 
+    class AggregateOptionFinder;
+
    private:
     // Interprets uninterpreted_option_ on the specified message, which
     // must be the mutable copy of the original options message to which
@@ -2082,6 +2086,11 @@
     bool SetOptionValue(const FieldDescriptor* option_field,
                         UnknownFieldSet* unknown_fields);
 
+    // Parses an aggregate value for a CPPTYPE_MESSAGE option and
+    // saves it into *unknown_fields.
+    bool SetAggregateOption(const FieldDescriptor* option_field,
+                            UnknownFieldSet* unknown_fields);
+
     // Convenience functions to set an int field the right way, depending on
     // its wire type (a single int CppType can represent multiple wire types).
     void SetInt32(int number, int32 value, FieldDescriptor::Type type,
@@ -2128,6 +2137,10 @@
     // can use it to find locations recorded by the parser.
     const UninterpretedOption* uninterpreted_option_;
 
+    // Factory used to create the dynamic messages we need to parse
+    // any aggregate option values we encounter.
+    DynamicMessageFactory dynamic_factory_;
+
     GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OptionInterpreter);
   };
 
@@ -2139,6 +2152,8 @@
   // redundantly declare OptionInterpreter a friend just to make things extra
   // clear for these bad compilers.
   friend class OptionInterpreter;
+  friend class OptionInterpreter::AggregateOptionFinder;
+
   static inline bool get_allow_unknown(const DescriptorPool* pool) {
     return pool->allow_unknown_;
   }
@@ -3973,9 +3988,6 @@
         intermediate_fields.push_back(field);
         descriptor = field->message_type();
       }
-    } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
-      return AddNameError("Option field \"" + debug_msg_name +
-                          "\" cannot be of message type.");
     }
   }
 
@@ -4310,18 +4322,95 @@
       break;
 
     case FieldDescriptor::CPPTYPE_MESSAGE:
-      // We don't currently support defining a message-typed option, so we
-      // should never actually get here.
-      return AddValueError("Option \"" + option_field->full_name() +
-                           "\" is a message.  To set fields within it, use "
-                           "syntax like \"" + option_field->name() +
-                           ".foo = value\".");
+      if (!SetAggregateOption(option_field, unknown_fields)) {
+        return false;
+      }
       break;
   }
 
   return true;
 }
 
+class DescriptorBuilder::OptionInterpreter::AggregateOptionFinder
+    : public TextFormat::Finder {
+ public:
+  DescriptorBuilder* builder_;
+
+  virtual const FieldDescriptor* FindExtension(
+      Message* message, const string& name) const {
+    if (builder_->pool_->mutex_ != NULL) {
+      builder_->pool_->mutex_->AssertHeld();
+    }
+    Symbol result = builder_->LookupSymbolNoPlaceholder(
+        name, message->GetDescriptor()->full_name());
+    if (result.type == Symbol::FIELD &&
+        result.field_descriptor->is_extension()) {
+      return result.field_descriptor;
+    } else {
+      return NULL;
+    }
+  }
+};
+
+// A custom error collector to record any text-format parsing errors
+namespace {
+class AggregateErrorCollector : public io::ErrorCollector {
+ public:
+  string error_;
+
+  virtual void AddError(int line, int column, const string& message) {
+    if (!error_.empty()) {
+      error_ += "; ";
+    }
+    error_ += message;
+  }
+
+  virtual void AddWarning(int line, int column, const string& message) {
+    // Ignore warnings
+  }
+};
+}
+
+// We construct a dynamic message of the type corresponding to
+// option_field, parse the supplied text-format string into this
+// message, and serialize the resulting message to produce the value.
+bool DescriptorBuilder::OptionInterpreter::SetAggregateOption(
+    const FieldDescriptor* option_field,
+    UnknownFieldSet* unknown_fields) {
+  if (!uninterpreted_option_->has_aggregate_value()) {
+    return AddValueError("Option \"" + option_field->full_name() +
+                         "\" is a message. To set the entire message, use "
+                         "syntax like \"" + option_field->name() +
+                         " = { <proto text format> }\". "
+                         "To set fields within it, use "
+                         "syntax like \"" + option_field->name() +
+                         ".foo = value\".");
+  }
+
+  const Descriptor* type = option_field->message_type();
+  scoped_ptr<Message> dynamic(dynamic_factory_.GetPrototype(type)->New());
+  GOOGLE_CHECK(dynamic.get() != NULL)
+      << "Could not create an instance of " << option_field->DebugString();
+
+  AggregateErrorCollector collector;
+  AggregateOptionFinder finder;
+  finder.builder_ = builder_;
+  TextFormat::Parser parser;
+  parser.RecordErrorsTo(&collector);
+  parser.SetFinder(&finder);
+  if (!parser.ParseFromString(uninterpreted_option_->aggregate_value(),
+                              dynamic.get())) {
+    AddValueError("Error while parsing option value for \"" +
+                  option_field->name() + "\": " + collector.error_);
+    return false;
+  } else {
+    string serial;
+    dynamic->SerializeToString(&serial);  // Never fails
+    unknown_fields->AddLengthDelimited(option_field->number(), serial);
+    return true;
+  }
+}
+
 void DescriptorBuilder::OptionInterpreter::SetInt32(int number, int32 value,
     FieldDescriptor::Type type, UnknownFieldSet* unknown_fields) {
   switch (type) {
diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc
index 922237f..87303ef 100644
--- a/src/google/protobuf/descriptor.pb.cc
+++ b/src/google/protobuf/descriptor.pb.cc
@@ -76,6 +76,12 @@
 const ::google::protobuf::Descriptor* UninterpretedOption_NamePart_descriptor_ = NULL;
 const ::google::protobuf::internal::GeneratedMessageReflection*
   UninterpretedOption_NamePart_reflection_ = NULL;
+const ::google::protobuf::Descriptor* SourceCodeInfo_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  SourceCodeInfo_reflection_ = NULL;
+const ::google::protobuf::Descriptor* SourceCodeInfo_Location_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  SourceCodeInfo_Location_reflection_ = NULL;
 
 }  // namespace
 
@@ -102,7 +108,7 @@
       ::google::protobuf::MessageFactory::generated_factory(),
       sizeof(FileDescriptorSet));
   FileDescriptorProto_descriptor_ = file->message_type(1);
-  static const int FileDescriptorProto_offsets_[8] = {
+  static const int FileDescriptorProto_offsets_[9] = {
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, name_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, package_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, dependency_),
@@ -111,6 +117,7 @@
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, service_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, extension_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, options_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, source_code_info_),
   };
   FileDescriptorProto_reflection_ =
     new ::google::protobuf::internal::GeneratedMessageReflection(
@@ -254,10 +261,11 @@
       ::google::protobuf::MessageFactory::generated_factory(),
       sizeof(MethodDescriptorProto));
   FileOptions_descriptor_ = file->message_type(8);
-  static const int FileOptions_offsets_[8] = {
+  static const int FileOptions_offsets_[9] = {
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_package_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_outer_classname_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_multiple_files_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_generate_equals_and_hash_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, optimize_for_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, cc_generic_services_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_generic_services_),
@@ -374,13 +382,14 @@
       ::google::protobuf::MessageFactory::generated_factory(),
       sizeof(MethodOptions));
   UninterpretedOption_descriptor_ = file->message_type(15);
-  static const int UninterpretedOption_offsets_[6] = {
+  static const int UninterpretedOption_offsets_[7] = {
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, name_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, identifier_value_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, positive_int_value_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, negative_int_value_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, double_value_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, string_value_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, aggregate_value_),
   };
   UninterpretedOption_reflection_ =
     new ::google::protobuf::internal::GeneratedMessageReflection(
@@ -409,6 +418,37 @@
       ::google::protobuf::DescriptorPool::generated_pool(),
       ::google::protobuf::MessageFactory::generated_factory(),
       sizeof(UninterpretedOption_NamePart));
+  SourceCodeInfo_descriptor_ = file->message_type(16);
+  static const int SourceCodeInfo_offsets_[1] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo, location_),
+  };
+  SourceCodeInfo_reflection_ =
+    new ::google::protobuf::internal::GeneratedMessageReflection(
+      SourceCodeInfo_descriptor_,
+      SourceCodeInfo::default_instance_,
+      SourceCodeInfo_offsets_,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo, _has_bits_[0]),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo, _unknown_fields_),
+      -1,
+      ::google::protobuf::DescriptorPool::generated_pool(),
+      ::google::protobuf::MessageFactory::generated_factory(),
+      sizeof(SourceCodeInfo));
+  SourceCodeInfo_Location_descriptor_ = SourceCodeInfo_descriptor_->nested_type(0);
+  static const int SourceCodeInfo_Location_offsets_[2] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, path_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, span_),
+  };
+  SourceCodeInfo_Location_reflection_ =
+    new ::google::protobuf::internal::GeneratedMessageReflection(
+      SourceCodeInfo_Location_descriptor_,
+      SourceCodeInfo_Location::default_instance_,
+      SourceCodeInfo_Location_offsets_,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, _has_bits_[0]),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, _unknown_fields_),
+      -1,
+      ::google::protobuf::DescriptorPool::generated_pool(),
+      ::google::protobuf::MessageFactory::generated_factory(),
+      sizeof(SourceCodeInfo_Location));
 }
 
 namespace {
@@ -457,6 +497,10 @@
     UninterpretedOption_descriptor_, &UninterpretedOption::default_instance());
   ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
     UninterpretedOption_NamePart_descriptor_, &UninterpretedOption_NamePart::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+    SourceCodeInfo_descriptor_, &SourceCodeInfo::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+    SourceCodeInfo_Location_descriptor_, &SourceCodeInfo_Location::default_instance());
 }
 
 }  // namespace
@@ -498,6 +542,10 @@
   delete UninterpretedOption_reflection_;
   delete UninterpretedOption_NamePart::default_instance_;
   delete UninterpretedOption_NamePart_reflection_;
+  delete SourceCodeInfo::default_instance_;
+  delete SourceCodeInfo_reflection_;
+  delete SourceCodeInfo_Location::default_instance_;
+  delete SourceCodeInfo_Location_reflection_;
 }
 
 void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() {
@@ -510,7 +558,7 @@
     "\n google/protobuf/descriptor.proto\022\017goog"
     "le.protobuf\"G\n\021FileDescriptorSet\0222\n\004file"
     "\030\001 \003(\0132$.google.protobuf.FileDescriptorP"
-    "roto\"\334\002\n\023FileDescriptorProto\022\014\n\004name\030\001 \001"
+    "roto\"\227\003\n\023FileDescriptorProto\022\014\n\004name\030\001 \001"
     "(\t\022\017\n\007package\030\002 \001(\t\022\022\n\ndependency\030\003 \003(\t\022"
     "6\n\014message_type\030\004 \003(\0132 .google.protobuf."
     "DescriptorProto\0227\n\tenum_type\030\005 \003(\0132$.goo"
@@ -518,88 +566,94 @@
     "ice\030\006 \003(\0132\'.google.protobuf.ServiceDescr"
     "iptorProto\0228\n\textension\030\007 \003(\0132%.google.p"
     "rotobuf.FieldDescriptorProto\022-\n\007options\030"
-    "\010 \001(\0132\034.google.protobuf.FileOptions\"\251\003\n\017"
-    "DescriptorProto\022\014\n\004name\030\001 \001(\t\0224\n\005field\030\002"
-    " \003(\0132%.google.protobuf.FieldDescriptorPr"
-    "oto\0228\n\textension\030\006 \003(\0132%.google.protobuf"
-    ".FieldDescriptorProto\0225\n\013nested_type\030\003 \003"
-    "(\0132 .google.protobuf.DescriptorProto\0227\n\t"
-    "enum_type\030\004 \003(\0132$.google.protobuf.EnumDe"
-    "scriptorProto\022H\n\017extension_range\030\005 \003(\0132/"
-    ".google.protobuf.DescriptorProto.Extensi"
-    "onRange\0220\n\007options\030\007 \001(\0132\037.google.protob"
-    "uf.MessageOptions\032,\n\016ExtensionRange\022\r\n\005s"
-    "tart\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\"\224\005\n\024FieldDescrip"
-    "torProto\022\014\n\004name\030\001 \001(\t\022\016\n\006number\030\003 \001(\005\022:"
-    "\n\005label\030\004 \001(\0162+.google.protobuf.FieldDes"
-    "criptorProto.Label\0228\n\004type\030\005 \001(\0162*.googl"
-    "e.protobuf.FieldDescriptorProto.Type\022\021\n\t"
-    "type_name\030\006 \001(\t\022\020\n\010extendee\030\002 \001(\t\022\025\n\rdef"
-    "ault_value\030\007 \001(\t\022.\n\007options\030\010 \001(\0132\035.goog"
-    "le.protobuf.FieldOptions\"\266\002\n\004Type\022\017\n\013TYP"
-    "E_DOUBLE\020\001\022\016\n\nTYPE_FLOAT\020\002\022\016\n\nTYPE_INT64"
-    "\020\003\022\017\n\013TYPE_UINT64\020\004\022\016\n\nTYPE_INT32\020\005\022\020\n\014T"
-    "YPE_FIXED64\020\006\022\020\n\014TYPE_FIXED32\020\007\022\r\n\tTYPE_"
-    "BOOL\020\010\022\017\n\013TYPE_STRING\020\t\022\016\n\nTYPE_GROUP\020\n\022"
-    "\020\n\014TYPE_MESSAGE\020\013\022\016\n\nTYPE_BYTES\020\014\022\017\n\013TYP"
-    "E_UINT32\020\r\022\r\n\tTYPE_ENUM\020\016\022\021\n\rTYPE_SFIXED"
-    "32\020\017\022\021\n\rTYPE_SFIXED64\020\020\022\017\n\013TYPE_SINT32\020\021"
-    "\022\017\n\013TYPE_SINT64\020\022\"C\n\005Label\022\022\n\016LABEL_OPTI"
-    "ONAL\020\001\022\022\n\016LABEL_REQUIRED\020\002\022\022\n\016LABEL_REPE"
-    "ATED\020\003\"\214\001\n\023EnumDescriptorProto\022\014\n\004name\030\001"
-    " \001(\t\0228\n\005value\030\002 \003(\0132).google.protobuf.En"
-    "umValueDescriptorProto\022-\n\007options\030\003 \001(\0132"
-    "\034.google.protobuf.EnumOptions\"l\n\030EnumVal"
-    "ueDescriptorProto\022\014\n\004name\030\001 \001(\t\022\016\n\006numbe"
-    "r\030\002 \001(\005\0222\n\007options\030\003 \001(\0132!.google.protob"
-    "uf.EnumValueOptions\"\220\001\n\026ServiceDescripto"
-    "rProto\022\014\n\004name\030\001 \001(\t\0226\n\006method\030\002 \003(\0132&.g"
-    "oogle.protobuf.MethodDescriptorProto\0220\n\007"
-    "options\030\003 \001(\0132\037.google.protobuf.ServiceO"
-    "ptions\"\177\n\025MethodDescriptorProto\022\014\n\004name\030"
-    "\001 \001(\t\022\022\n\ninput_type\030\002 \001(\t\022\023\n\013output_type"
-    "\030\003 \001(\t\022/\n\007options\030\004 \001(\0132\036.google.protobu"
-    "f.MethodOptions\"\244\003\n\013FileOptions\022\024\n\014java_"
-    "package\030\001 \001(\t\022\034\n\024java_outer_classname\030\010 "
-    "\001(\t\022\"\n\023java_multiple_files\030\n \001(\010:\005false\022"
-    "F\n\014optimize_for\030\t \001(\0162).google.protobuf."
-    "FileOptions.OptimizeMode:\005SPEED\022!\n\023cc_ge"
-    "neric_services\030\020 \001(\010:\004true\022#\n\025java_gener"
-    "ic_services\030\021 \001(\010:\004true\022!\n\023py_generic_se"
-    "rvices\030\022 \001(\010:\004true\022C\n\024uninterpreted_opti"
-    "on\030\347\007 \003(\0132$.google.protobuf.Uninterprete"
-    "dOption\":\n\014OptimizeMode\022\t\n\005SPEED\020\001\022\r\n\tCO"
-    "DE_SIZE\020\002\022\020\n\014LITE_RUNTIME\020\003*\t\010\350\007\020\200\200\200\200\002\"\270"
-    "\001\n\016MessageOptions\022&\n\027message_set_wire_fo"
-    "rmat\030\001 \001(\010:\005false\022.\n\037no_standard_descrip"
-    "tor_accessor\030\002 \001(\010:\005false\022C\n\024uninterpret"
+    "\010 \001(\0132\034.google.protobuf.FileOptions\0229\n\020s"
+    "ource_code_info\030\t \001(\0132\037.google.protobuf."
+    "SourceCodeInfo\"\251\003\n\017DescriptorProto\022\014\n\004na"
+    "me\030\001 \001(\t\0224\n\005field\030\002 \003(\0132%.google.protobu"
+    "f.FieldDescriptorProto\0228\n\textension\030\006 \003("
+    "\0132%.google.protobuf.FieldDescriptorProto"
+    "\0225\n\013nested_type\030\003 \003(\0132 .google.protobuf."
+    "DescriptorProto\0227\n\tenum_type\030\004 \003(\0132$.goo"
+    "gle.protobuf.EnumDescriptorProto\022H\n\017exte"
+    "nsion_range\030\005 \003(\0132/.google.protobuf.Desc"
+    "riptorProto.ExtensionRange\0220\n\007options\030\007 "
+    "\001(\0132\037.google.protobuf.MessageOptions\032,\n\016"
+    "ExtensionRange\022\r\n\005start\030\001 \001(\005\022\013\n\003end\030\002 \001"
+    "(\005\"\224\005\n\024FieldDescriptorProto\022\014\n\004name\030\001 \001("
+    "\t\022\016\n\006number\030\003 \001(\005\022:\n\005label\030\004 \001(\0162+.googl"
+    "e.protobuf.FieldDescriptorProto.Label\0228\n"
+    "\004type\030\005 \001(\0162*.google.protobuf.FieldDescr"
+    "iptorProto.Type\022\021\n\ttype_name\030\006 \001(\t\022\020\n\010ex"
+    "tendee\030\002 \001(\t\022\025\n\rdefault_value\030\007 \001(\t\022.\n\007o"
+    "ptions\030\010 \001(\0132\035.google.protobuf.FieldOpti"
+    "ons\"\266\002\n\004Type\022\017\n\013TYPE_DOUBLE\020\001\022\016\n\nTYPE_FL"
+    "OAT\020\002\022\016\n\nTYPE_INT64\020\003\022\017\n\013TYPE_UINT64\020\004\022\016"
+    "\n\nTYPE_INT32\020\005\022\020\n\014TYPE_FIXED64\020\006\022\020\n\014TYPE"
+    "_FIXED32\020\007\022\r\n\tTYPE_BOOL\020\010\022\017\n\013TYPE_STRING"
+    "\020\t\022\016\n\nTYPE_GROUP\020\n\022\020\n\014TYPE_MESSAGE\020\013\022\016\n\n"
+    "TYPE_BYTES\020\014\022\017\n\013TYPE_UINT32\020\r\022\r\n\tTYPE_EN"
+    "UM\020\016\022\021\n\rTYPE_SFIXED32\020\017\022\021\n\rTYPE_SFIXED64"
+    "\020\020\022\017\n\013TYPE_SINT32\020\021\022\017\n\013TYPE_SINT64\020\022\"C\n\005"
+    "Label\022\022\n\016LABEL_OPTIONAL\020\001\022\022\n\016LABEL_REQUI"
+    "RED\020\002\022\022\n\016LABEL_REPEATED\020\003\"\214\001\n\023EnumDescri"
+    "ptorProto\022\014\n\004name\030\001 \001(\t\0228\n\005value\030\002 \003(\0132)"
+    ".google.protobuf.EnumValueDescriptorProt"
+    "o\022-\n\007options\030\003 \001(\0132\034.google.protobuf.Enu"
+    "mOptions\"l\n\030EnumValueDescriptorProto\022\014\n\004"
+    "name\030\001 \001(\t\022\016\n\006number\030\002 \001(\005\0222\n\007options\030\003 "
+    "\001(\0132!.google.protobuf.EnumValueOptions\"\220"
+    "\001\n\026ServiceDescriptorProto\022\014\n\004name\030\001 \001(\t\022"
+    "6\n\006method\030\002 \003(\0132&.google.protobuf.Method"
+    "DescriptorProto\0220\n\007options\030\003 \001(\0132\037.googl"
+    "e.protobuf.ServiceOptions\"\177\n\025MethodDescr"
+    "iptorProto\022\014\n\004name\030\001 \001(\t\022\022\n\ninput_type\030\002"
+    " \001(\t\022\023\n\013output_type\030\003 \001(\t\022/\n\007options\030\004 \001"
+    "(\0132\036.google.protobuf.MethodOptions\"\325\003\n\013F"
+    "ileOptions\022\024\n\014java_package\030\001 \001(\t\022\034\n\024java"
+    "_outer_classname\030\010 \001(\t\022\"\n\023java_multiple_"
+    "files\030\n \001(\010:\005false\022,\n\035java_generate_equa"
+    "ls_and_hash\030\024 \001(\010:\005false\022F\n\014optimize_for"
+    "\030\t \001(\0162).google.protobuf.FileOptions.Opt"
+    "imizeMode:\005SPEED\022\"\n\023cc_generic_services\030"
+    "\020 \001(\010:\005false\022$\n\025java_generic_services\030\021 "
+    "\001(\010:\005false\022\"\n\023py_generic_services\030\022 \001(\010:"
+    "\005false\022C\n\024uninterpreted_option\030\347\007 \003(\0132$."
+    "google.protobuf.UninterpretedOption\":\n\014O"
+    "ptimizeMode\022\t\n\005SPEED\020\001\022\r\n\tCODE_SIZE\020\002\022\020\n"
+    "\014LITE_RUNTIME\020\003*\t\010\350\007\020\200\200\200\200\002\"\270\001\n\016MessageOp"
+    "tions\022&\n\027message_set_wire_format\030\001 \001(\010:\005"
+    "false\022.\n\037no_standard_descriptor_accessor"
+    "\030\002 \001(\010:\005false\022C\n\024uninterpreted_option\030\347\007"
+    " \003(\0132$.google.protobuf.UninterpretedOpti"
+    "on*\t\010\350\007\020\200\200\200\200\002\"\224\002\n\014FieldOptions\022:\n\005ctype\030"
+    "\001 \001(\0162#.google.protobuf.FieldOptions.CTy"
+    "pe:\006STRING\022\016\n\006packed\030\002 \001(\010\022\031\n\ndeprecated"
+    "\030\003 \001(\010:\005false\022\034\n\024experimental_map_key\030\t "
+    "\001(\t\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.goo"
+    "gle.protobuf.UninterpretedOption\"/\n\005CTyp"
+    "e\022\n\n\006STRING\020\000\022\010\n\004CORD\020\001\022\020\n\014STRING_PIECE\020"
+    "\002*\t\010\350\007\020\200\200\200\200\002\"]\n\013EnumOptions\022C\n\024uninterpr"
+    "eted_option\030\347\007 \003(\0132$.google.protobuf.Uni"
+    "nterpretedOption*\t\010\350\007\020\200\200\200\200\002\"b\n\020EnumValue"
+    "Options\022C\n\024uninterpreted_option\030\347\007 \003(\0132$"
+    ".google.protobuf.UninterpretedOption*\t\010\350"
+    "\007\020\200\200\200\200\002\"`\n\016ServiceOptions\022C\n\024uninterpret"
     "ed_option\030\347\007 \003(\0132$.google.protobuf.Unint"
-    "erpretedOption*\t\010\350\007\020\200\200\200\200\002\"\224\002\n\014FieldOptio"
-    "ns\022:\n\005ctype\030\001 \001(\0162#.google.protobuf.Fiel"
-    "dOptions.CType:\006STRING\022\016\n\006packed\030\002 \001(\010\022\031"
-    "\n\ndeprecated\030\003 \001(\010:\005false\022\034\n\024experimenta"
-    "l_map_key\030\t \001(\t\022C\n\024uninterpreted_option\030"
-    "\347\007 \003(\0132$.google.protobuf.UninterpretedOp"
-    "tion\"/\n\005CType\022\n\n\006STRING\020\000\022\010\n\004CORD\020\001\022\020\n\014S"
-    "TRING_PIECE\020\002*\t\010\350\007\020\200\200\200\200\002\"]\n\013EnumOptions\022"
-    "C\n\024uninterpreted_option\030\347\007 \003(\0132$.google."
-    "protobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\""
-    "b\n\020EnumValueOptions\022C\n\024uninterpreted_opt"
-    "ion\030\347\007 \003(\0132$.google.protobuf.Uninterpret"
-    "edOption*\t\010\350\007\020\200\200\200\200\002\"`\n\016ServiceOptions\022C\n"
-    "\024uninterpreted_option\030\347\007 \003(\0132$.google.pr"
-    "otobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"_\n"
-    "\rMethodOptions\022C\n\024uninterpreted_option\030\347"
-    "\007 \003(\0132$.google.protobuf.UninterpretedOpt"
-    "ion*\t\010\350\007\020\200\200\200\200\002\"\205\002\n\023UninterpretedOption\022;"
-    "\n\004name\030\002 \003(\0132-.google.protobuf.Uninterpr"
-    "etedOption.NamePart\022\030\n\020identifier_value\030"
-    "\003 \001(\t\022\032\n\022positive_int_value\030\004 \001(\004\022\032\n\022neg"
-    "ative_int_value\030\005 \001(\003\022\024\n\014double_value\030\006 "
-    "\001(\001\022\024\n\014string_value\030\007 \001(\014\0323\n\010NamePart\022\021\n"
-    "\tname_part\030\001 \002(\t\022\024\n\014is_extension\030\002 \002(\010B)"
-    "\n\023com.google.protobufB\020DescriptorProtosH"
-    "\001", 3681);
+    "erpretedOption*\t\010\350\007\020\200\200\200\200\002\"_\n\rMethodOptio"
+    "ns\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.goog"
+    "le.protobuf.UninterpretedOption*\t\010\350\007\020\200\200\200"
+    "\200\002\"\236\002\n\023UninterpretedOption\022;\n\004name\030\002 \003(\013"
+    "2-.google.protobuf.UninterpretedOption.N"
+    "amePart\022\030\n\020identifier_value\030\003 \001(\t\022\032\n\022pos"
+    "itive_int_value\030\004 \001(\004\022\032\n\022negative_int_va"
+    "lue\030\005 \001(\003\022\024\n\014double_value\030\006 \001(\001\022\024\n\014strin"
+    "g_value\030\007 \001(\014\022\027\n\017aggregate_value\030\010 \001(\t\0323"
+    "\n\010NamePart\022\021\n\tname_part\030\001 \002(\t\022\024\n\014is_exte"
+    "nsion\030\002 \002(\010\"|\n\016SourceCodeInfo\022:\n\010locatio"
+    "n\030\001 \003(\0132(.google.protobuf.SourceCodeInfo"
+    ".Location\032.\n\010Location\022\020\n\004path\030\001 \003(\005B\002\020\001\022"
+    "\020\n\004span\030\002 \003(\005B\002\020\001B)\n\023com.google.protobuf"
+    "B\020DescriptorProtosH\001", 3940);
   ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
     "google/protobuf/descriptor.proto", &protobuf_RegisterTypes);
   FileDescriptorSet::default_instance_ = new FileDescriptorSet();
@@ -620,6 +674,8 @@
   MethodOptions::default_instance_ = new MethodOptions();
   UninterpretedOption::default_instance_ = new UninterpretedOption();
   UninterpretedOption_NamePart::default_instance_ = new UninterpretedOption_NamePart();
+  SourceCodeInfo::default_instance_ = new SourceCodeInfo();
+  SourceCodeInfo_Location::default_instance_ = new SourceCodeInfo_Location();
   FileDescriptorSet::default_instance_->InitAsDefaultInstance();
   FileDescriptorProto::default_instance_->InitAsDefaultInstance();
   DescriptorProto::default_instance_->InitAsDefaultInstance();
@@ -638,6 +694,8 @@
   MethodOptions::default_instance_->InitAsDefaultInstance();
   UninterpretedOption::default_instance_->InitAsDefaultInstance();
   UninterpretedOption_NamePart::default_instance_->InitAsDefaultInstance();
+  SourceCodeInfo::default_instance_->InitAsDefaultInstance();
+  SourceCodeInfo_Location::default_instance_->InitAsDefaultInstance();
   ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto);
 }
 
@@ -856,8 +914,6 @@
 
 // ===================================================================
 
-const ::std::string FileDescriptorProto::_default_name_;
-const ::std::string FileDescriptorProto::_default_package_;
 #ifndef _MSC_VER
 const int FileDescriptorProto::kNameFieldNumber;
 const int FileDescriptorProto::kPackageFieldNumber;
@@ -867,6 +923,7 @@
 const int FileDescriptorProto::kServiceFieldNumber;
 const int FileDescriptorProto::kExtensionFieldNumber;
 const int FileDescriptorProto::kOptionsFieldNumber;
+const int FileDescriptorProto::kSourceCodeInfoFieldNumber;
 #endif  // !_MSC_VER
 
 FileDescriptorProto::FileDescriptorProto()
@@ -876,6 +933,7 @@
 
 void FileDescriptorProto::InitAsDefaultInstance() {
   options_ = const_cast< ::google::protobuf::FileOptions*>(&::google::protobuf::FileOptions::default_instance());
+  source_code_info_ = const_cast< ::google::protobuf::SourceCodeInfo*>(&::google::protobuf::SourceCodeInfo::default_instance());
 }
 
 FileDescriptorProto::FileDescriptorProto(const FileDescriptorProto& from)
@@ -886,9 +944,10 @@
 
 void FileDescriptorProto::SharedCtor() {
   _cached_size_ = 0;
-  name_ = const_cast< ::std::string*>(&_default_name_);
-  package_ = const_cast< ::std::string*>(&_default_package_);
+  name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  package_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
   options_ = NULL;
+  source_code_info_ = NULL;
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
 }
 
@@ -897,14 +956,15 @@
 }
 
 void FileDescriptorProto::SharedDtor() {
-  if (name_ != &_default_name_) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
     delete name_;
   }
-  if (package_ != &_default_package_) {
+  if (package_ != &::google::protobuf::internal::kEmptyString) {
     delete package_;
   }
   if (this != default_instance_) {
     delete options_;
+    delete source_code_info_;
   }
 }
 
@@ -930,20 +990,25 @@
 
 void FileDescriptorProto::Clear() {
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (_has_bit(0)) {
-      if (name_ != &_default_name_) {
+    if (has_name()) {
+      if (name_ != &::google::protobuf::internal::kEmptyString) {
         name_->clear();
       }
     }
-    if (_has_bit(1)) {
-      if (package_ != &_default_package_) {
+    if (has_package()) {
+      if (package_ != &::google::protobuf::internal::kEmptyString) {
         package_->clear();
       }
     }
-    if (_has_bit(7)) {
+    if (has_options()) {
       if (options_ != NULL) options_->::google::protobuf::FileOptions::Clear();
     }
   }
+  if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) {
+    if (has_source_code_info()) {
+      if (source_code_info_ != NULL) source_code_info_->::google::protobuf::SourceCodeInfo::Clear();
+    }
+  }
   dependency_.Clear();
   message_type_.Clear();
   enum_type_.Clear();
@@ -1080,6 +1145,20 @@
         } else {
           goto handle_uninterpreted;
         }
+        if (input->ExpectTag(74)) goto parse_source_code_info;
+        break;
+      }
+      
+      // optional .google.protobuf.SourceCodeInfo source_code_info = 9;
+      case 9: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+         parse_source_code_info:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+               input, mutable_source_code_info()));
+        } else {
+          goto handle_uninterpreted;
+        }
         if (input->ExpectAtEnd()) return true;
         break;
       }
@@ -1103,7 +1182,7 @@
 void FileDescriptorProto::SerializeWithCachedSizes(
     ::google::protobuf::io::CodedOutputStream* output) const {
   // optional string name = 1;
-  if (_has_bit(0)) {
+  if (has_name()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->name().data(), this->name().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -1112,7 +1191,7 @@
   }
   
   // optional string package = 2;
-  if (_has_bit(1)) {
+  if (has_package()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->package().data(), this->package().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -1154,11 +1233,17 @@
   }
   
   // optional .google.protobuf.FileOptions options = 8;
-  if (_has_bit(7)) {
+  if (has_options()) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       8, this->options(), output);
   }
   
+  // optional .google.protobuf.SourceCodeInfo source_code_info = 9;
+  if (has_source_code_info()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      9, this->source_code_info(), output);
+  }
+  
   if (!unknown_fields().empty()) {
     ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
         unknown_fields(), output);
@@ -1168,7 +1253,7 @@
 ::google::protobuf::uint8* FileDescriptorProto::SerializeWithCachedSizesToArray(
     ::google::protobuf::uint8* target) const {
   // optional string name = 1;
-  if (_has_bit(0)) {
+  if (has_name()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->name().data(), this->name().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -1178,7 +1263,7 @@
   }
   
   // optional string package = 2;
-  if (_has_bit(1)) {
+  if (has_package()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->package().data(), this->package().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -1225,12 +1310,19 @@
   }
   
   // optional .google.protobuf.FileOptions options = 8;
-  if (_has_bit(7)) {
+  if (has_options()) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         8, this->options(), target);
   }
   
+  // optional .google.protobuf.SourceCodeInfo source_code_info = 9;
+  if (has_source_code_info()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        9, this->source_code_info(), target);
+  }
+  
   if (!unknown_fields().empty()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
         unknown_fields(), target);
@@ -1264,6 +1356,15 @@
     }
     
   }
+  if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) {
+    // optional .google.protobuf.SourceCodeInfo source_code_info = 9;
+    if (has_source_code_info()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+          this->source_code_info());
+    }
+    
+  }
   // repeated string dependency = 3;
   total_size += 1 * this->dependency_size();
   for (int i = 0; i < this->dependency_size(); i++) {
@@ -1334,16 +1435,21 @@
   service_.MergeFrom(from.service_);
   extension_.MergeFrom(from.extension_);
   if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (from._has_bit(0)) {
+    if (from.has_name()) {
       set_name(from.name());
     }
-    if (from._has_bit(1)) {
+    if (from.has_package()) {
       set_package(from.package());
     }
-    if (from._has_bit(7)) {
+    if (from.has_options()) {
       mutable_options()->::google::protobuf::FileOptions::MergeFrom(from.options());
     }
   }
+  if (from._has_bits_[8 / 32] & (0xffu << (8 % 32))) {
+    if (from.has_source_code_info()) {
+      mutable_source_code_info()->::google::protobuf::SourceCodeInfo::MergeFrom(from.source_code_info());
+    }
+  }
   mutable_unknown_fields()->MergeFrom(from.unknown_fields());
 }
 
@@ -1389,6 +1495,7 @@
     service_.Swap(&other->service_);
     extension_.Swap(&other->extension_);
     std::swap(options_, other->options_);
+    std::swap(source_code_info_, other->source_code_info_);
     std::swap(_has_bits_[0], other->_has_bits_[0]);
     _unknown_fields_.Swap(&other->_unknown_fields_);
     std::swap(_cached_size_, other->_cached_size_);
@@ -1483,7 +1590,7 @@
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
                  input, &start_)));
-          _set_bit(0);
+          set_has_start();
         } else {
           goto handle_uninterpreted;
         }
@@ -1499,7 +1606,7 @@
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
                  input, &end_)));
-          _set_bit(1);
+          set_has_end();
         } else {
           goto handle_uninterpreted;
         }
@@ -1526,12 +1633,12 @@
 void DescriptorProto_ExtensionRange::SerializeWithCachedSizes(
     ::google::protobuf::io::CodedOutputStream* output) const {
   // optional int32 start = 1;
-  if (_has_bit(0)) {
+  if (has_start()) {
     ::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->start(), output);
   }
   
   // optional int32 end = 2;
-  if (_has_bit(1)) {
+  if (has_end()) {
     ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->end(), output);
   }
   
@@ -1544,12 +1651,12 @@
 ::google::protobuf::uint8* DescriptorProto_ExtensionRange::SerializeWithCachedSizesToArray(
     ::google::protobuf::uint8* target) const {
   // optional int32 start = 1;
-  if (_has_bit(0)) {
+  if (has_start()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(1, this->start(), target);
   }
   
   // optional int32 end = 2;
-  if (_has_bit(1)) {
+  if (has_end()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->end(), target);
   }
   
@@ -1605,10 +1712,10 @@
 void DescriptorProto_ExtensionRange::MergeFrom(const DescriptorProto_ExtensionRange& from) {
   GOOGLE_CHECK_NE(&from, this);
   if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (from._has_bit(0)) {
+    if (from.has_start()) {
       set_start(from.start());
     }
-    if (from._has_bit(1)) {
+    if (from.has_end()) {
       set_end(from.end());
     }
   }
@@ -1653,7 +1760,6 @@
 
 // -------------------------------------------------------------------
 
-const ::std::string DescriptorProto::_default_name_;
 #ifndef _MSC_VER
 const int DescriptorProto::kNameFieldNumber;
 const int DescriptorProto::kFieldFieldNumber;
@@ -1681,7 +1787,7 @@
 
 void DescriptorProto::SharedCtor() {
   _cached_size_ = 0;
-  name_ = const_cast< ::std::string*>(&_default_name_);
+  name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
   options_ = NULL;
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
 }
@@ -1691,7 +1797,7 @@
 }
 
 void DescriptorProto::SharedDtor() {
-  if (name_ != &_default_name_) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
     delete name_;
   }
   if (this != default_instance_) {
@@ -1721,12 +1827,12 @@
 
 void DescriptorProto::Clear() {
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (_has_bit(0)) {
-      if (name_ != &_default_name_) {
+    if (has_name()) {
+      if (name_ != &::google::protobuf::internal::kEmptyString) {
         name_->clear();
       }
     }
-    if (_has_bit(6)) {
+    if (has_options()) {
       if (options_ != NULL) options_->::google::protobuf::MessageOptions::Clear();
     }
   }
@@ -1869,7 +1975,7 @@
 void DescriptorProto::SerializeWithCachedSizes(
     ::google::protobuf::io::CodedOutputStream* output) const {
   // optional string name = 1;
-  if (_has_bit(0)) {
+  if (has_name()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->name().data(), this->name().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -1908,7 +2014,7 @@
   }
   
   // optional .google.protobuf.MessageOptions options = 7;
-  if (_has_bit(6)) {
+  if (has_options()) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       7, this->options(), output);
   }
@@ -1922,7 +2028,7 @@
 ::google::protobuf::uint8* DescriptorProto::SerializeWithCachedSizesToArray(
     ::google::protobuf::uint8* target) const {
   // optional string name = 1;
-  if (_has_bit(0)) {
+  if (has_name()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->name().data(), this->name().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -1967,7 +2073,7 @@
   }
   
   // optional .google.protobuf.MessageOptions options = 7;
-  if (_has_bit(6)) {
+  if (has_options()) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         7, this->options(), target);
@@ -2070,10 +2176,10 @@
   enum_type_.MergeFrom(from.enum_type_);
   extension_range_.MergeFrom(from.extension_range_);
   if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (from._has_bit(0)) {
+    if (from.has_name()) {
       set_name(from.name());
     }
-    if (from._has_bit(6)) {
+    if (from.has_options()) {
       mutable_options()->::google::protobuf::MessageOptions::MergeFrom(from.options());
     }
   }
@@ -2214,10 +2320,6 @@
 const FieldDescriptorProto_Label FieldDescriptorProto::Label_MAX;
 const int FieldDescriptorProto::Label_ARRAYSIZE;
 #endif  // _MSC_VER
-const ::std::string FieldDescriptorProto::_default_name_;
-const ::std::string FieldDescriptorProto::_default_type_name_;
-const ::std::string FieldDescriptorProto::_default_extendee_;
-const ::std::string FieldDescriptorProto::_default_default_value_;
 #ifndef _MSC_VER
 const int FieldDescriptorProto::kNameFieldNumber;
 const int FieldDescriptorProto::kNumberFieldNumber;
@@ -2246,13 +2348,13 @@
 
 void FieldDescriptorProto::SharedCtor() {
   _cached_size_ = 0;
-  name_ = const_cast< ::std::string*>(&_default_name_);
+  name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
   number_ = 0;
   label_ = 1;
   type_ = 1;
-  type_name_ = const_cast< ::std::string*>(&_default_type_name_);
-  extendee_ = const_cast< ::std::string*>(&_default_extendee_);
-  default_value_ = const_cast< ::std::string*>(&_default_default_value_);
+  type_name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  extendee_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  default_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
   options_ = NULL;
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
 }
@@ -2262,16 +2364,16 @@
 }
 
 void FieldDescriptorProto::SharedDtor() {
-  if (name_ != &_default_name_) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
     delete name_;
   }
-  if (type_name_ != &_default_type_name_) {
+  if (type_name_ != &::google::protobuf::internal::kEmptyString) {
     delete type_name_;
   }
-  if (extendee_ != &_default_extendee_) {
+  if (extendee_ != &::google::protobuf::internal::kEmptyString) {
     delete extendee_;
   }
-  if (default_value_ != &_default_default_value_) {
+  if (default_value_ != &::google::protobuf::internal::kEmptyString) {
     delete default_value_;
   }
   if (this != default_instance_) {
@@ -2301,30 +2403,30 @@
 
 void FieldDescriptorProto::Clear() {
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (_has_bit(0)) {
-      if (name_ != &_default_name_) {
+    if (has_name()) {
+      if (name_ != &::google::protobuf::internal::kEmptyString) {
         name_->clear();
       }
     }
     number_ = 0;
     label_ = 1;
     type_ = 1;
-    if (_has_bit(4)) {
-      if (type_name_ != &_default_type_name_) {
+    if (has_type_name()) {
+      if (type_name_ != &::google::protobuf::internal::kEmptyString) {
         type_name_->clear();
       }
     }
-    if (_has_bit(5)) {
-      if (extendee_ != &_default_extendee_) {
+    if (has_extendee()) {
+      if (extendee_ != &::google::protobuf::internal::kEmptyString) {
         extendee_->clear();
       }
     }
-    if (_has_bit(6)) {
-      if (default_value_ != &_default_default_value_) {
+    if (has_default_value()) {
+      if (default_value_ != &::google::protobuf::internal::kEmptyString) {
         default_value_->clear();
       }
     }
-    if (_has_bit(7)) {
+    if (has_options()) {
       if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear();
     }
   }
@@ -2379,7 +2481,7 @@
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
                  input, &number_)));
-          _set_bit(1);
+          set_has_number();
         } else {
           goto handle_uninterpreted;
         }
@@ -2496,7 +2598,7 @@
 void FieldDescriptorProto::SerializeWithCachedSizes(
     ::google::protobuf::io::CodedOutputStream* output) const {
   // optional string name = 1;
-  if (_has_bit(0)) {
+  if (has_name()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->name().data(), this->name().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -2505,7 +2607,7 @@
   }
   
   // optional string extendee = 2;
-  if (_has_bit(5)) {
+  if (has_extendee()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->extendee().data(), this->extendee().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -2514,24 +2616,24 @@
   }
   
   // optional int32 number = 3;
-  if (_has_bit(1)) {
+  if (has_number()) {
     ::google::protobuf::internal::WireFormatLite::WriteInt32(3, this->number(), output);
   }
   
   // optional .google.protobuf.FieldDescriptorProto.Label label = 4;
-  if (_has_bit(2)) {
+  if (has_label()) {
     ::google::protobuf::internal::WireFormatLite::WriteEnum(
       4, this->label(), output);
   }
   
   // optional .google.protobuf.FieldDescriptorProto.Type type = 5;
-  if (_has_bit(3)) {
+  if (has_type()) {
     ::google::protobuf::internal::WireFormatLite::WriteEnum(
       5, this->type(), output);
   }
   
   // optional string type_name = 6;
-  if (_has_bit(4)) {
+  if (has_type_name()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->type_name().data(), this->type_name().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -2540,7 +2642,7 @@
   }
   
   // optional string default_value = 7;
-  if (_has_bit(6)) {
+  if (has_default_value()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->default_value().data(), this->default_value().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -2549,7 +2651,7 @@
   }
   
   // optional .google.protobuf.FieldOptions options = 8;
-  if (_has_bit(7)) {
+  if (has_options()) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       8, this->options(), output);
   }
@@ -2563,7 +2665,7 @@
 ::google::protobuf::uint8* FieldDescriptorProto::SerializeWithCachedSizesToArray(
     ::google::protobuf::uint8* target) const {
   // optional string name = 1;
-  if (_has_bit(0)) {
+  if (has_name()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->name().data(), this->name().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -2573,7 +2675,7 @@
   }
   
   // optional string extendee = 2;
-  if (_has_bit(5)) {
+  if (has_extendee()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->extendee().data(), this->extendee().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -2583,24 +2685,24 @@
   }
   
   // optional int32 number = 3;
-  if (_has_bit(1)) {
+  if (has_number()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(3, this->number(), target);
   }
   
   // optional .google.protobuf.FieldDescriptorProto.Label label = 4;
-  if (_has_bit(2)) {
+  if (has_label()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
       4, this->label(), target);
   }
   
   // optional .google.protobuf.FieldDescriptorProto.Type type = 5;
-  if (_has_bit(3)) {
+  if (has_type()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
       5, this->type(), target);
   }
   
   // optional string type_name = 6;
-  if (_has_bit(4)) {
+  if (has_type_name()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->type_name().data(), this->type_name().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -2610,7 +2712,7 @@
   }
   
   // optional string default_value = 7;
-  if (_has_bit(6)) {
+  if (has_default_value()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->default_value().data(), this->default_value().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -2620,7 +2722,7 @@
   }
   
   // optional .google.protobuf.FieldOptions options = 8;
-  if (_has_bit(7)) {
+  if (has_options()) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         8, this->options(), target);
@@ -2718,28 +2820,28 @@
 void FieldDescriptorProto::MergeFrom(const FieldDescriptorProto& from) {
   GOOGLE_CHECK_NE(&from, this);
   if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (from._has_bit(0)) {
+    if (from.has_name()) {
       set_name(from.name());
     }
-    if (from._has_bit(1)) {
+    if (from.has_number()) {
       set_number(from.number());
     }
-    if (from._has_bit(2)) {
+    if (from.has_label()) {
       set_label(from.label());
     }
-    if (from._has_bit(3)) {
+    if (from.has_type()) {
       set_type(from.type());
     }
-    if (from._has_bit(4)) {
+    if (from.has_type_name()) {
       set_type_name(from.type_name());
     }
-    if (from._has_bit(5)) {
+    if (from.has_extendee()) {
       set_extendee(from.extendee());
     }
-    if (from._has_bit(6)) {
+    if (from.has_default_value()) {
       set_default_value(from.default_value());
     }
-    if (from._has_bit(7)) {
+    if (from.has_options()) {
       mutable_options()->::google::protobuf::FieldOptions::MergeFrom(from.options());
     }
   }
@@ -2793,7 +2895,6 @@
 
 // ===================================================================
 
-const ::std::string EnumDescriptorProto::_default_name_;
 #ifndef _MSC_VER
 const int EnumDescriptorProto::kNameFieldNumber;
 const int EnumDescriptorProto::kValueFieldNumber;
@@ -2817,7 +2918,7 @@
 
 void EnumDescriptorProto::SharedCtor() {
   _cached_size_ = 0;
-  name_ = const_cast< ::std::string*>(&_default_name_);
+  name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
   options_ = NULL;
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
 }
@@ -2827,7 +2928,7 @@
 }
 
 void EnumDescriptorProto::SharedDtor() {
-  if (name_ != &_default_name_) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
     delete name_;
   }
   if (this != default_instance_) {
@@ -2857,12 +2958,12 @@
 
 void EnumDescriptorProto::Clear() {
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (_has_bit(0)) {
-      if (name_ != &_default_name_) {
+    if (has_name()) {
+      if (name_ != &::google::protobuf::internal::kEmptyString) {
         name_->clear();
       }
     }
-    if (_has_bit(2)) {
+    if (has_options()) {
       if (options_ != NULL) options_->::google::protobuf::EnumOptions::Clear();
     }
   }
@@ -2941,7 +3042,7 @@
 void EnumDescriptorProto::SerializeWithCachedSizes(
     ::google::protobuf::io::CodedOutputStream* output) const {
   // optional string name = 1;
-  if (_has_bit(0)) {
+  if (has_name()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->name().data(), this->name().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -2956,7 +3057,7 @@
   }
   
   // optional .google.protobuf.EnumOptions options = 3;
-  if (_has_bit(2)) {
+  if (has_options()) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       3, this->options(), output);
   }
@@ -2970,7 +3071,7 @@
 ::google::protobuf::uint8* EnumDescriptorProto::SerializeWithCachedSizesToArray(
     ::google::protobuf::uint8* target) const {
   // optional string name = 1;
-  if (_has_bit(0)) {
+  if (has_name()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->name().data(), this->name().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -2987,7 +3088,7 @@
   }
   
   // optional .google.protobuf.EnumOptions options = 3;
-  if (_has_bit(2)) {
+  if (has_options()) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         3, this->options(), target);
@@ -3054,10 +3155,10 @@
   GOOGLE_CHECK_NE(&from, this);
   value_.MergeFrom(from.value_);
   if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (from._has_bit(0)) {
+    if (from.has_name()) {
       set_name(from.name());
     }
-    if (from._has_bit(2)) {
+    if (from.has_options()) {
       mutable_options()->::google::protobuf::EnumOptions::MergeFrom(from.options());
     }
   }
@@ -3109,7 +3210,6 @@
 
 // ===================================================================
 
-const ::std::string EnumValueDescriptorProto::_default_name_;
 #ifndef _MSC_VER
 const int EnumValueDescriptorProto::kNameFieldNumber;
 const int EnumValueDescriptorProto::kNumberFieldNumber;
@@ -3133,7 +3233,7 @@
 
 void EnumValueDescriptorProto::SharedCtor() {
   _cached_size_ = 0;
-  name_ = const_cast< ::std::string*>(&_default_name_);
+  name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
   number_ = 0;
   options_ = NULL;
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
@@ -3144,7 +3244,7 @@
 }
 
 void EnumValueDescriptorProto::SharedDtor() {
-  if (name_ != &_default_name_) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
     delete name_;
   }
   if (this != default_instance_) {
@@ -3174,13 +3274,13 @@
 
 void EnumValueDescriptorProto::Clear() {
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (_has_bit(0)) {
-      if (name_ != &_default_name_) {
+    if (has_name()) {
+      if (name_ != &::google::protobuf::internal::kEmptyString) {
         name_->clear();
       }
     }
     number_ = 0;
-    if (_has_bit(2)) {
+    if (has_options()) {
       if (options_ != NULL) options_->::google::protobuf::EnumValueOptions::Clear();
     }
   }
@@ -3218,7 +3318,7 @@
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
                  input, &number_)));
-          _set_bit(1);
+          set_has_number();
         } else {
           goto handle_uninterpreted;
         }
@@ -3259,7 +3359,7 @@
 void EnumValueDescriptorProto::SerializeWithCachedSizes(
     ::google::protobuf::io::CodedOutputStream* output) const {
   // optional string name = 1;
-  if (_has_bit(0)) {
+  if (has_name()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->name().data(), this->name().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -3268,12 +3368,12 @@
   }
   
   // optional int32 number = 2;
-  if (_has_bit(1)) {
+  if (has_number()) {
     ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->number(), output);
   }
   
   // optional .google.protobuf.EnumValueOptions options = 3;
-  if (_has_bit(2)) {
+  if (has_options()) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       3, this->options(), output);
   }
@@ -3287,7 +3387,7 @@
 ::google::protobuf::uint8* EnumValueDescriptorProto::SerializeWithCachedSizesToArray(
     ::google::protobuf::uint8* target) const {
   // optional string name = 1;
-  if (_has_bit(0)) {
+  if (has_name()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->name().data(), this->name().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -3297,12 +3397,12 @@
   }
   
   // optional int32 number = 2;
-  if (_has_bit(1)) {
+  if (has_number()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->number(), target);
   }
   
   // optional .google.protobuf.EnumValueOptions options = 3;
-  if (_has_bit(2)) {
+  if (has_options()) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         3, this->options(), target);
@@ -3367,13 +3467,13 @@
 void EnumValueDescriptorProto::MergeFrom(const EnumValueDescriptorProto& from) {
   GOOGLE_CHECK_NE(&from, this);
   if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (from._has_bit(0)) {
+    if (from.has_name()) {
       set_name(from.name());
     }
-    if (from._has_bit(1)) {
+    if (from.has_number()) {
       set_number(from.number());
     }
-    if (from._has_bit(2)) {
+    if (from.has_options()) {
       mutable_options()->::google::protobuf::EnumValueOptions::MergeFrom(from.options());
     }
   }
@@ -3422,7 +3522,6 @@
 
 // ===================================================================
 
-const ::std::string ServiceDescriptorProto::_default_name_;
 #ifndef _MSC_VER
 const int ServiceDescriptorProto::kNameFieldNumber;
 const int ServiceDescriptorProto::kMethodFieldNumber;
@@ -3446,7 +3545,7 @@
 
 void ServiceDescriptorProto::SharedCtor() {
   _cached_size_ = 0;
-  name_ = const_cast< ::std::string*>(&_default_name_);
+  name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
   options_ = NULL;
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
 }
@@ -3456,7 +3555,7 @@
 }
 
 void ServiceDescriptorProto::SharedDtor() {
-  if (name_ != &_default_name_) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
     delete name_;
   }
   if (this != default_instance_) {
@@ -3486,12 +3585,12 @@
 
 void ServiceDescriptorProto::Clear() {
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (_has_bit(0)) {
-      if (name_ != &_default_name_) {
+    if (has_name()) {
+      if (name_ != &::google::protobuf::internal::kEmptyString) {
         name_->clear();
       }
     }
-    if (_has_bit(2)) {
+    if (has_options()) {
       if (options_ != NULL) options_->::google::protobuf::ServiceOptions::Clear();
     }
   }
@@ -3570,7 +3669,7 @@
 void ServiceDescriptorProto::SerializeWithCachedSizes(
     ::google::protobuf::io::CodedOutputStream* output) const {
   // optional string name = 1;
-  if (_has_bit(0)) {
+  if (has_name()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->name().data(), this->name().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -3585,7 +3684,7 @@
   }
   
   // optional .google.protobuf.ServiceOptions options = 3;
-  if (_has_bit(2)) {
+  if (has_options()) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       3, this->options(), output);
   }
@@ -3599,7 +3698,7 @@
 ::google::protobuf::uint8* ServiceDescriptorProto::SerializeWithCachedSizesToArray(
     ::google::protobuf::uint8* target) const {
   // optional string name = 1;
-  if (_has_bit(0)) {
+  if (has_name()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->name().data(), this->name().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -3616,7 +3715,7 @@
   }
   
   // optional .google.protobuf.ServiceOptions options = 3;
-  if (_has_bit(2)) {
+  if (has_options()) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         3, this->options(), target);
@@ -3683,10 +3782,10 @@
   GOOGLE_CHECK_NE(&from, this);
   method_.MergeFrom(from.method_);
   if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (from._has_bit(0)) {
+    if (from.has_name()) {
       set_name(from.name());
     }
-    if (from._has_bit(2)) {
+    if (from.has_options()) {
       mutable_options()->::google::protobuf::ServiceOptions::MergeFrom(from.options());
     }
   }
@@ -3738,9 +3837,6 @@
 
 // ===================================================================
 
-const ::std::string MethodDescriptorProto::_default_name_;
-const ::std::string MethodDescriptorProto::_default_input_type_;
-const ::std::string MethodDescriptorProto::_default_output_type_;
 #ifndef _MSC_VER
 const int MethodDescriptorProto::kNameFieldNumber;
 const int MethodDescriptorProto::kInputTypeFieldNumber;
@@ -3765,9 +3861,9 @@
 
 void MethodDescriptorProto::SharedCtor() {
   _cached_size_ = 0;
-  name_ = const_cast< ::std::string*>(&_default_name_);
-  input_type_ = const_cast< ::std::string*>(&_default_input_type_);
-  output_type_ = const_cast< ::std::string*>(&_default_output_type_);
+  name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  input_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  output_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
   options_ = NULL;
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
 }
@@ -3777,13 +3873,13 @@
 }
 
 void MethodDescriptorProto::SharedDtor() {
-  if (name_ != &_default_name_) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
     delete name_;
   }
-  if (input_type_ != &_default_input_type_) {
+  if (input_type_ != &::google::protobuf::internal::kEmptyString) {
     delete input_type_;
   }
-  if (output_type_ != &_default_output_type_) {
+  if (output_type_ != &::google::protobuf::internal::kEmptyString) {
     delete output_type_;
   }
   if (this != default_instance_) {
@@ -3813,22 +3909,22 @@
 
 void MethodDescriptorProto::Clear() {
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (_has_bit(0)) {
-      if (name_ != &_default_name_) {
+    if (has_name()) {
+      if (name_ != &::google::protobuf::internal::kEmptyString) {
         name_->clear();
       }
     }
-    if (_has_bit(1)) {
-      if (input_type_ != &_default_input_type_) {
+    if (has_input_type()) {
+      if (input_type_ != &::google::protobuf::internal::kEmptyString) {
         input_type_->clear();
       }
     }
-    if (_has_bit(2)) {
-      if (output_type_ != &_default_output_type_) {
+    if (has_output_type()) {
+      if (output_type_ != &::google::protobuf::internal::kEmptyString) {
         output_type_->clear();
       }
     }
-    if (_has_bit(3)) {
+    if (has_options()) {
       if (options_ != NULL) options_->::google::protobuf::MethodOptions::Clear();
     }
   }
@@ -3925,7 +4021,7 @@
 void MethodDescriptorProto::SerializeWithCachedSizes(
     ::google::protobuf::io::CodedOutputStream* output) const {
   // optional string name = 1;
-  if (_has_bit(0)) {
+  if (has_name()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->name().data(), this->name().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -3934,7 +4030,7 @@
   }
   
   // optional string input_type = 2;
-  if (_has_bit(1)) {
+  if (has_input_type()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->input_type().data(), this->input_type().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -3943,7 +4039,7 @@
   }
   
   // optional string output_type = 3;
-  if (_has_bit(2)) {
+  if (has_output_type()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->output_type().data(), this->output_type().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -3952,7 +4048,7 @@
   }
   
   // optional .google.protobuf.MethodOptions options = 4;
-  if (_has_bit(3)) {
+  if (has_options()) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       4, this->options(), output);
   }
@@ -3966,7 +4062,7 @@
 ::google::protobuf::uint8* MethodDescriptorProto::SerializeWithCachedSizesToArray(
     ::google::protobuf::uint8* target) const {
   // optional string name = 1;
-  if (_has_bit(0)) {
+  if (has_name()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->name().data(), this->name().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -3976,7 +4072,7 @@
   }
   
   // optional string input_type = 2;
-  if (_has_bit(1)) {
+  if (has_input_type()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->input_type().data(), this->input_type().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -3986,7 +4082,7 @@
   }
   
   // optional string output_type = 3;
-  if (_has_bit(2)) {
+  if (has_output_type()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->output_type().data(), this->output_type().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -3996,7 +4092,7 @@
   }
   
   // optional .google.protobuf.MethodOptions options = 4;
-  if (_has_bit(3)) {
+  if (has_options()) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         4, this->options(), target);
@@ -4068,16 +4164,16 @@
 void MethodDescriptorProto::MergeFrom(const MethodDescriptorProto& from) {
   GOOGLE_CHECK_NE(&from, this);
   if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (from._has_bit(0)) {
+    if (from.has_name()) {
       set_name(from.name());
     }
-    if (from._has_bit(1)) {
+    if (from.has_input_type()) {
       set_input_type(from.input_type());
     }
-    if (from._has_bit(2)) {
+    if (from.has_output_type()) {
       set_output_type(from.output_type());
     }
-    if (from._has_bit(3)) {
+    if (from.has_options()) {
       mutable_options()->::google::protobuf::MethodOptions::MergeFrom(from.options());
     }
   }
@@ -4150,12 +4246,11 @@
 const FileOptions_OptimizeMode FileOptions::OptimizeMode_MAX;
 const int FileOptions::OptimizeMode_ARRAYSIZE;
 #endif  // _MSC_VER
-const ::std::string FileOptions::_default_java_package_;
-const ::std::string FileOptions::_default_java_outer_classname_;
 #ifndef _MSC_VER
 const int FileOptions::kJavaPackageFieldNumber;
 const int FileOptions::kJavaOuterClassnameFieldNumber;
 const int FileOptions::kJavaMultipleFilesFieldNumber;
+const int FileOptions::kJavaGenerateEqualsAndHashFieldNumber;
 const int FileOptions::kOptimizeForFieldNumber;
 const int FileOptions::kCcGenericServicesFieldNumber;
 const int FileOptions::kJavaGenericServicesFieldNumber;
@@ -4179,13 +4274,14 @@
 
 void FileOptions::SharedCtor() {
   _cached_size_ = 0;
-  java_package_ = const_cast< ::std::string*>(&_default_java_package_);
-  java_outer_classname_ = const_cast< ::std::string*>(&_default_java_outer_classname_);
+  java_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  java_outer_classname_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
   java_multiple_files_ = false;
+  java_generate_equals_and_hash_ = false;
   optimize_for_ = 1;
-  cc_generic_services_ = true;
-  java_generic_services_ = true;
-  py_generic_services_ = true;
+  cc_generic_services_ = false;
+  java_generic_services_ = false;
+  py_generic_services_ = false;
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
 }
 
@@ -4194,10 +4290,10 @@
 }
 
 void FileOptions::SharedDtor() {
-  if (java_package_ != &_default_java_package_) {
+  if (java_package_ != &::google::protobuf::internal::kEmptyString) {
     delete java_package_;
   }
-  if (java_outer_classname_ != &_default_java_outer_classname_) {
+  if (java_outer_classname_ != &::google::protobuf::internal::kEmptyString) {
     delete java_outer_classname_;
   }
   if (this != default_instance_) {
@@ -4227,21 +4323,22 @@
 void FileOptions::Clear() {
   _extensions_.Clear();
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (_has_bit(0)) {
-      if (java_package_ != &_default_java_package_) {
+    if (has_java_package()) {
+      if (java_package_ != &::google::protobuf::internal::kEmptyString) {
         java_package_->clear();
       }
     }
-    if (_has_bit(1)) {
-      if (java_outer_classname_ != &_default_java_outer_classname_) {
+    if (has_java_outer_classname()) {
+      if (java_outer_classname_ != &::google::protobuf::internal::kEmptyString) {
         java_outer_classname_->clear();
       }
     }
     java_multiple_files_ = false;
+    java_generate_equals_and_hash_ = false;
     optimize_for_ = 1;
-    cc_generic_services_ = true;
-    java_generic_services_ = true;
-    py_generic_services_ = true;
+    cc_generic_services_ = false;
+    java_generic_services_ = false;
+    py_generic_services_ = false;
   }
   uninterpreted_option_.Clear();
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
@@ -4316,7 +4413,7 @@
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
                  input, &java_multiple_files_)));
-          _set_bit(2);
+          set_has_java_multiple_files();
         } else {
           goto handle_uninterpreted;
         }
@@ -4324,7 +4421,7 @@
         break;
       }
       
-      // optional bool cc_generic_services = 16 [default = true];
+      // optional bool cc_generic_services = 16 [default = false];
       case 16: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
             ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
@@ -4332,7 +4429,7 @@
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
                  input, &cc_generic_services_)));
-          _set_bit(4);
+          set_has_cc_generic_services();
         } else {
           goto handle_uninterpreted;
         }
@@ -4340,7 +4437,7 @@
         break;
       }
       
-      // optional bool java_generic_services = 17 [default = true];
+      // optional bool java_generic_services = 17 [default = false];
       case 17: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
             ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
@@ -4348,7 +4445,7 @@
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
                  input, &java_generic_services_)));
-          _set_bit(5);
+          set_has_java_generic_services();
         } else {
           goto handle_uninterpreted;
         }
@@ -4356,7 +4453,7 @@
         break;
       }
       
-      // optional bool py_generic_services = 18 [default = true];
+      // optional bool py_generic_services = 18 [default = false];
       case 18: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
             ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
@@ -4364,7 +4461,23 @@
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
                  input, &py_generic_services_)));
-          _set_bit(6);
+          set_has_py_generic_services();
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(160)) goto parse_java_generate_equals_and_hash;
+        break;
+      }
+      
+      // optional bool java_generate_equals_and_hash = 20 [default = false];
+      case 20: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_java_generate_equals_and_hash:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &java_generate_equals_and_hash_)));
+          set_has_java_generate_equals_and_hash();
         } else {
           goto handle_uninterpreted;
         }
@@ -4411,7 +4524,7 @@
 void FileOptions::SerializeWithCachedSizes(
     ::google::protobuf::io::CodedOutputStream* output) const {
   // optional string java_package = 1;
-  if (_has_bit(0)) {
+  if (has_java_package()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->java_package().data(), this->java_package().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -4420,7 +4533,7 @@
   }
   
   // optional string java_outer_classname = 8;
-  if (_has_bit(1)) {
+  if (has_java_outer_classname()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->java_outer_classname().data(), this->java_outer_classname().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -4429,31 +4542,36 @@
   }
   
   // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
-  if (_has_bit(3)) {
+  if (has_optimize_for()) {
     ::google::protobuf::internal::WireFormatLite::WriteEnum(
       9, this->optimize_for(), output);
   }
   
   // optional bool java_multiple_files = 10 [default = false];
-  if (_has_bit(2)) {
+  if (has_java_multiple_files()) {
     ::google::protobuf::internal::WireFormatLite::WriteBool(10, this->java_multiple_files(), output);
   }
   
-  // optional bool cc_generic_services = 16 [default = true];
-  if (_has_bit(4)) {
+  // optional bool cc_generic_services = 16 [default = false];
+  if (has_cc_generic_services()) {
     ::google::protobuf::internal::WireFormatLite::WriteBool(16, this->cc_generic_services(), output);
   }
   
-  // optional bool java_generic_services = 17 [default = true];
-  if (_has_bit(5)) {
+  // optional bool java_generic_services = 17 [default = false];
+  if (has_java_generic_services()) {
     ::google::protobuf::internal::WireFormatLite::WriteBool(17, this->java_generic_services(), output);
   }
   
-  // optional bool py_generic_services = 18 [default = true];
-  if (_has_bit(6)) {
+  // optional bool py_generic_services = 18 [default = false];
+  if (has_py_generic_services()) {
     ::google::protobuf::internal::WireFormatLite::WriteBool(18, this->py_generic_services(), output);
   }
   
+  // optional bool java_generate_equals_and_hash = 20 [default = false];
+  if (has_java_generate_equals_and_hash()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(20, this->java_generate_equals_and_hash(), output);
+  }
+  
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   for (int i = 0; i < this->uninterpreted_option_size(); i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
@@ -4473,7 +4591,7 @@
 ::google::protobuf::uint8* FileOptions::SerializeWithCachedSizesToArray(
     ::google::protobuf::uint8* target) const {
   // optional string java_package = 1;
-  if (_has_bit(0)) {
+  if (has_java_package()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->java_package().data(), this->java_package().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -4483,7 +4601,7 @@
   }
   
   // optional string java_outer_classname = 8;
-  if (_has_bit(1)) {
+  if (has_java_outer_classname()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->java_outer_classname().data(), this->java_outer_classname().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -4493,31 +4611,36 @@
   }
   
   // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
-  if (_has_bit(3)) {
+  if (has_optimize_for()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
       9, this->optimize_for(), target);
   }
   
   // optional bool java_multiple_files = 10 [default = false];
-  if (_has_bit(2)) {
+  if (has_java_multiple_files()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(10, this->java_multiple_files(), target);
   }
   
-  // optional bool cc_generic_services = 16 [default = true];
-  if (_has_bit(4)) {
+  // optional bool cc_generic_services = 16 [default = false];
+  if (has_cc_generic_services()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(16, this->cc_generic_services(), target);
   }
   
-  // optional bool java_generic_services = 17 [default = true];
-  if (_has_bit(5)) {
+  // optional bool java_generic_services = 17 [default = false];
+  if (has_java_generic_services()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(17, this->java_generic_services(), target);
   }
   
-  // optional bool py_generic_services = 18 [default = true];
-  if (_has_bit(6)) {
+  // optional bool py_generic_services = 18 [default = false];
+  if (has_py_generic_services()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(18, this->py_generic_services(), target);
   }
   
+  // optional bool java_generate_equals_and_hash = 20 [default = false];
+  if (has_java_generate_equals_and_hash()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(20, this->java_generate_equals_and_hash(), target);
+  }
+  
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   for (int i = 0; i < this->uninterpreted_option_size(); i++) {
     target = ::google::protobuf::internal::WireFormatLite::
@@ -4559,23 +4682,28 @@
       total_size += 1 + 1;
     }
     
+    // optional bool java_generate_equals_and_hash = 20 [default = false];
+    if (has_java_generate_equals_and_hash()) {
+      total_size += 2 + 1;
+    }
+    
     // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
     if (has_optimize_for()) {
       total_size += 1 +
         ::google::protobuf::internal::WireFormatLite::EnumSize(this->optimize_for());
     }
     
-    // optional bool cc_generic_services = 16 [default = true];
+    // optional bool cc_generic_services = 16 [default = false];
     if (has_cc_generic_services()) {
       total_size += 2 + 1;
     }
     
-    // optional bool java_generic_services = 17 [default = true];
+    // optional bool java_generic_services = 17 [default = false];
     if (has_java_generic_services()) {
       total_size += 2 + 1;
     }
     
-    // optional bool py_generic_services = 18 [default = true];
+    // optional bool py_generic_services = 18 [default = false];
     if (has_py_generic_services()) {
       total_size += 2 + 1;
     }
@@ -4618,25 +4746,28 @@
   GOOGLE_CHECK_NE(&from, this);
   uninterpreted_option_.MergeFrom(from.uninterpreted_option_);
   if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (from._has_bit(0)) {
+    if (from.has_java_package()) {
       set_java_package(from.java_package());
     }
-    if (from._has_bit(1)) {
+    if (from.has_java_outer_classname()) {
       set_java_outer_classname(from.java_outer_classname());
     }
-    if (from._has_bit(2)) {
+    if (from.has_java_multiple_files()) {
       set_java_multiple_files(from.java_multiple_files());
     }
-    if (from._has_bit(3)) {
+    if (from.has_java_generate_equals_and_hash()) {
+      set_java_generate_equals_and_hash(from.java_generate_equals_and_hash());
+    }
+    if (from.has_optimize_for()) {
       set_optimize_for(from.optimize_for());
     }
-    if (from._has_bit(4)) {
+    if (from.has_cc_generic_services()) {
       set_cc_generic_services(from.cc_generic_services());
     }
-    if (from._has_bit(5)) {
+    if (from.has_java_generic_services()) {
       set_java_generic_services(from.java_generic_services());
     }
-    if (from._has_bit(6)) {
+    if (from.has_py_generic_services()) {
       set_py_generic_services(from.py_generic_services());
     }
   }
@@ -4670,6 +4801,7 @@
     std::swap(java_package_, other->java_package_);
     std::swap(java_outer_classname_, other->java_outer_classname_);
     std::swap(java_multiple_files_, other->java_multiple_files_);
+    std::swap(java_generate_equals_and_hash_, other->java_generate_equals_and_hash_);
     std::swap(optimize_for_, other->optimize_for_);
     std::swap(cc_generic_services_, other->cc_generic_services_);
     std::swap(java_generic_services_, other->java_generic_services_);
@@ -4773,7 +4905,7 @@
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
                  input, &message_set_wire_format_)));
-          _set_bit(0);
+          set_has_message_set_wire_format();
         } else {
           goto handle_uninterpreted;
         }
@@ -4789,7 +4921,7 @@
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
                  input, &no_standard_descriptor_accessor_)));
-          _set_bit(1);
+          set_has_no_standard_descriptor_accessor();
         } else {
           goto handle_uninterpreted;
         }
@@ -4836,12 +4968,12 @@
 void MessageOptions::SerializeWithCachedSizes(
     ::google::protobuf::io::CodedOutputStream* output) const {
   // optional bool message_set_wire_format = 1 [default = false];
-  if (_has_bit(0)) {
+  if (has_message_set_wire_format()) {
     ::google::protobuf::internal::WireFormatLite::WriteBool(1, this->message_set_wire_format(), output);
   }
   
   // optional bool no_standard_descriptor_accessor = 2 [default = false];
-  if (_has_bit(1)) {
+  if (has_no_standard_descriptor_accessor()) {
     ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->no_standard_descriptor_accessor(), output);
   }
   
@@ -4864,12 +4996,12 @@
 ::google::protobuf::uint8* MessageOptions::SerializeWithCachedSizesToArray(
     ::google::protobuf::uint8* target) const {
   // optional bool message_set_wire_format = 1 [default = false];
-  if (_has_bit(0)) {
+  if (has_message_set_wire_format()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(1, this->message_set_wire_format(), target);
   }
   
   // optional bool no_standard_descriptor_accessor = 2 [default = false];
-  if (_has_bit(1)) {
+  if (has_no_standard_descriptor_accessor()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->no_standard_descriptor_accessor(), target);
   }
   
@@ -4943,10 +5075,10 @@
   GOOGLE_CHECK_NE(&from, this);
   uninterpreted_option_.MergeFrom(from.uninterpreted_option_);
   if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (from._has_bit(0)) {
+    if (from.has_message_set_wire_format()) {
       set_message_set_wire_format(from.message_set_wire_format());
     }
-    if (from._has_bit(1)) {
+    if (from.has_no_standard_descriptor_accessor()) {
       set_no_standard_descriptor_accessor(from.no_standard_descriptor_accessor());
     }
   }
@@ -5021,7 +5153,6 @@
 const FieldOptions_CType FieldOptions::CType_MAX;
 const int FieldOptions::CType_ARRAYSIZE;
 #endif  // _MSC_VER
-const ::std::string FieldOptions::_default_experimental_map_key_;
 #ifndef _MSC_VER
 const int FieldOptions::kCtypeFieldNumber;
 const int FieldOptions::kPackedFieldNumber;
@@ -5049,7 +5180,7 @@
   ctype_ = 0;
   packed_ = false;
   deprecated_ = false;
-  experimental_map_key_ = const_cast< ::std::string*>(&_default_experimental_map_key_);
+  experimental_map_key_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
 }
 
@@ -5058,7 +5189,7 @@
 }
 
 void FieldOptions::SharedDtor() {
-  if (experimental_map_key_ != &_default_experimental_map_key_) {
+  if (experimental_map_key_ != &::google::protobuf::internal::kEmptyString) {
     delete experimental_map_key_;
   }
   if (this != default_instance_) {
@@ -5091,8 +5222,8 @@
     ctype_ = 0;
     packed_ = false;
     deprecated_ = false;
-    if (_has_bit(3)) {
-      if (experimental_map_key_ != &_default_experimental_map_key_) {
+    if (has_experimental_map_key()) {
+      if (experimental_map_key_ != &::google::protobuf::internal::kEmptyString) {
         experimental_map_key_->clear();
       }
     }
@@ -5136,7 +5267,7 @@
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
                  input, &packed_)));
-          _set_bit(1);
+          set_has_packed();
         } else {
           goto handle_uninterpreted;
         }
@@ -5152,7 +5283,7 @@
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
                  input, &deprecated_)));
-          _set_bit(2);
+          set_has_deprecated();
         } else {
           goto handle_uninterpreted;
         }
@@ -5216,23 +5347,23 @@
 void FieldOptions::SerializeWithCachedSizes(
     ::google::protobuf::io::CodedOutputStream* output) const {
   // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
-  if (_has_bit(0)) {
+  if (has_ctype()) {
     ::google::protobuf::internal::WireFormatLite::WriteEnum(
       1, this->ctype(), output);
   }
   
   // optional bool packed = 2;
-  if (_has_bit(1)) {
+  if (has_packed()) {
     ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->packed(), output);
   }
   
   // optional bool deprecated = 3 [default = false];
-  if (_has_bit(2)) {
+  if (has_deprecated()) {
     ::google::protobuf::internal::WireFormatLite::WriteBool(3, this->deprecated(), output);
   }
   
   // optional string experimental_map_key = 9;
-  if (_has_bit(3)) {
+  if (has_experimental_map_key()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->experimental_map_key().data(), this->experimental_map_key().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -5259,23 +5390,23 @@
 ::google::protobuf::uint8* FieldOptions::SerializeWithCachedSizesToArray(
     ::google::protobuf::uint8* target) const {
   // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
-  if (_has_bit(0)) {
+  if (has_ctype()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
       1, this->ctype(), target);
   }
   
   // optional bool packed = 2;
-  if (_has_bit(1)) {
+  if (has_packed()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->packed(), target);
   }
   
   // optional bool deprecated = 3 [default = false];
-  if (_has_bit(2)) {
+  if (has_deprecated()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(3, this->deprecated(), target);
   }
   
   // optional string experimental_map_key = 9;
-  if (_has_bit(3)) {
+  if (has_experimental_map_key()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->experimental_map_key().data(), this->experimental_map_key().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -5367,16 +5498,16 @@
   GOOGLE_CHECK_NE(&from, this);
   uninterpreted_option_.MergeFrom(from.uninterpreted_option_);
   if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (from._has_bit(0)) {
+    if (from.has_ctype()) {
       set_ctype(from.ctype());
     }
-    if (from._has_bit(1)) {
+    if (from.has_packed()) {
       set_packed(from.packed());
     }
-    if (from._has_bit(2)) {
+    if (from.has_deprecated()) {
       set_deprecated(from.deprecated());
     }
-    if (from._has_bit(3)) {
+    if (from.has_experimental_map_key()) {
       set_experimental_map_key(from.experimental_map_key());
     }
   }
@@ -6326,7 +6457,6 @@
 
 // ===================================================================
 
-const ::std::string UninterpretedOption_NamePart::_default_name_part_;
 #ifndef _MSC_VER
 const int UninterpretedOption_NamePart::kNamePartFieldNumber;
 const int UninterpretedOption_NamePart::kIsExtensionFieldNumber;
@@ -6348,7 +6478,7 @@
 
 void UninterpretedOption_NamePart::SharedCtor() {
   _cached_size_ = 0;
-  name_part_ = const_cast< ::std::string*>(&_default_name_part_);
+  name_part_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
   is_extension_ = false;
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
 }
@@ -6358,7 +6488,7 @@
 }
 
 void UninterpretedOption_NamePart::SharedDtor() {
-  if (name_part_ != &_default_name_part_) {
+  if (name_part_ != &::google::protobuf::internal::kEmptyString) {
     delete name_part_;
   }
   if (this != default_instance_) {
@@ -6387,8 +6517,8 @@
 
 void UninterpretedOption_NamePart::Clear() {
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (_has_bit(0)) {
-      if (name_part_ != &_default_name_part_) {
+    if (has_name_part()) {
+      if (name_part_ != &::google::protobuf::internal::kEmptyString) {
         name_part_->clear();
       }
     }
@@ -6428,7 +6558,7 @@
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
                  input, &is_extension_)));
-          _set_bit(1);
+          set_has_is_extension();
         } else {
           goto handle_uninterpreted;
         }
@@ -6455,7 +6585,7 @@
 void UninterpretedOption_NamePart::SerializeWithCachedSizes(
     ::google::protobuf::io::CodedOutputStream* output) const {
   // required string name_part = 1;
-  if (_has_bit(0)) {
+  if (has_name_part()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->name_part().data(), this->name_part().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -6464,7 +6594,7 @@
   }
   
   // required bool is_extension = 2;
-  if (_has_bit(1)) {
+  if (has_is_extension()) {
     ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->is_extension(), output);
   }
   
@@ -6477,7 +6607,7 @@
 ::google::protobuf::uint8* UninterpretedOption_NamePart::SerializeWithCachedSizesToArray(
     ::google::protobuf::uint8* target) const {
   // required string name_part = 1;
-  if (_has_bit(0)) {
+  if (has_name_part()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->name_part().data(), this->name_part().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -6487,7 +6617,7 @@
   }
   
   // required bool is_extension = 2;
-  if (_has_bit(1)) {
+  if (has_is_extension()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->is_extension(), target);
   }
   
@@ -6541,10 +6671,10 @@
 void UninterpretedOption_NamePart::MergeFrom(const UninterpretedOption_NamePart& from) {
   GOOGLE_CHECK_NE(&from, this);
   if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (from._has_bit(0)) {
+    if (from.has_name_part()) {
       set_name_part(from.name_part());
     }
-    if (from._has_bit(1)) {
+    if (from.has_is_extension()) {
       set_is_extension(from.is_extension());
     }
   }
@@ -6590,8 +6720,6 @@
 
 // -------------------------------------------------------------------
 
-const ::std::string UninterpretedOption::_default_identifier_value_;
-const ::std::string UninterpretedOption::_default_string_value_;
 #ifndef _MSC_VER
 const int UninterpretedOption::kNameFieldNumber;
 const int UninterpretedOption::kIdentifierValueFieldNumber;
@@ -6599,6 +6727,7 @@
 const int UninterpretedOption::kNegativeIntValueFieldNumber;
 const int UninterpretedOption::kDoubleValueFieldNumber;
 const int UninterpretedOption::kStringValueFieldNumber;
+const int UninterpretedOption::kAggregateValueFieldNumber;
 #endif  // !_MSC_VER
 
 UninterpretedOption::UninterpretedOption()
@@ -6617,11 +6746,12 @@
 
 void UninterpretedOption::SharedCtor() {
   _cached_size_ = 0;
-  identifier_value_ = const_cast< ::std::string*>(&_default_identifier_value_);
+  identifier_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
   positive_int_value_ = GOOGLE_ULONGLONG(0);
   negative_int_value_ = GOOGLE_LONGLONG(0);
   double_value_ = 0;
-  string_value_ = const_cast< ::std::string*>(&_default_string_value_);
+  string_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  aggregate_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
 }
 
@@ -6630,12 +6760,15 @@
 }
 
 void UninterpretedOption::SharedDtor() {
-  if (identifier_value_ != &_default_identifier_value_) {
+  if (identifier_value_ != &::google::protobuf::internal::kEmptyString) {
     delete identifier_value_;
   }
-  if (string_value_ != &_default_string_value_) {
+  if (string_value_ != &::google::protobuf::internal::kEmptyString) {
     delete string_value_;
   }
+  if (aggregate_value_ != &::google::protobuf::internal::kEmptyString) {
+    delete aggregate_value_;
+  }
   if (this != default_instance_) {
   }
 }
@@ -6662,19 +6795,24 @@
 
 void UninterpretedOption::Clear() {
   if (_has_bits_[1 / 32] & (0xffu << (1 % 32))) {
-    if (_has_bit(1)) {
-      if (identifier_value_ != &_default_identifier_value_) {
+    if (has_identifier_value()) {
+      if (identifier_value_ != &::google::protobuf::internal::kEmptyString) {
         identifier_value_->clear();
       }
     }
     positive_int_value_ = GOOGLE_ULONGLONG(0);
     negative_int_value_ = GOOGLE_LONGLONG(0);
     double_value_ = 0;
-    if (_has_bit(5)) {
-      if (string_value_ != &_default_string_value_) {
+    if (has_string_value()) {
+      if (string_value_ != &::google::protobuf::internal::kEmptyString) {
         string_value_->clear();
       }
     }
+    if (has_aggregate_value()) {
+      if (aggregate_value_ != &::google::protobuf::internal::kEmptyString) {
+        aggregate_value_->clear();
+      }
+    }
   }
   name_.Clear();
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
@@ -6727,7 +6865,7 @@
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    ::google::protobuf::uint64, ::google::protobuf::internal::WireFormatLite::TYPE_UINT64>(
                  input, &positive_int_value_)));
-          _set_bit(2);
+          set_has_positive_int_value();
         } else {
           goto handle_uninterpreted;
         }
@@ -6743,7 +6881,7 @@
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    ::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>(
                  input, &negative_int_value_)));
-          _set_bit(3);
+          set_has_negative_int_value();
         } else {
           goto handle_uninterpreted;
         }
@@ -6759,7 +6897,7 @@
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>(
                  input, &double_value_)));
-          _set_bit(4);
+          set_has_double_value();
         } else {
           goto handle_uninterpreted;
         }
@@ -6777,6 +6915,23 @@
         } else {
           goto handle_uninterpreted;
         }
+        if (input->ExpectTag(66)) goto parse_aggregate_value;
+        break;
+      }
+      
+      // optional string aggregate_value = 8;
+      case 8: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+         parse_aggregate_value:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_aggregate_value()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+            this->aggregate_value().data(), this->aggregate_value().length(),
+            ::google::protobuf::internal::WireFormat::PARSE);
+        } else {
+          goto handle_uninterpreted;
+        }
         if (input->ExpectAtEnd()) return true;
         break;
       }
@@ -6806,7 +6961,7 @@
   }
   
   // optional string identifier_value = 3;
-  if (_has_bit(1)) {
+  if (has_identifier_value()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->identifier_value().data(), this->identifier_value().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -6815,26 +6970,35 @@
   }
   
   // optional uint64 positive_int_value = 4;
-  if (_has_bit(2)) {
+  if (has_positive_int_value()) {
     ::google::protobuf::internal::WireFormatLite::WriteUInt64(4, this->positive_int_value(), output);
   }
   
   // optional int64 negative_int_value = 5;
-  if (_has_bit(3)) {
+  if (has_negative_int_value()) {
     ::google::protobuf::internal::WireFormatLite::WriteInt64(5, this->negative_int_value(), output);
   }
   
   // optional double double_value = 6;
-  if (_has_bit(4)) {
+  if (has_double_value()) {
     ::google::protobuf::internal::WireFormatLite::WriteDouble(6, this->double_value(), output);
   }
   
   // optional bytes string_value = 7;
-  if (_has_bit(5)) {
+  if (has_string_value()) {
     ::google::protobuf::internal::WireFormatLite::WriteBytes(
       7, this->string_value(), output);
   }
   
+  // optional string aggregate_value = 8;
+  if (has_aggregate_value()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->aggregate_value().data(), this->aggregate_value().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      8, this->aggregate_value(), output);
+  }
+  
   if (!unknown_fields().empty()) {
     ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
         unknown_fields(), output);
@@ -6851,7 +7015,7 @@
   }
   
   // optional string identifier_value = 3;
-  if (_has_bit(1)) {
+  if (has_identifier_value()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->identifier_value().data(), this->identifier_value().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -6861,27 +7025,37 @@
   }
   
   // optional uint64 positive_int_value = 4;
-  if (_has_bit(2)) {
+  if (has_positive_int_value()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteUInt64ToArray(4, this->positive_int_value(), target);
   }
   
   // optional int64 negative_int_value = 5;
-  if (_has_bit(3)) {
+  if (has_negative_int_value()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteInt64ToArray(5, this->negative_int_value(), target);
   }
   
   // optional double double_value = 6;
-  if (_has_bit(4)) {
+  if (has_double_value()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(6, this->double_value(), target);
   }
   
   // optional bytes string_value = 7;
-  if (_has_bit(5)) {
+  if (has_string_value()) {
     target =
       ::google::protobuf::internal::WireFormatLite::WriteBytesToArray(
         7, this->string_value(), target);
   }
   
+  // optional string aggregate_value = 8;
+  if (has_aggregate_value()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->aggregate_value().data(), this->aggregate_value().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        8, this->aggregate_value(), target);
+  }
+  
   if (!unknown_fields().empty()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
         unknown_fields(), target);
@@ -6926,6 +7100,13 @@
           this->string_value());
     }
     
+    // optional string aggregate_value = 8;
+    if (has_aggregate_value()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->aggregate_value());
+    }
+    
   }
   // repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
   total_size += 1 * this->name_size();
@@ -6962,21 +7143,24 @@
   GOOGLE_CHECK_NE(&from, this);
   name_.MergeFrom(from.name_);
   if (from._has_bits_[1 / 32] & (0xffu << (1 % 32))) {
-    if (from._has_bit(1)) {
+    if (from.has_identifier_value()) {
       set_identifier_value(from.identifier_value());
     }
-    if (from._has_bit(2)) {
+    if (from.has_positive_int_value()) {
       set_positive_int_value(from.positive_int_value());
     }
-    if (from._has_bit(3)) {
+    if (from.has_negative_int_value()) {
       set_negative_int_value(from.negative_int_value());
     }
-    if (from._has_bit(4)) {
+    if (from.has_double_value()) {
       set_double_value(from.double_value());
     }
-    if (from._has_bit(5)) {
+    if (from.has_string_value()) {
       set_string_value(from.string_value());
     }
+    if (from.has_aggregate_value()) {
+      set_aggregate_value(from.aggregate_value());
+    }
   }
   mutable_unknown_fields()->MergeFrom(from.unknown_fields());
 }
@@ -7009,6 +7193,7 @@
     std::swap(negative_int_value_, other->negative_int_value_);
     std::swap(double_value_, other->double_value_);
     std::swap(string_value_, other->string_value_);
+    std::swap(aggregate_value_, other->aggregate_value_);
     std::swap(_has_bits_[0], other->_has_bits_[0]);
     _unknown_fields_.Swap(&other->_unknown_fields_);
     std::swap(_cached_size_, other->_cached_size_);
@@ -7024,6 +7209,497 @@
 }
 
 
+// ===================================================================
+
+#ifndef _MSC_VER
+const int SourceCodeInfo_Location::kPathFieldNumber;
+const int SourceCodeInfo_Location::kSpanFieldNumber;
+#endif  // !_MSC_VER
+
+SourceCodeInfo_Location::SourceCodeInfo_Location()
+  : ::google::protobuf::Message() {
+  SharedCtor();
+}
+
+void SourceCodeInfo_Location::InitAsDefaultInstance() {
+}
+
+SourceCodeInfo_Location::SourceCodeInfo_Location(const SourceCodeInfo_Location& from)
+  : ::google::protobuf::Message() {
+  SharedCtor();
+  MergeFrom(from);
+}
+
+void SourceCodeInfo_Location::SharedCtor() {
+  _cached_size_ = 0;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+SourceCodeInfo_Location::~SourceCodeInfo_Location() {
+  SharedDtor();
+}
+
+void SourceCodeInfo_Location::SharedDtor() {
+  if (this != default_instance_) {
+  }
+}
+
+void SourceCodeInfo_Location::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* SourceCodeInfo_Location::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return SourceCodeInfo_Location_descriptor_;
+}
+
+const SourceCodeInfo_Location& SourceCodeInfo_Location::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();  return *default_instance_;
+}
+
+SourceCodeInfo_Location* SourceCodeInfo_Location::default_instance_ = NULL;
+
+SourceCodeInfo_Location* SourceCodeInfo_Location::New() const {
+  return new SourceCodeInfo_Location;
+}
+
+void SourceCodeInfo_Location::Clear() {
+  path_.Clear();
+  span_.Clear();
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->Clear();
+}
+
+bool SourceCodeInfo_Location::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
+  ::google::protobuf::uint32 tag;
+  while ((tag = input->ReadTag()) != 0) {
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // repeated int32 path = 1 [packed = true];
+      case 1: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, this->mutable_path())));
+        } else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag)
+                   == ::google::protobuf::internal::WireFormatLite::
+                      WIRETYPE_VARINT) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitiveNoInline<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 1, 10, input, this->mutable_path())));
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(18)) goto parse_span;
+        break;
+      }
+      
+      // repeated int32 span = 2 [packed = true];
+      case 2: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+         parse_span:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, this->mutable_span())));
+        } else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag)
+                   == ::google::protobuf::internal::WireFormatLite::
+                      WIRETYPE_VARINT) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitiveNoInline<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 1, 18, input, this->mutable_span())));
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectAtEnd()) return true;
+        break;
+      }
+      
+      default: {
+      handle_uninterpreted:
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          return true;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+  return true;
+#undef DO_
+}
+
+void SourceCodeInfo_Location::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // repeated int32 path = 1 [packed = true];
+  if (this->path_size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteTag(1, ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output);
+    output->WriteVarint32(_path_cached_byte_size_);
+  }
+  for (int i = 0; i < this->path_size(); i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32NoTag(
+      this->path(i), output);
+  }
+  
+  // repeated int32 span = 2 [packed = true];
+  if (this->span_size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteTag(2, ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output);
+    output->WriteVarint32(_span_cached_byte_size_);
+  }
+  for (int i = 0; i < this->span_size(); i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32NoTag(
+      this->span(i), output);
+  }
+  
+  if (!unknown_fields().empty()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        unknown_fields(), output);
+  }
+}
+
+::google::protobuf::uint8* SourceCodeInfo_Location::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // repeated int32 path = 1 [packed = true];
+  if (this->path_size() > 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(
+      1,
+      ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
+      target);
+    target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(
+      _path_cached_byte_size_, target);
+  }
+  for (int i = 0; i < this->path_size(); i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteInt32NoTagToArray(this->path(i), target);
+  }
+  
+  // repeated int32 span = 2 [packed = true];
+  if (this->span_size() > 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(
+      2,
+      ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
+      target);
+    target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(
+      _span_cached_byte_size_, target);
+  }
+  for (int i = 0; i < this->span_size(); i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteInt32NoTagToArray(this->span(i), target);
+  }
+  
+  if (!unknown_fields().empty()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        unknown_fields(), target);
+  }
+  return target;
+}
+
+int SourceCodeInfo_Location::ByteSize() const {
+  int total_size = 0;
+  
+  // repeated int32 path = 1 [packed = true];
+  {
+    int data_size = 0;
+    for (int i = 0; i < this->path_size(); i++) {
+      data_size += ::google::protobuf::internal::WireFormatLite::
+        Int32Size(this->path(i));
+    }
+    if (data_size > 0) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);
+    }
+    _path_cached_byte_size_ = data_size;
+    total_size += data_size;
+  }
+  
+  // repeated int32 span = 2 [packed = true];
+  {
+    int data_size = 0;
+    for (int i = 0; i < this->span_size(); i++) {
+      data_size += ::google::protobuf::internal::WireFormatLite::
+        Int32Size(this->span(i));
+    }
+    if (data_size > 0) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);
+    }
+    _span_cached_byte_size_ = data_size;
+    total_size += data_size;
+  }
+  
+  if (!unknown_fields().empty()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        unknown_fields());
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void SourceCodeInfo_Location::MergeFrom(const ::google::protobuf::Message& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  const SourceCodeInfo_Location* source =
+    ::google::protobuf::internal::dynamic_cast_if_available<const SourceCodeInfo_Location*>(
+      &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void SourceCodeInfo_Location::MergeFrom(const SourceCodeInfo_Location& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  path_.MergeFrom(from.path_);
+  span_.MergeFrom(from.span_);
+  mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+}
+
+void SourceCodeInfo_Location::CopyFrom(const ::google::protobuf::Message& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void SourceCodeInfo_Location::CopyFrom(const SourceCodeInfo_Location& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool SourceCodeInfo_Location::IsInitialized() const {
+  
+  return true;
+}
+
+void SourceCodeInfo_Location::Swap(SourceCodeInfo_Location* other) {
+  if (other != this) {
+    path_.Swap(&other->path_);
+    span_.Swap(&other->span_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    _unknown_fields_.Swap(&other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::google::protobuf::Metadata SourceCodeInfo_Location::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = SourceCodeInfo_Location_descriptor_;
+  metadata.reflection = SourceCodeInfo_Location_reflection_;
+  return metadata;
+}
+
+
+// -------------------------------------------------------------------
+
+#ifndef _MSC_VER
+const int SourceCodeInfo::kLocationFieldNumber;
+#endif  // !_MSC_VER
+
+SourceCodeInfo::SourceCodeInfo()
+  : ::google::protobuf::Message() {
+  SharedCtor();
+}
+
+void SourceCodeInfo::InitAsDefaultInstance() {
+}
+
+SourceCodeInfo::SourceCodeInfo(const SourceCodeInfo& from)
+  : ::google::protobuf::Message() {
+  SharedCtor();
+  MergeFrom(from);
+}
+
+void SourceCodeInfo::SharedCtor() {
+  _cached_size_ = 0;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+SourceCodeInfo::~SourceCodeInfo() {
+  SharedDtor();
+}
+
+void SourceCodeInfo::SharedDtor() {
+  if (this != default_instance_) {
+  }
+}
+
+void SourceCodeInfo::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* SourceCodeInfo::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return SourceCodeInfo_descriptor_;
+}
+
+const SourceCodeInfo& SourceCodeInfo::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();  return *default_instance_;
+}
+
+SourceCodeInfo* SourceCodeInfo::default_instance_ = NULL;
+
+SourceCodeInfo* SourceCodeInfo::New() const {
+  return new SourceCodeInfo;
+}
+
+void SourceCodeInfo::Clear() {
+  location_.Clear();
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->Clear();
+}
+
+bool SourceCodeInfo::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
+  ::google::protobuf::uint32 tag;
+  while ((tag = input->ReadTag()) != 0) {
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // repeated .google.protobuf.SourceCodeInfo.Location location = 1;
+      case 1: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+         parse_location:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+                input, add_location()));
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(10)) goto parse_location;
+        if (input->ExpectAtEnd()) return true;
+        break;
+      }
+      
+      default: {
+      handle_uninterpreted:
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          return true;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+  return true;
+#undef DO_
+}
+
+void SourceCodeInfo::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // repeated .google.protobuf.SourceCodeInfo.Location location = 1;
+  for (int i = 0; i < this->location_size(); i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1, this->location(i), output);
+  }
+  
+  if (!unknown_fields().empty()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        unknown_fields(), output);
+  }
+}
+
+::google::protobuf::uint8* SourceCodeInfo::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // repeated .google.protobuf.SourceCodeInfo.Location location = 1;
+  for (int i = 0; i < this->location_size(); i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        1, this->location(i), target);
+  }
+  
+  if (!unknown_fields().empty()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        unknown_fields(), target);
+  }
+  return target;
+}
+
+int SourceCodeInfo::ByteSize() const {
+  int total_size = 0;
+  
+  // repeated .google.protobuf.SourceCodeInfo.Location location = 1;
+  total_size += 1 * this->location_size();
+  for (int i = 0; i < this->location_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->location(i));
+  }
+  
+  if (!unknown_fields().empty()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        unknown_fields());
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void SourceCodeInfo::MergeFrom(const ::google::protobuf::Message& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  const SourceCodeInfo* source =
+    ::google::protobuf::internal::dynamic_cast_if_available<const SourceCodeInfo*>(
+      &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void SourceCodeInfo::MergeFrom(const SourceCodeInfo& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  location_.MergeFrom(from.location_);
+  mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+}
+
+void SourceCodeInfo::CopyFrom(const ::google::protobuf::Message& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void SourceCodeInfo::CopyFrom(const SourceCodeInfo& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool SourceCodeInfo::IsInitialized() const {
+  
+  return true;
+}
+
+void SourceCodeInfo::Swap(SourceCodeInfo* other) {
+  if (other != this) {
+    location_.Swap(&other->location_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    _unknown_fields_.Swap(&other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::google::protobuf::Metadata SourceCodeInfo::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = SourceCodeInfo_descriptor_;
+  metadata.reflection = SourceCodeInfo_reflection_;
+  return metadata;
+}
+
+
 // @@protoc_insertion_point(namespace_scope)
 
 }  // namespace protobuf
diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h
index 205c547..e85a933 100644
--- a/src/google/protobuf/descriptor.pb.h
+++ b/src/google/protobuf/descriptor.pb.h
@@ -51,6 +51,8 @@
 class MethodOptions;
 class UninterpretedOption;
 class UninterpretedOption_NamePart;
+class SourceCodeInfo;
+class SourceCodeInfo_Location;
 
 enum FieldDescriptorProto_Type {
   FieldDescriptorProto_Type_TYPE_DOUBLE = 1,
@@ -217,27 +219,18 @@
   
   // @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorSet)
  private:
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > file_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
+  
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static FileDescriptorSet* default_instance_;
 };
@@ -306,6 +299,7 @@
   inline void set_name(const char* value);
   inline void set_name(const char* value, size_t size);
   inline ::std::string* mutable_name();
+  inline ::std::string* release_name();
   
   // optional string package = 2;
   inline bool has_package() const;
@@ -316,6 +310,7 @@
   inline void set_package(const char* value);
   inline void set_package(const char* value, size_t size);
   inline ::std::string* mutable_package();
+  inline ::std::string* release_package();
   
   // repeated string dependency = 3;
   inline int dependency_size() const;
@@ -387,39 +382,46 @@
   static const int kOptionsFieldNumber = 8;
   inline const ::google::protobuf::FileOptions& options() const;
   inline ::google::protobuf::FileOptions* mutable_options();
+  inline ::google::protobuf::FileOptions* release_options();
+  
+  // optional .google.protobuf.SourceCodeInfo source_code_info = 9;
+  inline bool has_source_code_info() const;
+  inline void clear_source_code_info();
+  static const int kSourceCodeInfoFieldNumber = 9;
+  inline const ::google::protobuf::SourceCodeInfo& source_code_info() const;
+  inline ::google::protobuf::SourceCodeInfo* mutable_source_code_info();
+  inline ::google::protobuf::SourceCodeInfo* release_source_code_info();
   
   // @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorProto)
  private:
+  inline void set_has_name();
+  inline void clear_has_name();
+  inline void set_has_package();
+  inline void clear_has_package();
+  inline void set_has_options();
+  inline void clear_has_options();
+  inline void set_has_source_code_info();
+  inline void clear_has_source_code_info();
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   ::std::string* name_;
-  static const ::std::string _default_name_;
   ::std::string* package_;
-  static const ::std::string _default_package_;
   ::google::protobuf::RepeatedPtrField< ::std::string> dependency_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto > message_type_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto > enum_type_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto > service_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto > extension_;
   ::google::protobuf::FileOptions* options_;
+  ::google::protobuf::SourceCodeInfo* source_code_info_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(9 + 31) / 32];
+  
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(8 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static FileDescriptorProto* default_instance_;
 };
@@ -495,28 +497,23 @@
   
   // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto.ExtensionRange)
  private:
+  inline void set_has_start();
+  inline void clear_has_start();
+  inline void set_has_end();
+  inline void clear_has_end();
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   ::google::protobuf::int32 start_;
   ::google::protobuf::int32 end_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
+  
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static DescriptorProto_ExtensionRange* default_instance_;
 };
@@ -587,6 +584,7 @@
   inline void set_name(const char* value);
   inline void set_name(const char* value, size_t size);
   inline ::std::string* mutable_name();
+  inline ::std::string* release_name();
   
   // repeated .google.protobuf.FieldDescriptorProto field = 2;
   inline int field_size() const;
@@ -654,37 +652,32 @@
   static const int kOptionsFieldNumber = 7;
   inline const ::google::protobuf::MessageOptions& options() const;
   inline ::google::protobuf::MessageOptions* mutable_options();
+  inline ::google::protobuf::MessageOptions* release_options();
   
   // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto)
  private:
+  inline void set_has_name();
+  inline void clear_has_name();
+  inline void set_has_options();
+  inline void clear_has_options();
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   ::std::string* name_;
-  static const ::std::string _default_name_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto > field_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto > extension_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto > nested_type_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto > enum_type_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange > extension_range_;
   ::google::protobuf::MessageOptions* options_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(7 + 31) / 32];
+  
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(7 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static DescriptorProto* default_instance_;
 };
@@ -818,6 +811,7 @@
   inline void set_name(const char* value);
   inline void set_name(const char* value, size_t size);
   inline ::std::string* mutable_name();
+  inline ::std::string* release_name();
   
   // optional int32 number = 3;
   inline bool has_number() const;
@@ -849,6 +843,7 @@
   inline void set_type_name(const char* value);
   inline void set_type_name(const char* value, size_t size);
   inline ::std::string* mutable_type_name();
+  inline ::std::string* release_type_name();
   
   // optional string extendee = 2;
   inline bool has_extendee() const;
@@ -859,6 +854,7 @@
   inline void set_extendee(const char* value);
   inline void set_extendee(const char* value, size_t size);
   inline ::std::string* mutable_extendee();
+  inline ::std::string* release_extendee();
   
   // optional string default_value = 7;
   inline bool has_default_value() const;
@@ -869,6 +865,7 @@
   inline void set_default_value(const char* value);
   inline void set_default_value(const char* value, size_t size);
   inline ::std::string* mutable_default_value();
+  inline ::std::string* release_default_value();
   
   // optional .google.protobuf.FieldOptions options = 8;
   inline bool has_options() const;
@@ -876,41 +873,45 @@
   static const int kOptionsFieldNumber = 8;
   inline const ::google::protobuf::FieldOptions& options() const;
   inline ::google::protobuf::FieldOptions* mutable_options();
+  inline ::google::protobuf::FieldOptions* release_options();
   
   // @@protoc_insertion_point(class_scope:google.protobuf.FieldDescriptorProto)
  private:
+  inline void set_has_name();
+  inline void clear_has_name();
+  inline void set_has_number();
+  inline void clear_has_number();
+  inline void set_has_label();
+  inline void clear_has_label();
+  inline void set_has_type();
+  inline void clear_has_type();
+  inline void set_has_type_name();
+  inline void clear_has_type_name();
+  inline void set_has_extendee();
+  inline void clear_has_extendee();
+  inline void set_has_default_value();
+  inline void clear_has_default_value();
+  inline void set_has_options();
+  inline void clear_has_options();
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   ::std::string* name_;
-  static const ::std::string _default_name_;
   ::google::protobuf::int32 number_;
   int label_;
-  int type_;
   ::std::string* type_name_;
-  static const ::std::string _default_type_name_;
   ::std::string* extendee_;
-  static const ::std::string _default_extendee_;
   ::std::string* default_value_;
-  static const ::std::string _default_default_value_;
   ::google::protobuf::FieldOptions* options_;
+  int type_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(8 + 31) / 32];
+  
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(8 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static FieldDescriptorProto* default_instance_;
 };
@@ -979,6 +980,7 @@
   inline void set_name(const char* value);
   inline void set_name(const char* value, size_t size);
   inline ::std::string* mutable_name();
+  inline ::std::string* release_name();
   
   // repeated .google.protobuf.EnumValueDescriptorProto value = 2;
   inline int value_size() const;
@@ -998,33 +1000,28 @@
   static const int kOptionsFieldNumber = 3;
   inline const ::google::protobuf::EnumOptions& options() const;
   inline ::google::protobuf::EnumOptions* mutable_options();
+  inline ::google::protobuf::EnumOptions* release_options();
   
   // @@protoc_insertion_point(class_scope:google.protobuf.EnumDescriptorProto)
  private:
+  inline void set_has_name();
+  inline void clear_has_name();
+  inline void set_has_options();
+  inline void clear_has_options();
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   ::std::string* name_;
-  static const ::std::string _default_name_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto > value_;
   ::google::protobuf::EnumOptions* options_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
+  
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static EnumDescriptorProto* default_instance_;
 };
@@ -1093,6 +1090,7 @@
   inline void set_name(const char* value);
   inline void set_name(const char* value, size_t size);
   inline ::std::string* mutable_name();
+  inline ::std::string* release_name();
   
   // optional int32 number = 2;
   inline bool has_number() const;
@@ -1107,33 +1105,30 @@
   static const int kOptionsFieldNumber = 3;
   inline const ::google::protobuf::EnumValueOptions& options() const;
   inline ::google::protobuf::EnumValueOptions* mutable_options();
+  inline ::google::protobuf::EnumValueOptions* release_options();
   
   // @@protoc_insertion_point(class_scope:google.protobuf.EnumValueDescriptorProto)
  private:
+  inline void set_has_name();
+  inline void clear_has_name();
+  inline void set_has_number();
+  inline void clear_has_number();
+  inline void set_has_options();
+  inline void clear_has_options();
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   ::std::string* name_;
-  static const ::std::string _default_name_;
-  ::google::protobuf::int32 number_;
   ::google::protobuf::EnumValueOptions* options_;
+  ::google::protobuf::int32 number_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
+  
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static EnumValueDescriptorProto* default_instance_;
 };
@@ -1202,6 +1197,7 @@
   inline void set_name(const char* value);
   inline void set_name(const char* value, size_t size);
   inline ::std::string* mutable_name();
+  inline ::std::string* release_name();
   
   // repeated .google.protobuf.MethodDescriptorProto method = 2;
   inline int method_size() const;
@@ -1221,33 +1217,28 @@
   static const int kOptionsFieldNumber = 3;
   inline const ::google::protobuf::ServiceOptions& options() const;
   inline ::google::protobuf::ServiceOptions* mutable_options();
+  inline ::google::protobuf::ServiceOptions* release_options();
   
   // @@protoc_insertion_point(class_scope:google.protobuf.ServiceDescriptorProto)
  private:
+  inline void set_has_name();
+  inline void clear_has_name();
+  inline void set_has_options();
+  inline void clear_has_options();
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   ::std::string* name_;
-  static const ::std::string _default_name_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto > method_;
   ::google::protobuf::ServiceOptions* options_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
+  
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static ServiceDescriptorProto* default_instance_;
 };
@@ -1316,6 +1307,7 @@
   inline void set_name(const char* value);
   inline void set_name(const char* value, size_t size);
   inline ::std::string* mutable_name();
+  inline ::std::string* release_name();
   
   // optional string input_type = 2;
   inline bool has_input_type() const;
@@ -1326,6 +1318,7 @@
   inline void set_input_type(const char* value);
   inline void set_input_type(const char* value, size_t size);
   inline ::std::string* mutable_input_type();
+  inline ::std::string* release_input_type();
   
   // optional string output_type = 3;
   inline bool has_output_type() const;
@@ -1336,6 +1329,7 @@
   inline void set_output_type(const char* value);
   inline void set_output_type(const char* value, size_t size);
   inline ::std::string* mutable_output_type();
+  inline ::std::string* release_output_type();
   
   // optional .google.protobuf.MethodOptions options = 4;
   inline bool has_options() const;
@@ -1343,36 +1337,33 @@
   static const int kOptionsFieldNumber = 4;
   inline const ::google::protobuf::MethodOptions& options() const;
   inline ::google::protobuf::MethodOptions* mutable_options();
+  inline ::google::protobuf::MethodOptions* release_options();
   
   // @@protoc_insertion_point(class_scope:google.protobuf.MethodDescriptorProto)
  private:
+  inline void set_has_name();
+  inline void clear_has_name();
+  inline void set_has_input_type();
+  inline void clear_has_input_type();
+  inline void set_has_output_type();
+  inline void clear_has_output_type();
+  inline void set_has_options();
+  inline void clear_has_options();
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   ::std::string* name_;
-  static const ::std::string _default_name_;
   ::std::string* input_type_;
-  static const ::std::string _default_input_type_;
   ::std::string* output_type_;
-  static const ::std::string _default_output_type_;
   ::google::protobuf::MethodOptions* options_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(4 + 31) / 32];
+  
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(4 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static MethodDescriptorProto* default_instance_;
 };
@@ -1466,6 +1457,7 @@
   inline void set_java_package(const char* value);
   inline void set_java_package(const char* value, size_t size);
   inline ::std::string* mutable_java_package();
+  inline ::std::string* release_java_package();
   
   // optional string java_outer_classname = 8;
   inline bool has_java_outer_classname() const;
@@ -1476,6 +1468,7 @@
   inline void set_java_outer_classname(const char* value);
   inline void set_java_outer_classname(const char* value, size_t size);
   inline ::std::string* mutable_java_outer_classname();
+  inline ::std::string* release_java_outer_classname();
   
   // optional bool java_multiple_files = 10 [default = false];
   inline bool has_java_multiple_files() const;
@@ -1484,6 +1477,13 @@
   inline bool java_multiple_files() const;
   inline void set_java_multiple_files(bool value);
   
+  // optional bool java_generate_equals_and_hash = 20 [default = false];
+  inline bool has_java_generate_equals_and_hash() const;
+  inline void clear_java_generate_equals_and_hash();
+  static const int kJavaGenerateEqualsAndHashFieldNumber = 20;
+  inline bool java_generate_equals_and_hash() const;
+  inline void set_java_generate_equals_and_hash(bool value);
+  
   // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
   inline bool has_optimize_for() const;
   inline void clear_optimize_for();
@@ -1491,21 +1491,21 @@
   inline ::google::protobuf::FileOptions_OptimizeMode optimize_for() const;
   inline void set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value);
   
-  // optional bool cc_generic_services = 16 [default = true];
+  // optional bool cc_generic_services = 16 [default = false];
   inline bool has_cc_generic_services() const;
   inline void clear_cc_generic_services();
   static const int kCcGenericServicesFieldNumber = 16;
   inline bool cc_generic_services() const;
   inline void set_cc_generic_services(bool value);
   
-  // optional bool java_generic_services = 17 [default = true];
+  // optional bool java_generic_services = 17 [default = false];
   inline bool has_java_generic_services() const;
   inline void clear_java_generic_services();
   static const int kJavaGenericServicesFieldNumber = 17;
   inline bool java_generic_services() const;
   inline void set_java_generic_services(bool value);
   
-  // optional bool py_generic_services = 18 [default = true];
+  // optional bool py_generic_services = 18 [default = false];
   inline bool has_py_generic_services() const;
   inline void clear_py_generic_services();
   static const int kPyGenericServicesFieldNumber = 18;
@@ -1527,37 +1527,44 @@
   GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FileOptions)
   // @@protoc_insertion_point(class_scope:google.protobuf.FileOptions)
  private:
+  inline void set_has_java_package();
+  inline void clear_has_java_package();
+  inline void set_has_java_outer_classname();
+  inline void clear_has_java_outer_classname();
+  inline void set_has_java_multiple_files();
+  inline void clear_has_java_multiple_files();
+  inline void set_has_java_generate_equals_and_hash();
+  inline void clear_has_java_generate_equals_and_hash();
+  inline void set_has_optimize_for();
+  inline void clear_has_optimize_for();
+  inline void set_has_cc_generic_services();
+  inline void clear_has_cc_generic_services();
+  inline void set_has_java_generic_services();
+  inline void clear_has_java_generic_services();
+  inline void set_has_py_generic_services();
+  inline void clear_has_py_generic_services();
+  
   ::google::protobuf::internal::ExtensionSet _extensions_;
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   ::std::string* java_package_;
-  static const ::std::string _default_java_package_;
   ::std::string* java_outer_classname_;
-  static const ::std::string _default_java_outer_classname_;
-  bool java_multiple_files_;
   int optimize_for_;
+  bool java_multiple_files_;
+  bool java_generate_equals_and_hash_;
   bool cc_generic_services_;
   bool java_generic_services_;
-  bool py_generic_services_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
+  bool py_generic_services_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(9 + 31) / 32];
+  
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(8 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static FileOptions* default_instance_;
 };
@@ -1646,30 +1653,26 @@
   GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MessageOptions)
   // @@protoc_insertion_point(class_scope:google.protobuf.MessageOptions)
  private:
-  ::google::protobuf::internal::ExtensionSet _extensions_;
-  ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
+  inline void set_has_message_set_wire_format();
+  inline void clear_has_message_set_wire_format();
+  inline void set_has_no_standard_descriptor_accessor();
+  inline void clear_has_no_standard_descriptor_accessor();
   
+  ::google::protobuf::internal::ExtensionSet _extensions_;
+  
+  ::google::protobuf::UnknownFieldSet _unknown_fields_;
+  
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
   bool message_set_wire_format_;
   bool no_standard_descriptor_accessor_;
-  ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
+  
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static MessageOptions* default_instance_;
 };
@@ -1784,6 +1787,7 @@
   inline void set_experimental_map_key(const char* value);
   inline void set_experimental_map_key(const char* value, size_t size);
   inline ::std::string* mutable_experimental_map_key();
+  inline ::std::string* release_experimental_map_key();
   
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   inline int uninterpreted_option_size() const;
@@ -1800,33 +1804,32 @@
   GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FieldOptions)
   // @@protoc_insertion_point(class_scope:google.protobuf.FieldOptions)
  private:
+  inline void set_has_ctype();
+  inline void clear_has_ctype();
+  inline void set_has_packed();
+  inline void clear_has_packed();
+  inline void set_has_deprecated();
+  inline void clear_has_deprecated();
+  inline void set_has_experimental_map_key();
+  inline void clear_has_experimental_map_key();
+  
   ::google::protobuf::internal::ExtensionSet _extensions_;
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   int ctype_;
   bool packed_;
   bool deprecated_;
   ::std::string* experimental_map_key_;
-  static const ::std::string _default_experimental_map_key_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(5 + 31) / 32];
+  
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(5 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static FieldOptions* default_instance_;
 };
@@ -1901,28 +1904,20 @@
   GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumOptions)
   // @@protoc_insertion_point(class_scope:google.protobuf.EnumOptions)
  private:
+  
   ::google::protobuf::internal::ExtensionSet _extensions_;
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
+  
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static EnumOptions* default_instance_;
 };
@@ -1997,28 +1992,20 @@
   GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumValueOptions)
   // @@protoc_insertion_point(class_scope:google.protobuf.EnumValueOptions)
  private:
+  
   ::google::protobuf::internal::ExtensionSet _extensions_;
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
+  
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static EnumValueOptions* default_instance_;
 };
@@ -2093,28 +2080,20 @@
   GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(ServiceOptions)
   // @@protoc_insertion_point(class_scope:google.protobuf.ServiceOptions)
  private:
+  
   ::google::protobuf::internal::ExtensionSet _extensions_;
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
+  
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static ServiceOptions* default_instance_;
 };
@@ -2189,28 +2168,20 @@
   GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MethodOptions)
   // @@protoc_insertion_point(class_scope:google.protobuf.MethodOptions)
  private:
+  
   ::google::protobuf::internal::ExtensionSet _extensions_;
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
+  
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static MethodOptions* default_instance_;
 };
@@ -2279,6 +2250,7 @@
   inline void set_name_part(const char* value);
   inline void set_name_part(const char* value, size_t size);
   inline ::std::string* mutable_name_part();
+  inline ::std::string* release_name_part();
   
   // required bool is_extension = 2;
   inline bool has_is_extension() const;
@@ -2289,29 +2261,23 @@
   
   // @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption.NamePart)
  private:
+  inline void set_has_name_part();
+  inline void clear_has_name_part();
+  inline void set_has_is_extension();
+  inline void clear_has_is_extension();
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   ::std::string* name_part_;
-  static const ::std::string _default_name_part_;
   bool is_extension_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
+  
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static UninterpretedOption_NamePart* default_instance_;
 };
@@ -2394,6 +2360,7 @@
   inline void set_identifier_value(const char* value);
   inline void set_identifier_value(const char* value, size_t size);
   inline ::std::string* mutable_identifier_value();
+  inline ::std::string* release_identifier_value();
   
   // optional uint64 positive_int_value = 4;
   inline bool has_positive_int_value() const;
@@ -2425,40 +2392,241 @@
   inline void set_string_value(const char* value);
   inline void set_string_value(const void* value, size_t size);
   inline ::std::string* mutable_string_value();
+  inline ::std::string* release_string_value();
+  
+  // optional string aggregate_value = 8;
+  inline bool has_aggregate_value() const;
+  inline void clear_aggregate_value();
+  static const int kAggregateValueFieldNumber = 8;
+  inline const ::std::string& aggregate_value() const;
+  inline void set_aggregate_value(const ::std::string& value);
+  inline void set_aggregate_value(const char* value);
+  inline void set_aggregate_value(const char* value, size_t size);
+  inline ::std::string* mutable_aggregate_value();
+  inline ::std::string* release_aggregate_value();
   
   // @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption)
  private:
+  inline void set_has_identifier_value();
+  inline void clear_has_identifier_value();
+  inline void set_has_positive_int_value();
+  inline void clear_has_positive_int_value();
+  inline void set_has_negative_int_value();
+  inline void clear_has_negative_int_value();
+  inline void set_has_double_value();
+  inline void clear_has_double_value();
+  inline void set_has_string_value();
+  inline void clear_has_string_value();
+  inline void set_has_aggregate_value();
+  inline void clear_has_aggregate_value();
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart > name_;
   ::std::string* identifier_value_;
-  static const ::std::string _default_identifier_value_;
   ::google::protobuf::uint64 positive_int_value_;
   ::google::protobuf::int64 negative_int_value_;
   double double_value_;
   ::std::string* string_value_;
-  static const ::std::string _default_string_value_;
+  ::std::string* aggregate_value_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(7 + 31) / 32];
+  
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(6 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static UninterpretedOption* default_instance_;
 };
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT SourceCodeInfo_Location : public ::google::protobuf::Message {
+ public:
+  SourceCodeInfo_Location();
+  virtual ~SourceCodeInfo_Location();
+  
+  SourceCodeInfo_Location(const SourceCodeInfo_Location& from);
+  
+  inline SourceCodeInfo_Location& operator=(const SourceCodeInfo_Location& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _unknown_fields_;
+  }
+  
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+  
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const SourceCodeInfo_Location& default_instance();
+  
+  void Swap(SourceCodeInfo_Location* other);
+  
+  // implements Message ----------------------------------------------
+  
+  SourceCodeInfo_Location* New() const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const SourceCodeInfo_Location& from);
+  void MergeFrom(const SourceCodeInfo_Location& from);
+  void Clear();
+  bool IsInitialized() const;
+  
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  
+  ::google::protobuf::Metadata GetMetadata() const;
+  
+  // nested types ----------------------------------------------------
+  
+  // accessors -------------------------------------------------------
+  
+  // repeated int32 path = 1 [packed = true];
+  inline int path_size() const;
+  inline void clear_path();
+  static const int kPathFieldNumber = 1;
+  inline ::google::protobuf::int32 path(int index) const;
+  inline void set_path(int index, ::google::protobuf::int32 value);
+  inline void add_path(::google::protobuf::int32 value);
+  inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+      path() const;
+  inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+      mutable_path();
+  
+  // repeated int32 span = 2 [packed = true];
+  inline int span_size() const;
+  inline void clear_span();
+  static const int kSpanFieldNumber = 2;
+  inline ::google::protobuf::int32 span(int index) const;
+  inline void set_span(int index, ::google::protobuf::int32 value);
+  inline void add_span(::google::protobuf::int32 value);
+  inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+      span() const;
+  inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+      mutable_span();
+  
+  // @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo.Location)
+ private:
+  
+  ::google::protobuf::UnknownFieldSet _unknown_fields_;
+  
+  ::google::protobuf::RepeatedField< ::google::protobuf::int32 > path_;
+  mutable int _path_cached_byte_size_;
+  ::google::protobuf::RepeatedField< ::google::protobuf::int32 > span_;
+  mutable int _span_cached_byte_size_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
+  
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+  
+  void InitAsDefaultInstance();
+  static SourceCodeInfo_Location* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT SourceCodeInfo : public ::google::protobuf::Message {
+ public:
+  SourceCodeInfo();
+  virtual ~SourceCodeInfo();
+  
+  SourceCodeInfo(const SourceCodeInfo& from);
+  
+  inline SourceCodeInfo& operator=(const SourceCodeInfo& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _unknown_fields_;
+  }
+  
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+  
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const SourceCodeInfo& default_instance();
+  
+  void Swap(SourceCodeInfo* other);
+  
+  // implements Message ----------------------------------------------
+  
+  SourceCodeInfo* New() const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const SourceCodeInfo& from);
+  void MergeFrom(const SourceCodeInfo& from);
+  void Clear();
+  bool IsInitialized() const;
+  
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  
+  ::google::protobuf::Metadata GetMetadata() const;
+  
+  // nested types ----------------------------------------------------
+  
+  typedef SourceCodeInfo_Location Location;
+  
+  // accessors -------------------------------------------------------
+  
+  // repeated .google.protobuf.SourceCodeInfo.Location location = 1;
+  inline int location_size() const;
+  inline void clear_location();
+  static const int kLocationFieldNumber = 1;
+  inline const ::google::protobuf::SourceCodeInfo_Location& location(int index) const;
+  inline ::google::protobuf::SourceCodeInfo_Location* mutable_location(int index);
+  inline ::google::protobuf::SourceCodeInfo_Location* add_location();
+  inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >&
+      location() const;
+  inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >*
+      mutable_location();
+  
+  // @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo)
+ private:
+  
+  ::google::protobuf::UnknownFieldSet _unknown_fields_;
+  
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location > location_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
+  
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+  
+  void InitAsDefaultInstance();
+  static SourceCodeInfo* default_instance_;
+};
 // ===================================================================
 
 
@@ -2497,87 +2665,119 @@
 
 // optional string name = 1;
 inline bool FileDescriptorProto::has_name() const {
-  return _has_bit(0);
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void FileDescriptorProto::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void FileDescriptorProto::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
 }
 inline void FileDescriptorProto::clear_name() {
-  if (name_ != &_default_name_) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
     name_->clear();
   }
-  _clear_bit(0);
+  clear_has_name();
 }
 inline const ::std::string& FileDescriptorProto::name() const {
   return *name_;
 }
 inline void FileDescriptorProto::set_name(const ::std::string& value) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(value);
 }
 inline void FileDescriptorProto::set_name(const char* value) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(value);
 }
 inline void FileDescriptorProto::set_name(const char* value, size_t size) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* FileDescriptorProto::mutable_name() {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   return name_;
 }
+inline ::std::string* FileDescriptorProto::release_name() {
+  clear_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = name_;
+    name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // optional string package = 2;
 inline bool FileDescriptorProto::has_package() const {
-  return _has_bit(1);
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void FileDescriptorProto::set_has_package() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void FileDescriptorProto::clear_has_package() {
+  _has_bits_[0] &= ~0x00000002u;
 }
 inline void FileDescriptorProto::clear_package() {
-  if (package_ != &_default_package_) {
+  if (package_ != &::google::protobuf::internal::kEmptyString) {
     package_->clear();
   }
-  _clear_bit(1);
+  clear_has_package();
 }
 inline const ::std::string& FileDescriptorProto::package() const {
   return *package_;
 }
 inline void FileDescriptorProto::set_package(const ::std::string& value) {
-  _set_bit(1);
-  if (package_ == &_default_package_) {
+  set_has_package();
+  if (package_ == &::google::protobuf::internal::kEmptyString) {
     package_ = new ::std::string;
   }
   package_->assign(value);
 }
 inline void FileDescriptorProto::set_package(const char* value) {
-  _set_bit(1);
-  if (package_ == &_default_package_) {
+  set_has_package();
+  if (package_ == &::google::protobuf::internal::kEmptyString) {
     package_ = new ::std::string;
   }
   package_->assign(value);
 }
 inline void FileDescriptorProto::set_package(const char* value, size_t size) {
-  _set_bit(1);
-  if (package_ == &_default_package_) {
+  set_has_package();
+  if (package_ == &::google::protobuf::internal::kEmptyString) {
     package_ = new ::std::string;
   }
   package_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* FileDescriptorProto::mutable_package() {
-  _set_bit(1);
-  if (package_ == &_default_package_) {
+  set_has_package();
+  if (package_ == &::google::protobuf::internal::kEmptyString) {
     package_ = new ::std::string;
   }
   return package_;
 }
+inline ::std::string* FileDescriptorProto::release_package() {
+  clear_has_package();
+  if (package_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = package_;
+    package_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // repeated string dependency = 3;
 inline int FileDescriptorProto::dependency_size() const {
@@ -2725,20 +2925,61 @@
 
 // optional .google.protobuf.FileOptions options = 8;
 inline bool FileDescriptorProto::has_options() const {
-  return _has_bit(7);
+  return (_has_bits_[0] & 0x00000080u) != 0;
+}
+inline void FileDescriptorProto::set_has_options() {
+  _has_bits_[0] |= 0x00000080u;
+}
+inline void FileDescriptorProto::clear_has_options() {
+  _has_bits_[0] &= ~0x00000080u;
 }
 inline void FileDescriptorProto::clear_options() {
   if (options_ != NULL) options_->::google::protobuf::FileOptions::Clear();
-  _clear_bit(7);
+  clear_has_options();
 }
 inline const ::google::protobuf::FileOptions& FileDescriptorProto::options() const {
   return options_ != NULL ? *options_ : *default_instance_->options_;
 }
 inline ::google::protobuf::FileOptions* FileDescriptorProto::mutable_options() {
-  _set_bit(7);
+  set_has_options();
   if (options_ == NULL) options_ = new ::google::protobuf::FileOptions;
   return options_;
 }
+inline ::google::protobuf::FileOptions* FileDescriptorProto::release_options() {
+  clear_has_options();
+  ::google::protobuf::FileOptions* temp = options_;
+  options_ = NULL;
+  return temp;
+}
+
+// optional .google.protobuf.SourceCodeInfo source_code_info = 9;
+inline bool FileDescriptorProto::has_source_code_info() const {
+  return (_has_bits_[0] & 0x00000100u) != 0;
+}
+inline void FileDescriptorProto::set_has_source_code_info() {
+  _has_bits_[0] |= 0x00000100u;
+}
+inline void FileDescriptorProto::clear_has_source_code_info() {
+  _has_bits_[0] &= ~0x00000100u;
+}
+inline void FileDescriptorProto::clear_source_code_info() {
+  if (source_code_info_ != NULL) source_code_info_->::google::protobuf::SourceCodeInfo::Clear();
+  clear_has_source_code_info();
+}
+inline const ::google::protobuf::SourceCodeInfo& FileDescriptorProto::source_code_info() const {
+  return source_code_info_ != NULL ? *source_code_info_ : *default_instance_->source_code_info_;
+}
+inline ::google::protobuf::SourceCodeInfo* FileDescriptorProto::mutable_source_code_info() {
+  set_has_source_code_info();
+  if (source_code_info_ == NULL) source_code_info_ = new ::google::protobuf::SourceCodeInfo;
+  return source_code_info_;
+}
+inline ::google::protobuf::SourceCodeInfo* FileDescriptorProto::release_source_code_info() {
+  clear_has_source_code_info();
+  ::google::protobuf::SourceCodeInfo* temp = source_code_info_;
+  source_code_info_ = NULL;
+  return temp;
+}
 
 // -------------------------------------------------------------------
 
@@ -2746,33 +2987,45 @@
 
 // optional int32 start = 1;
 inline bool DescriptorProto_ExtensionRange::has_start() const {
-  return _has_bit(0);
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void DescriptorProto_ExtensionRange::set_has_start() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void DescriptorProto_ExtensionRange::clear_has_start() {
+  _has_bits_[0] &= ~0x00000001u;
 }
 inline void DescriptorProto_ExtensionRange::clear_start() {
   start_ = 0;
-  _clear_bit(0);
+  clear_has_start();
 }
 inline ::google::protobuf::int32 DescriptorProto_ExtensionRange::start() const {
   return start_;
 }
 inline void DescriptorProto_ExtensionRange::set_start(::google::protobuf::int32 value) {
-  _set_bit(0);
+  set_has_start();
   start_ = value;
 }
 
 // optional int32 end = 2;
 inline bool DescriptorProto_ExtensionRange::has_end() const {
-  return _has_bit(1);
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void DescriptorProto_ExtensionRange::set_has_end() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void DescriptorProto_ExtensionRange::clear_has_end() {
+  _has_bits_[0] &= ~0x00000002u;
 }
 inline void DescriptorProto_ExtensionRange::clear_end() {
   end_ = 0;
-  _clear_bit(1);
+  clear_has_end();
 }
 inline ::google::protobuf::int32 DescriptorProto_ExtensionRange::end() const {
   return end_;
 }
 inline void DescriptorProto_ExtensionRange::set_end(::google::protobuf::int32 value) {
-  _set_bit(1);
+  set_has_end();
   end_ = value;
 }
 
@@ -2782,45 +3035,61 @@
 
 // optional string name = 1;
 inline bool DescriptorProto::has_name() const {
-  return _has_bit(0);
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void DescriptorProto::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void DescriptorProto::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
 }
 inline void DescriptorProto::clear_name() {
-  if (name_ != &_default_name_) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
     name_->clear();
   }
-  _clear_bit(0);
+  clear_has_name();
 }
 inline const ::std::string& DescriptorProto::name() const {
   return *name_;
 }
 inline void DescriptorProto::set_name(const ::std::string& value) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(value);
 }
 inline void DescriptorProto::set_name(const char* value) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(value);
 }
 inline void DescriptorProto::set_name(const char* value, size_t size) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* DescriptorProto::mutable_name() {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   return name_;
 }
+inline ::std::string* DescriptorProto::release_name() {
+  clear_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = name_;
+    name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // repeated .google.protobuf.FieldDescriptorProto field = 2;
 inline int DescriptorProto::field_size() const {
@@ -2949,20 +3218,32 @@
 
 // optional .google.protobuf.MessageOptions options = 7;
 inline bool DescriptorProto::has_options() const {
-  return _has_bit(6);
+  return (_has_bits_[0] & 0x00000040u) != 0;
+}
+inline void DescriptorProto::set_has_options() {
+  _has_bits_[0] |= 0x00000040u;
+}
+inline void DescriptorProto::clear_has_options() {
+  _has_bits_[0] &= ~0x00000040u;
 }
 inline void DescriptorProto::clear_options() {
   if (options_ != NULL) options_->::google::protobuf::MessageOptions::Clear();
-  _clear_bit(6);
+  clear_has_options();
 }
 inline const ::google::protobuf::MessageOptions& DescriptorProto::options() const {
   return options_ != NULL ? *options_ : *default_instance_->options_;
 }
 inline ::google::protobuf::MessageOptions* DescriptorProto::mutable_options() {
-  _set_bit(6);
+  set_has_options();
   if (options_ == NULL) options_ = new ::google::protobuf::MessageOptions;
   return options_;
 }
+inline ::google::protobuf::MessageOptions* DescriptorProto::release_options() {
+  clear_has_options();
+  ::google::protobuf::MessageOptions* temp = options_;
+  options_ = NULL;
+  return temp;
+}
 
 // -------------------------------------------------------------------
 
@@ -2970,238 +3251,332 @@
 
 // optional string name = 1;
 inline bool FieldDescriptorProto::has_name() const {
-  return _has_bit(0);
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void FieldDescriptorProto::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void FieldDescriptorProto::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
 }
 inline void FieldDescriptorProto::clear_name() {
-  if (name_ != &_default_name_) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
     name_->clear();
   }
-  _clear_bit(0);
+  clear_has_name();
 }
 inline const ::std::string& FieldDescriptorProto::name() const {
   return *name_;
 }
 inline void FieldDescriptorProto::set_name(const ::std::string& value) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(value);
 }
 inline void FieldDescriptorProto::set_name(const char* value) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(value);
 }
 inline void FieldDescriptorProto::set_name(const char* value, size_t size) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* FieldDescriptorProto::mutable_name() {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   return name_;
 }
+inline ::std::string* FieldDescriptorProto::release_name() {
+  clear_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = name_;
+    name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // optional int32 number = 3;
 inline bool FieldDescriptorProto::has_number() const {
-  return _has_bit(1);
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void FieldDescriptorProto::set_has_number() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void FieldDescriptorProto::clear_has_number() {
+  _has_bits_[0] &= ~0x00000002u;
 }
 inline void FieldDescriptorProto::clear_number() {
   number_ = 0;
-  _clear_bit(1);
+  clear_has_number();
 }
 inline ::google::protobuf::int32 FieldDescriptorProto::number() const {
   return number_;
 }
 inline void FieldDescriptorProto::set_number(::google::protobuf::int32 value) {
-  _set_bit(1);
+  set_has_number();
   number_ = value;
 }
 
 // optional .google.protobuf.FieldDescriptorProto.Label label = 4;
 inline bool FieldDescriptorProto::has_label() const {
-  return _has_bit(2);
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void FieldDescriptorProto::set_has_label() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void FieldDescriptorProto::clear_has_label() {
+  _has_bits_[0] &= ~0x00000004u;
 }
 inline void FieldDescriptorProto::clear_label() {
   label_ = 1;
-  _clear_bit(2);
+  clear_has_label();
 }
 inline ::google::protobuf::FieldDescriptorProto_Label FieldDescriptorProto::label() const {
   return static_cast< ::google::protobuf::FieldDescriptorProto_Label >(label_);
 }
 inline void FieldDescriptorProto::set_label(::google::protobuf::FieldDescriptorProto_Label value) {
   GOOGLE_DCHECK(::google::protobuf::FieldDescriptorProto_Label_IsValid(value));
-  _set_bit(2);
+  set_has_label();
   label_ = value;
 }
 
 // optional .google.protobuf.FieldDescriptorProto.Type type = 5;
 inline bool FieldDescriptorProto::has_type() const {
-  return _has_bit(3);
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+inline void FieldDescriptorProto::set_has_type() {
+  _has_bits_[0] |= 0x00000008u;
+}
+inline void FieldDescriptorProto::clear_has_type() {
+  _has_bits_[0] &= ~0x00000008u;
 }
 inline void FieldDescriptorProto::clear_type() {
   type_ = 1;
-  _clear_bit(3);
+  clear_has_type();
 }
 inline ::google::protobuf::FieldDescriptorProto_Type FieldDescriptorProto::type() const {
   return static_cast< ::google::protobuf::FieldDescriptorProto_Type >(type_);
 }
 inline void FieldDescriptorProto::set_type(::google::protobuf::FieldDescriptorProto_Type value) {
   GOOGLE_DCHECK(::google::protobuf::FieldDescriptorProto_Type_IsValid(value));
-  _set_bit(3);
+  set_has_type();
   type_ = value;
 }
 
 // optional string type_name = 6;
 inline bool FieldDescriptorProto::has_type_name() const {
-  return _has_bit(4);
+  return (_has_bits_[0] & 0x00000010u) != 0;
+}
+inline void FieldDescriptorProto::set_has_type_name() {
+  _has_bits_[0] |= 0x00000010u;
+}
+inline void FieldDescriptorProto::clear_has_type_name() {
+  _has_bits_[0] &= ~0x00000010u;
 }
 inline void FieldDescriptorProto::clear_type_name() {
-  if (type_name_ != &_default_type_name_) {
+  if (type_name_ != &::google::protobuf::internal::kEmptyString) {
     type_name_->clear();
   }
-  _clear_bit(4);
+  clear_has_type_name();
 }
 inline const ::std::string& FieldDescriptorProto::type_name() const {
   return *type_name_;
 }
 inline void FieldDescriptorProto::set_type_name(const ::std::string& value) {
-  _set_bit(4);
-  if (type_name_ == &_default_type_name_) {
+  set_has_type_name();
+  if (type_name_ == &::google::protobuf::internal::kEmptyString) {
     type_name_ = new ::std::string;
   }
   type_name_->assign(value);
 }
 inline void FieldDescriptorProto::set_type_name(const char* value) {
-  _set_bit(4);
-  if (type_name_ == &_default_type_name_) {
+  set_has_type_name();
+  if (type_name_ == &::google::protobuf::internal::kEmptyString) {
     type_name_ = new ::std::string;
   }
   type_name_->assign(value);
 }
 inline void FieldDescriptorProto::set_type_name(const char* value, size_t size) {
-  _set_bit(4);
-  if (type_name_ == &_default_type_name_) {
+  set_has_type_name();
+  if (type_name_ == &::google::protobuf::internal::kEmptyString) {
     type_name_ = new ::std::string;
   }
   type_name_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* FieldDescriptorProto::mutable_type_name() {
-  _set_bit(4);
-  if (type_name_ == &_default_type_name_) {
+  set_has_type_name();
+  if (type_name_ == &::google::protobuf::internal::kEmptyString) {
     type_name_ = new ::std::string;
   }
   return type_name_;
 }
+inline ::std::string* FieldDescriptorProto::release_type_name() {
+  clear_has_type_name();
+  if (type_name_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = type_name_;
+    type_name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // optional string extendee = 2;
 inline bool FieldDescriptorProto::has_extendee() const {
-  return _has_bit(5);
+  return (_has_bits_[0] & 0x00000020u) != 0;
+}
+inline void FieldDescriptorProto::set_has_extendee() {
+  _has_bits_[0] |= 0x00000020u;
+}
+inline void FieldDescriptorProto::clear_has_extendee() {
+  _has_bits_[0] &= ~0x00000020u;
 }
 inline void FieldDescriptorProto::clear_extendee() {
-  if (extendee_ != &_default_extendee_) {
+  if (extendee_ != &::google::protobuf::internal::kEmptyString) {
     extendee_->clear();
   }
-  _clear_bit(5);
+  clear_has_extendee();
 }
 inline const ::std::string& FieldDescriptorProto::extendee() const {
   return *extendee_;
 }
 inline void FieldDescriptorProto::set_extendee(const ::std::string& value) {
-  _set_bit(5);
-  if (extendee_ == &_default_extendee_) {
+  set_has_extendee();
+  if (extendee_ == &::google::protobuf::internal::kEmptyString) {
     extendee_ = new ::std::string;
   }
   extendee_->assign(value);
 }
 inline void FieldDescriptorProto::set_extendee(const char* value) {
-  _set_bit(5);
-  if (extendee_ == &_default_extendee_) {
+  set_has_extendee();
+  if (extendee_ == &::google::protobuf::internal::kEmptyString) {
     extendee_ = new ::std::string;
   }
   extendee_->assign(value);
 }
 inline void FieldDescriptorProto::set_extendee(const char* value, size_t size) {
-  _set_bit(5);
-  if (extendee_ == &_default_extendee_) {
+  set_has_extendee();
+  if (extendee_ == &::google::protobuf::internal::kEmptyString) {
     extendee_ = new ::std::string;
   }
   extendee_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* FieldDescriptorProto::mutable_extendee() {
-  _set_bit(5);
-  if (extendee_ == &_default_extendee_) {
+  set_has_extendee();
+  if (extendee_ == &::google::protobuf::internal::kEmptyString) {
     extendee_ = new ::std::string;
   }
   return extendee_;
 }
+inline ::std::string* FieldDescriptorProto::release_extendee() {
+  clear_has_extendee();
+  if (extendee_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = extendee_;
+    extendee_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // optional string default_value = 7;
 inline bool FieldDescriptorProto::has_default_value() const {
-  return _has_bit(6);
+  return (_has_bits_[0] & 0x00000040u) != 0;
+}
+inline void FieldDescriptorProto::set_has_default_value() {
+  _has_bits_[0] |= 0x00000040u;
+}
+inline void FieldDescriptorProto::clear_has_default_value() {
+  _has_bits_[0] &= ~0x00000040u;
 }
 inline void FieldDescriptorProto::clear_default_value() {
-  if (default_value_ != &_default_default_value_) {
+  if (default_value_ != &::google::protobuf::internal::kEmptyString) {
     default_value_->clear();
   }
-  _clear_bit(6);
+  clear_has_default_value();
 }
 inline const ::std::string& FieldDescriptorProto::default_value() const {
   return *default_value_;
 }
 inline void FieldDescriptorProto::set_default_value(const ::std::string& value) {
-  _set_bit(6);
-  if (default_value_ == &_default_default_value_) {
+  set_has_default_value();
+  if (default_value_ == &::google::protobuf::internal::kEmptyString) {
     default_value_ = new ::std::string;
   }
   default_value_->assign(value);
 }
 inline void FieldDescriptorProto::set_default_value(const char* value) {
-  _set_bit(6);
-  if (default_value_ == &_default_default_value_) {
+  set_has_default_value();
+  if (default_value_ == &::google::protobuf::internal::kEmptyString) {
     default_value_ = new ::std::string;
   }
   default_value_->assign(value);
 }
 inline void FieldDescriptorProto::set_default_value(const char* value, size_t size) {
-  _set_bit(6);
-  if (default_value_ == &_default_default_value_) {
+  set_has_default_value();
+  if (default_value_ == &::google::protobuf::internal::kEmptyString) {
     default_value_ = new ::std::string;
   }
   default_value_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* FieldDescriptorProto::mutable_default_value() {
-  _set_bit(6);
-  if (default_value_ == &_default_default_value_) {
+  set_has_default_value();
+  if (default_value_ == &::google::protobuf::internal::kEmptyString) {
     default_value_ = new ::std::string;
   }
   return default_value_;
 }
+inline ::std::string* FieldDescriptorProto::release_default_value() {
+  clear_has_default_value();
+  if (default_value_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = default_value_;
+    default_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // optional .google.protobuf.FieldOptions options = 8;
 inline bool FieldDescriptorProto::has_options() const {
-  return _has_bit(7);
+  return (_has_bits_[0] & 0x00000080u) != 0;
+}
+inline void FieldDescriptorProto::set_has_options() {
+  _has_bits_[0] |= 0x00000080u;
+}
+inline void FieldDescriptorProto::clear_has_options() {
+  _has_bits_[0] &= ~0x00000080u;
 }
 inline void FieldDescriptorProto::clear_options() {
   if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear();
-  _clear_bit(7);
+  clear_has_options();
 }
 inline const ::google::protobuf::FieldOptions& FieldDescriptorProto::options() const {
   return options_ != NULL ? *options_ : *default_instance_->options_;
 }
 inline ::google::protobuf::FieldOptions* FieldDescriptorProto::mutable_options() {
-  _set_bit(7);
+  set_has_options();
   if (options_ == NULL) options_ = new ::google::protobuf::FieldOptions;
   return options_;
 }
+inline ::google::protobuf::FieldOptions* FieldDescriptorProto::release_options() {
+  clear_has_options();
+  ::google::protobuf::FieldOptions* temp = options_;
+  options_ = NULL;
+  return temp;
+}
 
 // -------------------------------------------------------------------
 
@@ -3209,45 +3584,61 @@
 
 // optional string name = 1;
 inline bool EnumDescriptorProto::has_name() const {
-  return _has_bit(0);
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void EnumDescriptorProto::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void EnumDescriptorProto::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
 }
 inline void EnumDescriptorProto::clear_name() {
-  if (name_ != &_default_name_) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
     name_->clear();
   }
-  _clear_bit(0);
+  clear_has_name();
 }
 inline const ::std::string& EnumDescriptorProto::name() const {
   return *name_;
 }
 inline void EnumDescriptorProto::set_name(const ::std::string& value) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(value);
 }
 inline void EnumDescriptorProto::set_name(const char* value) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(value);
 }
 inline void EnumDescriptorProto::set_name(const char* value, size_t size) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* EnumDescriptorProto::mutable_name() {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   return name_;
 }
+inline ::std::string* EnumDescriptorProto::release_name() {
+  clear_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = name_;
+    name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // repeated .google.protobuf.EnumValueDescriptorProto value = 2;
 inline int EnumDescriptorProto::value_size() const {
@@ -3276,20 +3667,32 @@
 
 // optional .google.protobuf.EnumOptions options = 3;
 inline bool EnumDescriptorProto::has_options() const {
-  return _has_bit(2);
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void EnumDescriptorProto::set_has_options() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void EnumDescriptorProto::clear_has_options() {
+  _has_bits_[0] &= ~0x00000004u;
 }
 inline void EnumDescriptorProto::clear_options() {
   if (options_ != NULL) options_->::google::protobuf::EnumOptions::Clear();
-  _clear_bit(2);
+  clear_has_options();
 }
 inline const ::google::protobuf::EnumOptions& EnumDescriptorProto::options() const {
   return options_ != NULL ? *options_ : *default_instance_->options_;
 }
 inline ::google::protobuf::EnumOptions* EnumDescriptorProto::mutable_options() {
-  _set_bit(2);
+  set_has_options();
   if (options_ == NULL) options_ = new ::google::protobuf::EnumOptions;
   return options_;
 }
+inline ::google::protobuf::EnumOptions* EnumDescriptorProto::release_options() {
+  clear_has_options();
+  ::google::protobuf::EnumOptions* temp = options_;
+  options_ = NULL;
+  return temp;
+}
 
 // -------------------------------------------------------------------
 
@@ -3297,78 +3700,112 @@
 
 // optional string name = 1;
 inline bool EnumValueDescriptorProto::has_name() const {
-  return _has_bit(0);
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void EnumValueDescriptorProto::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void EnumValueDescriptorProto::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
 }
 inline void EnumValueDescriptorProto::clear_name() {
-  if (name_ != &_default_name_) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
     name_->clear();
   }
-  _clear_bit(0);
+  clear_has_name();
 }
 inline const ::std::string& EnumValueDescriptorProto::name() const {
   return *name_;
 }
 inline void EnumValueDescriptorProto::set_name(const ::std::string& value) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(value);
 }
 inline void EnumValueDescriptorProto::set_name(const char* value) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(value);
 }
 inline void EnumValueDescriptorProto::set_name(const char* value, size_t size) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* EnumValueDescriptorProto::mutable_name() {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   return name_;
 }
+inline ::std::string* EnumValueDescriptorProto::release_name() {
+  clear_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = name_;
+    name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // optional int32 number = 2;
 inline bool EnumValueDescriptorProto::has_number() const {
-  return _has_bit(1);
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void EnumValueDescriptorProto::set_has_number() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void EnumValueDescriptorProto::clear_has_number() {
+  _has_bits_[0] &= ~0x00000002u;
 }
 inline void EnumValueDescriptorProto::clear_number() {
   number_ = 0;
-  _clear_bit(1);
+  clear_has_number();
 }
 inline ::google::protobuf::int32 EnumValueDescriptorProto::number() const {
   return number_;
 }
 inline void EnumValueDescriptorProto::set_number(::google::protobuf::int32 value) {
-  _set_bit(1);
+  set_has_number();
   number_ = value;
 }
 
 // optional .google.protobuf.EnumValueOptions options = 3;
 inline bool EnumValueDescriptorProto::has_options() const {
-  return _has_bit(2);
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void EnumValueDescriptorProto::set_has_options() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void EnumValueDescriptorProto::clear_has_options() {
+  _has_bits_[0] &= ~0x00000004u;
 }
 inline void EnumValueDescriptorProto::clear_options() {
   if (options_ != NULL) options_->::google::protobuf::EnumValueOptions::Clear();
-  _clear_bit(2);
+  clear_has_options();
 }
 inline const ::google::protobuf::EnumValueOptions& EnumValueDescriptorProto::options() const {
   return options_ != NULL ? *options_ : *default_instance_->options_;
 }
 inline ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::mutable_options() {
-  _set_bit(2);
+  set_has_options();
   if (options_ == NULL) options_ = new ::google::protobuf::EnumValueOptions;
   return options_;
 }
+inline ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::release_options() {
+  clear_has_options();
+  ::google::protobuf::EnumValueOptions* temp = options_;
+  options_ = NULL;
+  return temp;
+}
 
 // -------------------------------------------------------------------
 
@@ -3376,45 +3813,61 @@
 
 // optional string name = 1;
 inline bool ServiceDescriptorProto::has_name() const {
-  return _has_bit(0);
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void ServiceDescriptorProto::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void ServiceDescriptorProto::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
 }
 inline void ServiceDescriptorProto::clear_name() {
-  if (name_ != &_default_name_) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
     name_->clear();
   }
-  _clear_bit(0);
+  clear_has_name();
 }
 inline const ::std::string& ServiceDescriptorProto::name() const {
   return *name_;
 }
 inline void ServiceDescriptorProto::set_name(const ::std::string& value) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(value);
 }
 inline void ServiceDescriptorProto::set_name(const char* value) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(value);
 }
 inline void ServiceDescriptorProto::set_name(const char* value, size_t size) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* ServiceDescriptorProto::mutable_name() {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   return name_;
 }
+inline ::std::string* ServiceDescriptorProto::release_name() {
+  clear_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = name_;
+    name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // repeated .google.protobuf.MethodDescriptorProto method = 2;
 inline int ServiceDescriptorProto::method_size() const {
@@ -3443,20 +3896,32 @@
 
 // optional .google.protobuf.ServiceOptions options = 3;
 inline bool ServiceDescriptorProto::has_options() const {
-  return _has_bit(2);
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void ServiceDescriptorProto::set_has_options() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void ServiceDescriptorProto::clear_has_options() {
+  _has_bits_[0] &= ~0x00000004u;
 }
 inline void ServiceDescriptorProto::clear_options() {
   if (options_ != NULL) options_->::google::protobuf::ServiceOptions::Clear();
-  _clear_bit(2);
+  clear_has_options();
 }
 inline const ::google::protobuf::ServiceOptions& ServiceDescriptorProto::options() const {
   return options_ != NULL ? *options_ : *default_instance_->options_;
 }
 inline ::google::protobuf::ServiceOptions* ServiceDescriptorProto::mutable_options() {
-  _set_bit(2);
+  set_has_options();
   if (options_ == NULL) options_ = new ::google::protobuf::ServiceOptions;
   return options_;
 }
+inline ::google::protobuf::ServiceOptions* ServiceDescriptorProto::release_options() {
+  clear_has_options();
+  ::google::protobuf::ServiceOptions* temp = options_;
+  options_ = NULL;
+  return temp;
+}
 
 // -------------------------------------------------------------------
 
@@ -3464,146 +3929,206 @@
 
 // optional string name = 1;
 inline bool MethodDescriptorProto::has_name() const {
-  return _has_bit(0);
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void MethodDescriptorProto::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void MethodDescriptorProto::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
 }
 inline void MethodDescriptorProto::clear_name() {
-  if (name_ != &_default_name_) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
     name_->clear();
   }
-  _clear_bit(0);
+  clear_has_name();
 }
 inline const ::std::string& MethodDescriptorProto::name() const {
   return *name_;
 }
 inline void MethodDescriptorProto::set_name(const ::std::string& value) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(value);
 }
 inline void MethodDescriptorProto::set_name(const char* value) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(value);
 }
 inline void MethodDescriptorProto::set_name(const char* value, size_t size) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* MethodDescriptorProto::mutable_name() {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   return name_;
 }
+inline ::std::string* MethodDescriptorProto::release_name() {
+  clear_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = name_;
+    name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // optional string input_type = 2;
 inline bool MethodDescriptorProto::has_input_type() const {
-  return _has_bit(1);
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void MethodDescriptorProto::set_has_input_type() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void MethodDescriptorProto::clear_has_input_type() {
+  _has_bits_[0] &= ~0x00000002u;
 }
 inline void MethodDescriptorProto::clear_input_type() {
-  if (input_type_ != &_default_input_type_) {
+  if (input_type_ != &::google::protobuf::internal::kEmptyString) {
     input_type_->clear();
   }
-  _clear_bit(1);
+  clear_has_input_type();
 }
 inline const ::std::string& MethodDescriptorProto::input_type() const {
   return *input_type_;
 }
 inline void MethodDescriptorProto::set_input_type(const ::std::string& value) {
-  _set_bit(1);
-  if (input_type_ == &_default_input_type_) {
+  set_has_input_type();
+  if (input_type_ == &::google::protobuf::internal::kEmptyString) {
     input_type_ = new ::std::string;
   }
   input_type_->assign(value);
 }
 inline void MethodDescriptorProto::set_input_type(const char* value) {
-  _set_bit(1);
-  if (input_type_ == &_default_input_type_) {
+  set_has_input_type();
+  if (input_type_ == &::google::protobuf::internal::kEmptyString) {
     input_type_ = new ::std::string;
   }
   input_type_->assign(value);
 }
 inline void MethodDescriptorProto::set_input_type(const char* value, size_t size) {
-  _set_bit(1);
-  if (input_type_ == &_default_input_type_) {
+  set_has_input_type();
+  if (input_type_ == &::google::protobuf::internal::kEmptyString) {
     input_type_ = new ::std::string;
   }
   input_type_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* MethodDescriptorProto::mutable_input_type() {
-  _set_bit(1);
-  if (input_type_ == &_default_input_type_) {
+  set_has_input_type();
+  if (input_type_ == &::google::protobuf::internal::kEmptyString) {
     input_type_ = new ::std::string;
   }
   return input_type_;
 }
+inline ::std::string* MethodDescriptorProto::release_input_type() {
+  clear_has_input_type();
+  if (input_type_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = input_type_;
+    input_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // optional string output_type = 3;
 inline bool MethodDescriptorProto::has_output_type() const {
-  return _has_bit(2);
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void MethodDescriptorProto::set_has_output_type() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void MethodDescriptorProto::clear_has_output_type() {
+  _has_bits_[0] &= ~0x00000004u;
 }
 inline void MethodDescriptorProto::clear_output_type() {
-  if (output_type_ != &_default_output_type_) {
+  if (output_type_ != &::google::protobuf::internal::kEmptyString) {
     output_type_->clear();
   }
-  _clear_bit(2);
+  clear_has_output_type();
 }
 inline const ::std::string& MethodDescriptorProto::output_type() const {
   return *output_type_;
 }
 inline void MethodDescriptorProto::set_output_type(const ::std::string& value) {
-  _set_bit(2);
-  if (output_type_ == &_default_output_type_) {
+  set_has_output_type();
+  if (output_type_ == &::google::protobuf::internal::kEmptyString) {
     output_type_ = new ::std::string;
   }
   output_type_->assign(value);
 }
 inline void MethodDescriptorProto::set_output_type(const char* value) {
-  _set_bit(2);
-  if (output_type_ == &_default_output_type_) {
+  set_has_output_type();
+  if (output_type_ == &::google::protobuf::internal::kEmptyString) {
     output_type_ = new ::std::string;
   }
   output_type_->assign(value);
 }
 inline void MethodDescriptorProto::set_output_type(const char* value, size_t size) {
-  _set_bit(2);
-  if (output_type_ == &_default_output_type_) {
+  set_has_output_type();
+  if (output_type_ == &::google::protobuf::internal::kEmptyString) {
     output_type_ = new ::std::string;
   }
   output_type_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* MethodDescriptorProto::mutable_output_type() {
-  _set_bit(2);
-  if (output_type_ == &_default_output_type_) {
+  set_has_output_type();
+  if (output_type_ == &::google::protobuf::internal::kEmptyString) {
     output_type_ = new ::std::string;
   }
   return output_type_;
 }
+inline ::std::string* MethodDescriptorProto::release_output_type() {
+  clear_has_output_type();
+  if (output_type_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = output_type_;
+    output_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // optional .google.protobuf.MethodOptions options = 4;
 inline bool MethodDescriptorProto::has_options() const {
-  return _has_bit(3);
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+inline void MethodDescriptorProto::set_has_options() {
+  _has_bits_[0] |= 0x00000008u;
+}
+inline void MethodDescriptorProto::clear_has_options() {
+  _has_bits_[0] &= ~0x00000008u;
 }
 inline void MethodDescriptorProto::clear_options() {
   if (options_ != NULL) options_->::google::protobuf::MethodOptions::Clear();
-  _clear_bit(3);
+  clear_has_options();
 }
 inline const ::google::protobuf::MethodOptions& MethodDescriptorProto::options() const {
   return options_ != NULL ? *options_ : *default_instance_->options_;
 }
 inline ::google::protobuf::MethodOptions* MethodDescriptorProto::mutable_options() {
-  _set_bit(3);
+  set_has_options();
   if (options_ == NULL) options_ = new ::google::protobuf::MethodOptions;
   return options_;
 }
+inline ::google::protobuf::MethodOptions* MethodDescriptorProto::release_options() {
+  clear_has_options();
+  ::google::protobuf::MethodOptions* temp = options_;
+  options_ = NULL;
+  return temp;
+}
 
 // -------------------------------------------------------------------
 
@@ -3611,166 +4136,250 @@
 
 // optional string java_package = 1;
 inline bool FileOptions::has_java_package() const {
-  return _has_bit(0);
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void FileOptions::set_has_java_package() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void FileOptions::clear_has_java_package() {
+  _has_bits_[0] &= ~0x00000001u;
 }
 inline void FileOptions::clear_java_package() {
-  if (java_package_ != &_default_java_package_) {
+  if (java_package_ != &::google::protobuf::internal::kEmptyString) {
     java_package_->clear();
   }
-  _clear_bit(0);
+  clear_has_java_package();
 }
 inline const ::std::string& FileOptions::java_package() const {
   return *java_package_;
 }
 inline void FileOptions::set_java_package(const ::std::string& value) {
-  _set_bit(0);
-  if (java_package_ == &_default_java_package_) {
+  set_has_java_package();
+  if (java_package_ == &::google::protobuf::internal::kEmptyString) {
     java_package_ = new ::std::string;
   }
   java_package_->assign(value);
 }
 inline void FileOptions::set_java_package(const char* value) {
-  _set_bit(0);
-  if (java_package_ == &_default_java_package_) {
+  set_has_java_package();
+  if (java_package_ == &::google::protobuf::internal::kEmptyString) {
     java_package_ = new ::std::string;
   }
   java_package_->assign(value);
 }
 inline void FileOptions::set_java_package(const char* value, size_t size) {
-  _set_bit(0);
-  if (java_package_ == &_default_java_package_) {
+  set_has_java_package();
+  if (java_package_ == &::google::protobuf::internal::kEmptyString) {
     java_package_ = new ::std::string;
   }
   java_package_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* FileOptions::mutable_java_package() {
-  _set_bit(0);
-  if (java_package_ == &_default_java_package_) {
+  set_has_java_package();
+  if (java_package_ == &::google::protobuf::internal::kEmptyString) {
     java_package_ = new ::std::string;
   }
   return java_package_;
 }
+inline ::std::string* FileOptions::release_java_package() {
+  clear_has_java_package();
+  if (java_package_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = java_package_;
+    java_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // optional string java_outer_classname = 8;
 inline bool FileOptions::has_java_outer_classname() const {
-  return _has_bit(1);
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void FileOptions::set_has_java_outer_classname() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void FileOptions::clear_has_java_outer_classname() {
+  _has_bits_[0] &= ~0x00000002u;
 }
 inline void FileOptions::clear_java_outer_classname() {
-  if (java_outer_classname_ != &_default_java_outer_classname_) {
+  if (java_outer_classname_ != &::google::protobuf::internal::kEmptyString) {
     java_outer_classname_->clear();
   }
-  _clear_bit(1);
+  clear_has_java_outer_classname();
 }
 inline const ::std::string& FileOptions::java_outer_classname() const {
   return *java_outer_classname_;
 }
 inline void FileOptions::set_java_outer_classname(const ::std::string& value) {
-  _set_bit(1);
-  if (java_outer_classname_ == &_default_java_outer_classname_) {
+  set_has_java_outer_classname();
+  if (java_outer_classname_ == &::google::protobuf::internal::kEmptyString) {
     java_outer_classname_ = new ::std::string;
   }
   java_outer_classname_->assign(value);
 }
 inline void FileOptions::set_java_outer_classname(const char* value) {
-  _set_bit(1);
-  if (java_outer_classname_ == &_default_java_outer_classname_) {
+  set_has_java_outer_classname();
+  if (java_outer_classname_ == &::google::protobuf::internal::kEmptyString) {
     java_outer_classname_ = new ::std::string;
   }
   java_outer_classname_->assign(value);
 }
 inline void FileOptions::set_java_outer_classname(const char* value, size_t size) {
-  _set_bit(1);
-  if (java_outer_classname_ == &_default_java_outer_classname_) {
+  set_has_java_outer_classname();
+  if (java_outer_classname_ == &::google::protobuf::internal::kEmptyString) {
     java_outer_classname_ = new ::std::string;
   }
   java_outer_classname_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* FileOptions::mutable_java_outer_classname() {
-  _set_bit(1);
-  if (java_outer_classname_ == &_default_java_outer_classname_) {
+  set_has_java_outer_classname();
+  if (java_outer_classname_ == &::google::protobuf::internal::kEmptyString) {
     java_outer_classname_ = new ::std::string;
   }
   return java_outer_classname_;
 }
+inline ::std::string* FileOptions::release_java_outer_classname() {
+  clear_has_java_outer_classname();
+  if (java_outer_classname_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = java_outer_classname_;
+    java_outer_classname_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // optional bool java_multiple_files = 10 [default = false];
 inline bool FileOptions::has_java_multiple_files() const {
-  return _has_bit(2);
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void FileOptions::set_has_java_multiple_files() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void FileOptions::clear_has_java_multiple_files() {
+  _has_bits_[0] &= ~0x00000004u;
 }
 inline void FileOptions::clear_java_multiple_files() {
   java_multiple_files_ = false;
-  _clear_bit(2);
+  clear_has_java_multiple_files();
 }
 inline bool FileOptions::java_multiple_files() const {
   return java_multiple_files_;
 }
 inline void FileOptions::set_java_multiple_files(bool value) {
-  _set_bit(2);
+  set_has_java_multiple_files();
   java_multiple_files_ = value;
 }
 
+// optional bool java_generate_equals_and_hash = 20 [default = false];
+inline bool FileOptions::has_java_generate_equals_and_hash() const {
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+inline void FileOptions::set_has_java_generate_equals_and_hash() {
+  _has_bits_[0] |= 0x00000008u;
+}
+inline void FileOptions::clear_has_java_generate_equals_and_hash() {
+  _has_bits_[0] &= ~0x00000008u;
+}
+inline void FileOptions::clear_java_generate_equals_and_hash() {
+  java_generate_equals_and_hash_ = false;
+  clear_has_java_generate_equals_and_hash();
+}
+inline bool FileOptions::java_generate_equals_and_hash() const {
+  return java_generate_equals_and_hash_;
+}
+inline void FileOptions::set_java_generate_equals_and_hash(bool value) {
+  set_has_java_generate_equals_and_hash();
+  java_generate_equals_and_hash_ = value;
+}
+
 // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
 inline bool FileOptions::has_optimize_for() const {
-  return _has_bit(3);
+  return (_has_bits_[0] & 0x00000010u) != 0;
+}
+inline void FileOptions::set_has_optimize_for() {
+  _has_bits_[0] |= 0x00000010u;
+}
+inline void FileOptions::clear_has_optimize_for() {
+  _has_bits_[0] &= ~0x00000010u;
 }
 inline void FileOptions::clear_optimize_for() {
   optimize_for_ = 1;
-  _clear_bit(3);
+  clear_has_optimize_for();
 }
 inline ::google::protobuf::FileOptions_OptimizeMode FileOptions::optimize_for() const {
   return static_cast< ::google::protobuf::FileOptions_OptimizeMode >(optimize_for_);
 }
 inline void FileOptions::set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value) {
   GOOGLE_DCHECK(::google::protobuf::FileOptions_OptimizeMode_IsValid(value));
-  _set_bit(3);
+  set_has_optimize_for();
   optimize_for_ = value;
 }
 
-// optional bool cc_generic_services = 16 [default = true];
+// optional bool cc_generic_services = 16 [default = false];
 inline bool FileOptions::has_cc_generic_services() const {
-  return _has_bit(4);
+  return (_has_bits_[0] & 0x00000020u) != 0;
+}
+inline void FileOptions::set_has_cc_generic_services() {
+  _has_bits_[0] |= 0x00000020u;
+}
+inline void FileOptions::clear_has_cc_generic_services() {
+  _has_bits_[0] &= ~0x00000020u;
 }
 inline void FileOptions::clear_cc_generic_services() {
-  cc_generic_services_ = true;
-  _clear_bit(4);
+  cc_generic_services_ = false;
+  clear_has_cc_generic_services();
 }
 inline bool FileOptions::cc_generic_services() const {
   return cc_generic_services_;
 }
 inline void FileOptions::set_cc_generic_services(bool value) {
-  _set_bit(4);
+  set_has_cc_generic_services();
   cc_generic_services_ = value;
 }
 
-// optional bool java_generic_services = 17 [default = true];
+// optional bool java_generic_services = 17 [default = false];
 inline bool FileOptions::has_java_generic_services() const {
-  return _has_bit(5);
+  return (_has_bits_[0] & 0x00000040u) != 0;
+}
+inline void FileOptions::set_has_java_generic_services() {
+  _has_bits_[0] |= 0x00000040u;
+}
+inline void FileOptions::clear_has_java_generic_services() {
+  _has_bits_[0] &= ~0x00000040u;
 }
 inline void FileOptions::clear_java_generic_services() {
-  java_generic_services_ = true;
-  _clear_bit(5);
+  java_generic_services_ = false;
+  clear_has_java_generic_services();
 }
 inline bool FileOptions::java_generic_services() const {
   return java_generic_services_;
 }
 inline void FileOptions::set_java_generic_services(bool value) {
-  _set_bit(5);
+  set_has_java_generic_services();
   java_generic_services_ = value;
 }
 
-// optional bool py_generic_services = 18 [default = true];
+// optional bool py_generic_services = 18 [default = false];
 inline bool FileOptions::has_py_generic_services() const {
-  return _has_bit(6);
+  return (_has_bits_[0] & 0x00000080u) != 0;
+}
+inline void FileOptions::set_has_py_generic_services() {
+  _has_bits_[0] |= 0x00000080u;
+}
+inline void FileOptions::clear_has_py_generic_services() {
+  _has_bits_[0] &= ~0x00000080u;
 }
 inline void FileOptions::clear_py_generic_services() {
-  py_generic_services_ = true;
-  _clear_bit(6);
+  py_generic_services_ = false;
+  clear_has_py_generic_services();
 }
 inline bool FileOptions::py_generic_services() const {
   return py_generic_services_;
 }
 inline void FileOptions::set_py_generic_services(bool value) {
-  _set_bit(6);
+  set_has_py_generic_services();
   py_generic_services_ = value;
 }
 
@@ -3805,33 +4414,45 @@
 
 // optional bool message_set_wire_format = 1 [default = false];
 inline bool MessageOptions::has_message_set_wire_format() const {
-  return _has_bit(0);
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void MessageOptions::set_has_message_set_wire_format() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void MessageOptions::clear_has_message_set_wire_format() {
+  _has_bits_[0] &= ~0x00000001u;
 }
 inline void MessageOptions::clear_message_set_wire_format() {
   message_set_wire_format_ = false;
-  _clear_bit(0);
+  clear_has_message_set_wire_format();
 }
 inline bool MessageOptions::message_set_wire_format() const {
   return message_set_wire_format_;
 }
 inline void MessageOptions::set_message_set_wire_format(bool value) {
-  _set_bit(0);
+  set_has_message_set_wire_format();
   message_set_wire_format_ = value;
 }
 
 // optional bool no_standard_descriptor_accessor = 2 [default = false];
 inline bool MessageOptions::has_no_standard_descriptor_accessor() const {
-  return _has_bit(1);
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void MessageOptions::set_has_no_standard_descriptor_accessor() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void MessageOptions::clear_has_no_standard_descriptor_accessor() {
+  _has_bits_[0] &= ~0x00000002u;
 }
 inline void MessageOptions::clear_no_standard_descriptor_accessor() {
   no_standard_descriptor_accessor_ = false;
-  _clear_bit(1);
+  clear_has_no_standard_descriptor_accessor();
 }
 inline bool MessageOptions::no_standard_descriptor_accessor() const {
   return no_standard_descriptor_accessor_;
 }
 inline void MessageOptions::set_no_standard_descriptor_accessor(bool value) {
-  _set_bit(1);
+  set_has_no_standard_descriptor_accessor();
   no_standard_descriptor_accessor_ = value;
 }
 
@@ -3866,94 +4487,128 @@
 
 // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
 inline bool FieldOptions::has_ctype() const {
-  return _has_bit(0);
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void FieldOptions::set_has_ctype() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void FieldOptions::clear_has_ctype() {
+  _has_bits_[0] &= ~0x00000001u;
 }
 inline void FieldOptions::clear_ctype() {
   ctype_ = 0;
-  _clear_bit(0);
+  clear_has_ctype();
 }
 inline ::google::protobuf::FieldOptions_CType FieldOptions::ctype() const {
   return static_cast< ::google::protobuf::FieldOptions_CType >(ctype_);
 }
 inline void FieldOptions::set_ctype(::google::protobuf::FieldOptions_CType value) {
   GOOGLE_DCHECK(::google::protobuf::FieldOptions_CType_IsValid(value));
-  _set_bit(0);
+  set_has_ctype();
   ctype_ = value;
 }
 
 // optional bool packed = 2;
 inline bool FieldOptions::has_packed() const {
-  return _has_bit(1);
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void FieldOptions::set_has_packed() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void FieldOptions::clear_has_packed() {
+  _has_bits_[0] &= ~0x00000002u;
 }
 inline void FieldOptions::clear_packed() {
   packed_ = false;
-  _clear_bit(1);
+  clear_has_packed();
 }
 inline bool FieldOptions::packed() const {
   return packed_;
 }
 inline void FieldOptions::set_packed(bool value) {
-  _set_bit(1);
+  set_has_packed();
   packed_ = value;
 }
 
 // optional bool deprecated = 3 [default = false];
 inline bool FieldOptions::has_deprecated() const {
-  return _has_bit(2);
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void FieldOptions::set_has_deprecated() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void FieldOptions::clear_has_deprecated() {
+  _has_bits_[0] &= ~0x00000004u;
 }
 inline void FieldOptions::clear_deprecated() {
   deprecated_ = false;
-  _clear_bit(2);
+  clear_has_deprecated();
 }
 inline bool FieldOptions::deprecated() const {
   return deprecated_;
 }
 inline void FieldOptions::set_deprecated(bool value) {
-  _set_bit(2);
+  set_has_deprecated();
   deprecated_ = value;
 }
 
 // optional string experimental_map_key = 9;
 inline bool FieldOptions::has_experimental_map_key() const {
-  return _has_bit(3);
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+inline void FieldOptions::set_has_experimental_map_key() {
+  _has_bits_[0] |= 0x00000008u;
+}
+inline void FieldOptions::clear_has_experimental_map_key() {
+  _has_bits_[0] &= ~0x00000008u;
 }
 inline void FieldOptions::clear_experimental_map_key() {
-  if (experimental_map_key_ != &_default_experimental_map_key_) {
+  if (experimental_map_key_ != &::google::protobuf::internal::kEmptyString) {
     experimental_map_key_->clear();
   }
-  _clear_bit(3);
+  clear_has_experimental_map_key();
 }
 inline const ::std::string& FieldOptions::experimental_map_key() const {
   return *experimental_map_key_;
 }
 inline void FieldOptions::set_experimental_map_key(const ::std::string& value) {
-  _set_bit(3);
-  if (experimental_map_key_ == &_default_experimental_map_key_) {
+  set_has_experimental_map_key();
+  if (experimental_map_key_ == &::google::protobuf::internal::kEmptyString) {
     experimental_map_key_ = new ::std::string;
   }
   experimental_map_key_->assign(value);
 }
 inline void FieldOptions::set_experimental_map_key(const char* value) {
-  _set_bit(3);
-  if (experimental_map_key_ == &_default_experimental_map_key_) {
+  set_has_experimental_map_key();
+  if (experimental_map_key_ == &::google::protobuf::internal::kEmptyString) {
     experimental_map_key_ = new ::std::string;
   }
   experimental_map_key_->assign(value);
 }
 inline void FieldOptions::set_experimental_map_key(const char* value, size_t size) {
-  _set_bit(3);
-  if (experimental_map_key_ == &_default_experimental_map_key_) {
+  set_has_experimental_map_key();
+  if (experimental_map_key_ == &::google::protobuf::internal::kEmptyString) {
     experimental_map_key_ = new ::std::string;
   }
   experimental_map_key_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* FieldOptions::mutable_experimental_map_key() {
-  _set_bit(3);
-  if (experimental_map_key_ == &_default_experimental_map_key_) {
+  set_has_experimental_map_key();
+  if (experimental_map_key_ == &::google::protobuf::internal::kEmptyString) {
     experimental_map_key_ = new ::std::string;
   }
   return experimental_map_key_;
 }
+inline ::std::string* FieldOptions::release_experimental_map_key() {
+  clear_has_experimental_map_key();
+  if (experimental_map_key_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = experimental_map_key_;
+    experimental_map_key_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
 inline int FieldOptions::uninterpreted_option_size() const {
@@ -4102,59 +4757,81 @@
 
 // required string name_part = 1;
 inline bool UninterpretedOption_NamePart::has_name_part() const {
-  return _has_bit(0);
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void UninterpretedOption_NamePart::set_has_name_part() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void UninterpretedOption_NamePart::clear_has_name_part() {
+  _has_bits_[0] &= ~0x00000001u;
 }
 inline void UninterpretedOption_NamePart::clear_name_part() {
-  if (name_part_ != &_default_name_part_) {
+  if (name_part_ != &::google::protobuf::internal::kEmptyString) {
     name_part_->clear();
   }
-  _clear_bit(0);
+  clear_has_name_part();
 }
 inline const ::std::string& UninterpretedOption_NamePart::name_part() const {
   return *name_part_;
 }
 inline void UninterpretedOption_NamePart::set_name_part(const ::std::string& value) {
-  _set_bit(0);
-  if (name_part_ == &_default_name_part_) {
+  set_has_name_part();
+  if (name_part_ == &::google::protobuf::internal::kEmptyString) {
     name_part_ = new ::std::string;
   }
   name_part_->assign(value);
 }
 inline void UninterpretedOption_NamePart::set_name_part(const char* value) {
-  _set_bit(0);
-  if (name_part_ == &_default_name_part_) {
+  set_has_name_part();
+  if (name_part_ == &::google::protobuf::internal::kEmptyString) {
     name_part_ = new ::std::string;
   }
   name_part_->assign(value);
 }
 inline void UninterpretedOption_NamePart::set_name_part(const char* value, size_t size) {
-  _set_bit(0);
-  if (name_part_ == &_default_name_part_) {
+  set_has_name_part();
+  if (name_part_ == &::google::protobuf::internal::kEmptyString) {
     name_part_ = new ::std::string;
   }
   name_part_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* UninterpretedOption_NamePart::mutable_name_part() {
-  _set_bit(0);
-  if (name_part_ == &_default_name_part_) {
+  set_has_name_part();
+  if (name_part_ == &::google::protobuf::internal::kEmptyString) {
     name_part_ = new ::std::string;
   }
   return name_part_;
 }
+inline ::std::string* UninterpretedOption_NamePart::release_name_part() {
+  clear_has_name_part();
+  if (name_part_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = name_part_;
+    name_part_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // required bool is_extension = 2;
 inline bool UninterpretedOption_NamePart::has_is_extension() const {
-  return _has_bit(1);
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void UninterpretedOption_NamePart::set_has_is_extension() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void UninterpretedOption_NamePart::clear_has_is_extension() {
+  _has_bits_[0] &= ~0x00000002u;
 }
 inline void UninterpretedOption_NamePart::clear_is_extension() {
   is_extension_ = false;
-  _clear_bit(1);
+  clear_has_is_extension();
 }
 inline bool UninterpretedOption_NamePart::is_extension() const {
   return is_extension_;
 }
 inline void UninterpretedOption_NamePart::set_is_extension(bool value) {
-  _set_bit(1);
+  set_has_is_extension();
   is_extension_ = value;
 }
 
@@ -4189,135 +4866,326 @@
 
 // optional string identifier_value = 3;
 inline bool UninterpretedOption::has_identifier_value() const {
-  return _has_bit(1);
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void UninterpretedOption::set_has_identifier_value() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void UninterpretedOption::clear_has_identifier_value() {
+  _has_bits_[0] &= ~0x00000002u;
 }
 inline void UninterpretedOption::clear_identifier_value() {
-  if (identifier_value_ != &_default_identifier_value_) {
+  if (identifier_value_ != &::google::protobuf::internal::kEmptyString) {
     identifier_value_->clear();
   }
-  _clear_bit(1);
+  clear_has_identifier_value();
 }
 inline const ::std::string& UninterpretedOption::identifier_value() const {
   return *identifier_value_;
 }
 inline void UninterpretedOption::set_identifier_value(const ::std::string& value) {
-  _set_bit(1);
-  if (identifier_value_ == &_default_identifier_value_) {
+  set_has_identifier_value();
+  if (identifier_value_ == &::google::protobuf::internal::kEmptyString) {
     identifier_value_ = new ::std::string;
   }
   identifier_value_->assign(value);
 }
 inline void UninterpretedOption::set_identifier_value(const char* value) {
-  _set_bit(1);
-  if (identifier_value_ == &_default_identifier_value_) {
+  set_has_identifier_value();
+  if (identifier_value_ == &::google::protobuf::internal::kEmptyString) {
     identifier_value_ = new ::std::string;
   }
   identifier_value_->assign(value);
 }
 inline void UninterpretedOption::set_identifier_value(const char* value, size_t size) {
-  _set_bit(1);
-  if (identifier_value_ == &_default_identifier_value_) {
+  set_has_identifier_value();
+  if (identifier_value_ == &::google::protobuf::internal::kEmptyString) {
     identifier_value_ = new ::std::string;
   }
   identifier_value_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* UninterpretedOption::mutable_identifier_value() {
-  _set_bit(1);
-  if (identifier_value_ == &_default_identifier_value_) {
+  set_has_identifier_value();
+  if (identifier_value_ == &::google::protobuf::internal::kEmptyString) {
     identifier_value_ = new ::std::string;
   }
   return identifier_value_;
 }
+inline ::std::string* UninterpretedOption::release_identifier_value() {
+  clear_has_identifier_value();
+  if (identifier_value_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = identifier_value_;
+    identifier_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // optional uint64 positive_int_value = 4;
 inline bool UninterpretedOption::has_positive_int_value() const {
-  return _has_bit(2);
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void UninterpretedOption::set_has_positive_int_value() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void UninterpretedOption::clear_has_positive_int_value() {
+  _has_bits_[0] &= ~0x00000004u;
 }
 inline void UninterpretedOption::clear_positive_int_value() {
   positive_int_value_ = GOOGLE_ULONGLONG(0);
-  _clear_bit(2);
+  clear_has_positive_int_value();
 }
 inline ::google::protobuf::uint64 UninterpretedOption::positive_int_value() const {
   return positive_int_value_;
 }
 inline void UninterpretedOption::set_positive_int_value(::google::protobuf::uint64 value) {
-  _set_bit(2);
+  set_has_positive_int_value();
   positive_int_value_ = value;
 }
 
 // optional int64 negative_int_value = 5;
 inline bool UninterpretedOption::has_negative_int_value() const {
-  return _has_bit(3);
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+inline void UninterpretedOption::set_has_negative_int_value() {
+  _has_bits_[0] |= 0x00000008u;
+}
+inline void UninterpretedOption::clear_has_negative_int_value() {
+  _has_bits_[0] &= ~0x00000008u;
 }
 inline void UninterpretedOption::clear_negative_int_value() {
   negative_int_value_ = GOOGLE_LONGLONG(0);
-  _clear_bit(3);
+  clear_has_negative_int_value();
 }
 inline ::google::protobuf::int64 UninterpretedOption::negative_int_value() const {
   return negative_int_value_;
 }
 inline void UninterpretedOption::set_negative_int_value(::google::protobuf::int64 value) {
-  _set_bit(3);
+  set_has_negative_int_value();
   negative_int_value_ = value;
 }
 
 // optional double double_value = 6;
 inline bool UninterpretedOption::has_double_value() const {
-  return _has_bit(4);
+  return (_has_bits_[0] & 0x00000010u) != 0;
+}
+inline void UninterpretedOption::set_has_double_value() {
+  _has_bits_[0] |= 0x00000010u;
+}
+inline void UninterpretedOption::clear_has_double_value() {
+  _has_bits_[0] &= ~0x00000010u;
 }
 inline void UninterpretedOption::clear_double_value() {
   double_value_ = 0;
-  _clear_bit(4);
+  clear_has_double_value();
 }
 inline double UninterpretedOption::double_value() const {
   return double_value_;
 }
 inline void UninterpretedOption::set_double_value(double value) {
-  _set_bit(4);
+  set_has_double_value();
   double_value_ = value;
 }
 
 // optional bytes string_value = 7;
 inline bool UninterpretedOption::has_string_value() const {
-  return _has_bit(5);
+  return (_has_bits_[0] & 0x00000020u) != 0;
+}
+inline void UninterpretedOption::set_has_string_value() {
+  _has_bits_[0] |= 0x00000020u;
+}
+inline void UninterpretedOption::clear_has_string_value() {
+  _has_bits_[0] &= ~0x00000020u;
 }
 inline void UninterpretedOption::clear_string_value() {
-  if (string_value_ != &_default_string_value_) {
+  if (string_value_ != &::google::protobuf::internal::kEmptyString) {
     string_value_->clear();
   }
-  _clear_bit(5);
+  clear_has_string_value();
 }
 inline const ::std::string& UninterpretedOption::string_value() const {
   return *string_value_;
 }
 inline void UninterpretedOption::set_string_value(const ::std::string& value) {
-  _set_bit(5);
-  if (string_value_ == &_default_string_value_) {
+  set_has_string_value();
+  if (string_value_ == &::google::protobuf::internal::kEmptyString) {
     string_value_ = new ::std::string;
   }
   string_value_->assign(value);
 }
 inline void UninterpretedOption::set_string_value(const char* value) {
-  _set_bit(5);
-  if (string_value_ == &_default_string_value_) {
+  set_has_string_value();
+  if (string_value_ == &::google::protobuf::internal::kEmptyString) {
     string_value_ = new ::std::string;
   }
   string_value_->assign(value);
 }
 inline void UninterpretedOption::set_string_value(const void* value, size_t size) {
-  _set_bit(5);
-  if (string_value_ == &_default_string_value_) {
+  set_has_string_value();
+  if (string_value_ == &::google::protobuf::internal::kEmptyString) {
     string_value_ = new ::std::string;
   }
   string_value_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* UninterpretedOption::mutable_string_value() {
-  _set_bit(5);
-  if (string_value_ == &_default_string_value_) {
+  set_has_string_value();
+  if (string_value_ == &::google::protobuf::internal::kEmptyString) {
     string_value_ = new ::std::string;
   }
   return string_value_;
 }
+inline ::std::string* UninterpretedOption::release_string_value() {
+  clear_has_string_value();
+  if (string_value_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = string_value_;
+    string_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
+
+// optional string aggregate_value = 8;
+inline bool UninterpretedOption::has_aggregate_value() const {
+  return (_has_bits_[0] & 0x00000040u) != 0;
+}
+inline void UninterpretedOption::set_has_aggregate_value() {
+  _has_bits_[0] |= 0x00000040u;
+}
+inline void UninterpretedOption::clear_has_aggregate_value() {
+  _has_bits_[0] &= ~0x00000040u;
+}
+inline void UninterpretedOption::clear_aggregate_value() {
+  if (aggregate_value_ != &::google::protobuf::internal::kEmptyString) {
+    aggregate_value_->clear();
+  }
+  clear_has_aggregate_value();
+}
+inline const ::std::string& UninterpretedOption::aggregate_value() const {
+  return *aggregate_value_;
+}
+inline void UninterpretedOption::set_aggregate_value(const ::std::string& value) {
+  set_has_aggregate_value();
+  if (aggregate_value_ == &::google::protobuf::internal::kEmptyString) {
+    aggregate_value_ = new ::std::string;
+  }
+  aggregate_value_->assign(value);
+}
+inline void UninterpretedOption::set_aggregate_value(const char* value) {
+  set_has_aggregate_value();
+  if (aggregate_value_ == &::google::protobuf::internal::kEmptyString) {
+    aggregate_value_ = new ::std::string;
+  }
+  aggregate_value_->assign(value);
+}
+inline void UninterpretedOption::set_aggregate_value(const char* value, size_t size) {
+  set_has_aggregate_value();
+  if (aggregate_value_ == &::google::protobuf::internal::kEmptyString) {
+    aggregate_value_ = new ::std::string;
+  }
+  aggregate_value_->assign(reinterpret_cast<const char*>(value), size);
+}
+inline ::std::string* UninterpretedOption::mutable_aggregate_value() {
+  set_has_aggregate_value();
+  if (aggregate_value_ == &::google::protobuf::internal::kEmptyString) {
+    aggregate_value_ = new ::std::string;
+  }
+  return aggregate_value_;
+}
+inline ::std::string* UninterpretedOption::release_aggregate_value() {
+  clear_has_aggregate_value();
+  if (aggregate_value_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = aggregate_value_;
+    aggregate_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
+
+// -------------------------------------------------------------------
+
+// SourceCodeInfo_Location
+
+// repeated int32 path = 1 [packed = true];
+inline int SourceCodeInfo_Location::path_size() const {
+  return path_.size();
+}
+inline void SourceCodeInfo_Location::clear_path() {
+  path_.Clear();
+}
+inline ::google::protobuf::int32 SourceCodeInfo_Location::path(int index) const {
+  return path_.Get(index);
+}
+inline void SourceCodeInfo_Location::set_path(int index, ::google::protobuf::int32 value) {
+  path_.Set(index, value);
+}
+inline void SourceCodeInfo_Location::add_path(::google::protobuf::int32 value) {
+  path_.Add(value);
+}
+inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+SourceCodeInfo_Location::path() const {
+  return path_;
+}
+inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+SourceCodeInfo_Location::mutable_path() {
+  return &path_;
+}
+
+// repeated int32 span = 2 [packed = true];
+inline int SourceCodeInfo_Location::span_size() const {
+  return span_.size();
+}
+inline void SourceCodeInfo_Location::clear_span() {
+  span_.Clear();
+}
+inline ::google::protobuf::int32 SourceCodeInfo_Location::span(int index) const {
+  return span_.Get(index);
+}
+inline void SourceCodeInfo_Location::set_span(int index, ::google::protobuf::int32 value) {
+  span_.Set(index, value);
+}
+inline void SourceCodeInfo_Location::add_span(::google::protobuf::int32 value) {
+  span_.Add(value);
+}
+inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+SourceCodeInfo_Location::span() const {
+  return span_;
+}
+inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+SourceCodeInfo_Location::mutable_span() {
+  return &span_;
+}
+
+// -------------------------------------------------------------------
+
+// SourceCodeInfo
+
+// repeated .google.protobuf.SourceCodeInfo.Location location = 1;
+inline int SourceCodeInfo::location_size() const {
+  return location_.size();
+}
+inline void SourceCodeInfo::clear_location() {
+  location_.Clear();
+}
+inline const ::google::protobuf::SourceCodeInfo_Location& SourceCodeInfo::location(int index) const {
+  return location_.Get(index);
+}
+inline ::google::protobuf::SourceCodeInfo_Location* SourceCodeInfo::mutable_location(int index) {
+  return location_.Mutable(index);
+}
+inline ::google::protobuf::SourceCodeInfo_Location* SourceCodeInfo::add_location() {
+  return location_.Add();
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >&
+SourceCodeInfo::location() const {
+  return location_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >*
+SourceCodeInfo::mutable_location() {
+  return &location_;
+}
 
 
 // @@protoc_insertion_point(namespace_scope)
diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto
index cc04aa8..233f879 100644
--- a/src/google/protobuf/descriptor.proto
+++ b/src/google/protobuf/descriptor.proto
@@ -67,6 +67,12 @@
   repeated FieldDescriptorProto extension = 7;
 
   optional FileOptions options = 8;
+
+  // This field contains optional information about the original source code.
+  // You may safely remove this entire field whithout harming runtime
+  // functionality of the descriptors -- the information is needed only by
+  // development tools.
+  optional SourceCodeInfo source_code_info = 9;
 }
 
 // Describes a message type.
@@ -245,6 +251,12 @@
   // top-level extensions defined in the file.
   optional bool java_multiple_files = 10 [default=false];
 
+  // If set true, then the Java code generator will generate equals() and
+  // hashCode() methods for all messages defined in the .proto file. This is
+  // purely a speed optimization, as the AbstractMessage base class includes
+  // reflection-based implementations of these methods.
+  optional bool java_generate_equals_and_hash = 20 [default=false];
+
   // Generated classes can be optimized for speed or code size.
   enum OptimizeMode {
     SPEED = 1;        // Generate complete code for parsing, serialization,
@@ -264,13 +276,12 @@
   // early versions of proto2.
   //
   // Generic services are now considered deprecated in favor of using plugins
-  // that generate code specific to your particular RPC system.  If you are
-  // using such a plugin, set these to false.  In the future, we may change
-  // the default to false, so if you explicitly want generic services, you
-  // should explicitly set these to true.
-  optional bool cc_generic_services = 16 [default=true];
-  optional bool java_generic_services = 17 [default=true];
-  optional bool py_generic_services = 18 [default=true];
+  // that generate code specific to your particular RPC system.  Therefore,
+  // these default to false.  Old code which depends on generic services should
+  // explicitly set them to true.
+  optional bool cc_generic_services = 16 [default=false];
+  optional bool java_generic_services = 17 [default=false];
+  optional bool py_generic_services = 18 [default=false];
 
   // The parser stores options it doesn't recognize here. See above.
   repeated UninterpretedOption uninterpreted_option = 999;
@@ -430,4 +441,93 @@
   optional int64 negative_int_value = 5;
   optional double double_value = 6;
   optional bytes string_value = 7;
+  optional string aggregate_value = 8;
+}
+
+// ===================================================================
+// Optional source code info
+
+// Encapsulates information about the original source file from which a
+// FileDescriptorProto was generated.
+message SourceCodeInfo {
+  // A Location identifies a piece of source code in a .proto file which
+  // corresponds to a particular definition.  This information is intended
+  // to be useful to IDEs, code indexers, documentation generators, and similar
+  // tools.
+  //
+  // For example, say we have a file like:
+  //   message Foo {
+  //     optional string foo = 1;
+  //   }
+  // Let's look at just the field definition:
+  //   optional string foo = 1;
+  //   ^       ^^     ^^  ^  ^^^
+  //   a       bc     de  f  ghi
+  // We have the following locations:
+  //   span   path               represents
+  //   [a,i)  [ 4, 0, 2, 0 ]     The whole field definition.
+  //   [a,b)  [ 4, 0, 2, 0, 4 ]  The label (optional).
+  //   [c,d)  [ 4, 0, 2, 0, 5 ]  The type (string).
+  //   [e,f)  [ 4, 0, 2, 0, 1 ]  The name (foo).
+  //   [g,h)  [ 4, 0, 2, 0, 3 ]  The number (1).
+  //
+  // Notes:
+  // - A location may refer to a repeated field itself (i.e. not to any
+  //   particular index within it).  This is used whenever a set of elements are
+  //   logically enclosed in a single code segment.  For example, an entire
+  //   extend block (possibly containing multiple extension definitions) will
+  //   have an outer location whose path refers to the "extensions" repeated
+  //   field without an index.
+  // - Multiple locations may have the same path.  This happens when a single
+  //   logical declaration is spread out across multiple places.  The most
+  //   obvious example is the "extend" block again -- there may be multiple
+  //   extend blocks in the same scope, each of which will have the same path.
+  // - A location's span is not always a subset of its parent's span.  For
+  //   example, the "extendee" of an extension declaration appears at the
+  //   beginning of the "extend" block and is shared by all extensions within
+  //   the block.
+  // - Just because a location's span is a subset of some other location's span
+  //   does not mean that it is a descendent.  For example, a "group" defines
+  //   both a type and a field in a single declaration.  Thus, the locations
+  //   corresponding to the type and field and their components will overlap.
+  // - Code which tries to interpret locations should probably be designed to
+  //   ignore those that it doesn't understand, as more types of locations could
+  //   be recorded in the future.
+  repeated Location location = 1;
+  message Location {
+    // Identifies which part of the FileDescriptorProto was defined at this
+    // location.
+    //
+    // Each element is a field number or an index.  They form a path from
+    // the root FileDescriptorProto to the place where the definition.  For
+    // example, this path:
+    //   [ 4, 3, 2, 7, 1 ]
+    // refers to:
+    //   file.message_type(3)  // 4, 3
+    //       .field(7)         // 2, 7
+    //       .name()           // 1
+    // This is because FileDescriptorProto.message_type has field number 4:
+    //   repeated DescriptorProto message_type = 4;
+    // and DescriptorProto.field has field number 2:
+    //   repeated FieldDescriptorProto field = 2;
+    // and FieldDescriptorProto.name has field number 1:
+    //   optional string name = 1;
+    //
+    // Thus, the above path gives the location of a field name.  If we removed
+    // the last element:
+    //   [ 4, 3, 2, 7 ]
+    // this path refers to the whole field declaration (from the beginning
+    // of the label to the terminating semicolon).
+    repeated int32 path = 1 [packed=true];
+
+    // Always has exactly three or four elements: start line, start column,
+    // end line (optional, otherwise assumed same as start line), end column.
+    // These are packed into a single field for efficiency.  Note that line
+    // and column numbers are zero-based -- typically you will want to add
+    // 1 to each before displaying to a user.
+    repeated int32 span = 2 [packed=true];
+
+    // TODO(kenton):  Record comments appearing before and after the
+    // declaration.
+  }
 }
diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc
index d70c9bf..55aebfd 100644
--- a/src/google/protobuf/descriptor_unittest.cc
+++ b/src/google/protobuf/descriptor_unittest.cc
@@ -2212,6 +2212,45 @@
   EXPECT_EQ(1234, options.GetExtension(protobuf_unittest::complex_opt1).foo());
 }
 
+// Check that aggregate options were parsed and saved correctly in
+// the appropriate descriptors.
+TEST(CustomOptions, AggregateOptions) {
+  const Descriptor* msg = protobuf_unittest::AggregateMessage::descriptor();
+  const FileDescriptor* file = msg->file();
+  const FieldDescriptor* field = msg->FindFieldByName("fieldname");
+  const EnumDescriptor* enumd = file->FindEnumTypeByName("AggregateEnum");
+  const EnumValueDescriptor* enumv = enumd->FindValueByName("VALUE");
+  const ServiceDescriptor* service = file->FindServiceByName(
+      "AggregateService");
+  const MethodDescriptor* method = service->FindMethodByName("Method");
+
+  // Tests for the different types of data embedded in fileopt
+  const protobuf_unittest::Aggregate& file_options =
+      file->options().GetExtension(protobuf_unittest::fileopt);
+  EXPECT_EQ(100, file_options.i());
+  EXPECT_EQ("FileAnnotation", file_options.s());
+  EXPECT_EQ("NestedFileAnnotation", file_options.sub().s());
+  EXPECT_EQ("FileExtensionAnnotation",
+            file_options.file().GetExtension(protobuf_unittest::fileopt).s());
+  EXPECT_EQ("EmbeddedMessageSetElement",
+            file_options.mset().GetExtension(
+                protobuf_unittest::AggregateMessageSetElement
+                ::message_set_extension).s());
+
+  // Simple tests for all the other types of annotations
+  EXPECT_EQ("MessageAnnotation",
+            msg->options().GetExtension(protobuf_unittest::msgopt).s());
+  EXPECT_EQ("FieldAnnotation",
+            field->options().GetExtension(protobuf_unittest::fieldopt).s());
+  EXPECT_EQ("EnumAnnotation",
+            enumd->options().GetExtension(protobuf_unittest::enumopt).s());
+  EXPECT_EQ("EnumValueAnnotation",
+            enumv->options().GetExtension(protobuf_unittest::enumvalopt).s());
+  EXPECT_EQ("ServiceAnnotation",
+            service->options().GetExtension(protobuf_unittest::serviceopt).s());
+  EXPECT_EQ("MethodAnnotation",
+            method->options().GetExtension(protobuf_unittest::methodopt).s());
+}
 
 // ===================================================================
 
@@ -3425,25 +3464,50 @@
     "string option \"foo\".\n");
 }
 
-TEST_F(ValidationErrorTest, TryingToSetMessageValuedOption) {
+// Helper function for tests that check for aggregate value parsing
+// errors.  The "value" argument is embedded inside the
+// "uninterpreted_option" portion of the result.
+static string EmbedAggregateValue(const char* value) {
+  return strings::Substitute(
+      "name: \"foo.proto\" "
+      "dependency: \"google/protobuf/descriptor.proto\" "
+      "message_type { name: \"Foo\" } "
+      "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
+      "            type: TYPE_MESSAGE type_name: \"Foo\" "
+      "            extendee: \"google.protobuf.FileOptions\" }"
+      "options { uninterpreted_option { name { name_part: \"foo\" "
+      "                                        is_extension: true } "
+      "                                 $0 } }",
+      value);
+}
+
+TEST_F(ValidationErrorTest, AggregateValueNotFound) {
   BuildDescriptorMessagesInTestPool();
 
   BuildFileWithErrors(
-    "name: \"foo.proto\" "
-    "dependency: \"google/protobuf/descriptor.proto\" "
-    "message_type { "
-    "  name: \"TestMessage\" "
-    "  field { name:\"baz\" number:1 label:LABEL_OPTIONAL type:TYPE_STRING }"
-    "}"
-    "extension { name: \"bar\" number: 7672757 label: LABEL_OPTIONAL "
-    "            type: TYPE_MESSAGE type_name: \"TestMessage\" "
-    "            extendee: \"google.protobuf.FileOptions\" }"
-    "options { uninterpreted_option { name { name_part: \"bar\" "
-    "                                        is_extension: true } "
-    "                                 identifier_value: \"QUUX\" } }",
+      EmbedAggregateValue("string_value: \"\""),
+      "foo.proto: foo.proto: OPTION_VALUE: Option \"foo\" is a message. "
+      "To set the entire message, use syntax like "
+      "\"foo = { <proto text format> }\". To set fields within it, use "
+      "syntax like \"foo.foo = value\".\n");
+}
 
-    "foo.proto: foo.proto: OPTION_NAME: Option field \"(bar)\" cannot be of "
-    "message type.\n");
+TEST_F(ValidationErrorTest, AggregateValueParseError) {
+  BuildDescriptorMessagesInTestPool();
+
+  BuildFileWithErrors(
+      EmbedAggregateValue("aggregate_value: \"1+2\""),
+      "foo.proto: foo.proto: OPTION_VALUE: Error while parsing option "
+      "value for \"foo\": Expected identifier.\n");
+}
+
+TEST_F(ValidationErrorTest, AggregateValueUnknownFields) {
+  BuildDescriptorMessagesInTestPool();
+
+  BuildFileWithErrors(
+      EmbedAggregateValue("aggregate_value: \"x:100\""),
+      "foo.proto: foo.proto: OPTION_VALUE: Error while parsing option "
+      "value for \"foo\": Message type \"Foo\" has no field named \"x\".\n");
 }
 
 TEST_F(ValidationErrorTest, NotLiteImportsLite) {
@@ -3483,7 +3547,11 @@
 TEST_F(ValidationErrorTest, NoLiteServices) {
   BuildFileWithErrors(
     "name: \"foo.proto\" "
-    "options { optimize_for: LITE_RUNTIME } "
+    "options {"
+    "  optimize_for: LITE_RUNTIME"
+    "  cc_generic_services: true"
+    "  java_generic_services: true"
+    "} "
     "service { name: \"Foo\" }",
 
     "foo.proto: Foo: NAME: Files with optimize_for = LITE_RUNTIME cannot "
@@ -3497,7 +3565,7 @@
     "  cc_generic_services: false"
     "  java_generic_services: false"
     "} "
-    "service { name: \"Foo\" }");
+    "service { name: \"Bar\" }");
 }
 
 TEST_F(ValidationErrorTest, RollbackAfterError) {
diff --git a/src/google/protobuf/extension_set.cc b/src/google/protobuf/extension_set.cc
index 6084885..1a6f5df 100644
--- a/src/google/protobuf/extension_set.cc
+++ b/src/google/protobuf/extension_set.cc
@@ -186,6 +186,18 @@
   return iter->second.GetSize();
 }
 
+FieldType ExtensionSet::ExtensionType(int number) const {
+  map<int, Extension>::const_iterator iter = extensions_.find(number);
+  if (iter == extensions_.end()) {
+    GOOGLE_LOG(DFATAL) << "Don't lookup extension types if they aren't present (1). ";
+    return 0;
+  }
+  if (iter->second.is_cleared) {
+    GOOGLE_LOG(DFATAL) << "Don't lookup extension types if they aren't present (2). ";
+  }
+  return iter->second.type;
+}
+
 void ExtensionSet::ClearExtension(int number) {
   map<int, Extension>::iterator iter = extensions_.find(number);
   if (iter == extensions_.end()) return;
diff --git a/src/google/protobuf/extension_set.h b/src/google/protobuf/extension_set.h
index 14d5d15..ac1ada0 100644
--- a/src/google/protobuf/extension_set.h
+++ b/src/google/protobuf/extension_set.h
@@ -39,11 +39,11 @@
 #define GOOGLE_PROTOBUF_EXTENSION_SET_H__
 
 #include <vector>
-#include <stack>
 #include <map>
 #include <utility>
 #include <string>
 
+
 #include <google/protobuf/stubs/common.h>
 
 namespace google {
@@ -214,6 +214,7 @@
 
   bool Has(int number) const;
   int ExtensionSize(int number) const;   // Size of a repeated extension.
+  FieldType ExtensionType(int number) const;
   void ClearExtension(int number);
 
   // singular fields -------------------------------------------------
@@ -451,6 +452,7 @@
     int SpaceUsedExcludingSelf() const;
   };
 
+
   // Gets the extension with the given number, creating it if it does not
   // already exist.  Returns true if the extension did not already exist.
   bool MaybeNewExtension(int number, const FieldDescriptor* descriptor,
diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc
index 0f065ff..a0dd75c 100644
--- a/src/google/protobuf/generated_message_reflection.cc
+++ b/src/google/protobuf/generated_message_reflection.cc
@@ -45,8 +45,6 @@
 namespace protobuf {
 namespace internal {
 
-namespace { const string kEmptyString; }
-
 int StringSpaceUsedExcludingSelf(const string& str) {
   const void* start = &str;
   const void* end = &str + 1;
@@ -69,7 +67,6 @@
 }
 
 const string& NameOfEnum(const EnumDescriptor* descriptor, int value) {
-  static string kEmptyString;
   const EnumValueDescriptor* d = descriptor->FindValueByNumber(value);
   return (d == NULL ? kEmptyString : d->name());
 }
diff --git a/src/google/protobuf/generated_message_util.cc b/src/google/protobuf/generated_message_util.cc
index 7ac015d..76e547b 100644
--- a/src/google/protobuf/generated_message_util.cc
+++ b/src/google/protobuf/generated_message_util.cc
@@ -47,6 +47,8 @@
   return std::numeric_limits<double>::quiet_NaN();
 }
 
+const ::std::string kEmptyString;
+
 
 }  // namespace internal
 }  // namespace protobuf
diff --git a/src/google/protobuf/generated_message_util.h b/src/google/protobuf/generated_message_util.h
index daa16f7..1a2343d 100644
--- a/src/google/protobuf/generated_message_util.h
+++ b/src/google/protobuf/generated_message_util.h
@@ -38,6 +38,8 @@
 #ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__
 #define GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__
 
+#include <string>
+
 #include <google/protobuf/stubs/common.h>
 
 
@@ -66,8 +68,11 @@
 
 
 // Constants for special floating point values.
-LIBPROTOBUF_EXPORT double Infinity();
-LIBPROTOBUF_EXPORT double NaN();
+double Infinity();
+double NaN();
+
+// Constant used for empty default strings.
+extern const ::std::string kEmptyString;
 
 
 }  // namespace internal
diff --git a/src/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc
index 6a91a13..57d486f 100644
--- a/src/google/protobuf/io/coded_stream.cc
+++ b/src/google/protobuf/io/coded_stream.cc
@@ -56,6 +56,15 @@
 static const int kMaxVarint32Bytes = 5;
 
 
+inline bool NextNonEmpty(ZeroCopyInputStream* input,
+                         const void** data, int* size) {
+  bool success;
+  do {
+    success = input->Next(data, size);
+  } while (success && *size == 0);
+  return success;
+}
+
 }  // namespace
 
 // CodedInputStream ==================================================
@@ -489,7 +498,7 @@
 
   const void* void_buffer;
   int buffer_size;
-  if (input_->Next(&void_buffer, &buffer_size)) {
+  if (NextNonEmpty(input_, &void_buffer, &buffer_size)) {
     buffer_ = reinterpret_cast<const uint8*>(void_buffer);
     buffer_end_ = buffer_ + buffer_size;
     GOOGLE_CHECK_GE(buffer_size, 0);
diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h
index 93effc8..73a54dd 100644
--- a/src/google/protobuf/io/coded_stream.h
+++ b/src/google/protobuf/io/coded_stream.h
@@ -129,8 +129,8 @@
 #endif
 #include <google/protobuf/stubs/common.h>
 
-namespace google {
 
+namespace google {
 namespace protobuf {
 
 class DescriptorPool;
@@ -782,7 +782,8 @@
 }
 
 inline bool CodedInputStream::ReadLittleEndian32(uint32* value) {
-#if defined(PROTOBUF_LITTLE_ENDIAN)
+#if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) && \
+    defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN
   if (GOOGLE_PREDICT_TRUE(BufferSize() >= static_cast<int>(sizeof(*value)))) {
     memcpy(value, buffer_, sizeof(*value));
     Advance(sizeof(*value));
@@ -796,7 +797,8 @@
 }
 
 inline bool CodedInputStream::ReadLittleEndian64(uint64* value) {
-#if defined(PROTOBUF_LITTLE_ENDIAN)
+#if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) && \
+    defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN
   if (GOOGLE_PREDICT_TRUE(BufferSize() >= static_cast<int>(sizeof(*value)))) {
     memcpy(value, buffer_, sizeof(*value));
     Advance(sizeof(*value));
@@ -1093,10 +1095,10 @@
 }  // namespace io
 }  // namespace protobuf
 
-}  // namespace google
 
 #if defined(_MSC_VER) && _MSC_VER >= 1300
   #pragma runtime_checks("c", restore)
 #endif  // _MSC_VER
 
+}  // namespace google
 #endif  // GOOGLE_PROTOBUF_IO_CODED_STREAM_H__
diff --git a/src/google/protobuf/io/coded_stream_unittest.cc b/src/google/protobuf/io/coded_stream_unittest.cc
index 7d29833..ff268ab 100644
--- a/src/google/protobuf/io/coded_stream_unittest.cc
+++ b/src/google/protobuf/io/coded_stream_unittest.cc
@@ -208,6 +208,33 @@
   EXPECT_EQ(kVarintCases_case.size, input.ByteCount());
 }
 
+// This is the regression test that verifies that there is no issues
+// with the empty input buffers handling.
+TEST_F(CodedStreamTest, EmptyInputBeforeEos) {
+  class In : public ZeroCopyInputStream {
+   public:
+    In() : count_(0) {}
+   private:
+    virtual bool Next(const void** data, int* size) {
+      *data = NULL;
+      *size = 0;
+      return count_++ < 2;
+    }
+    virtual void BackUp(int count)  {
+      GOOGLE_LOG(FATAL) << "Tests never call this.";
+    }
+    virtual bool Skip(int count) {
+      GOOGLE_LOG(FATAL) << "Tests never call this.";
+      return false;
+    }
+    virtual int64 ByteCount() const { return 0; }
+    int count_;
+  } in;
+  CodedInputStream input(&in);
+  input.ReadTag();
+  EXPECT_TRUE(input.ConsumedEntireMessage());
+}
+
 TEST_1D(CodedStreamTest, ExpectTag, kVarintCases) {
   // Leave one byte at the beginning of the buffer so we can read it
   // to force the first buffer to be loaded.
@@ -995,6 +1022,7 @@
   EXPECT_FALSE(coded_input.ConsumedEntireMessage());
 }
 
+
 TEST_F(CodedStreamTest, RecursionLimit) {
   ArrayInputStream input(buffer_, sizeof(buffer_));
   CodedInputStream coded_input(&input);
diff --git a/src/google/protobuf/io/gzip_stream.cc b/src/google/protobuf/io/gzip_stream.cc
index 84d277f..0f1ff87 100644
--- a/src/google/protobuf/io/gzip_stream.cc
+++ b/src/google/protobuf/io/gzip_stream.cc
@@ -73,6 +73,17 @@
   zerror_ = inflateEnd(&zcontext_);
 }
 
+static inline int internalInflateInit2(
+    z_stream* zcontext, GzipInputStream::Format format) {
+  int windowBitsFormat = 0;
+  switch (format) {
+    case GzipInputStream::GZIP: windowBitsFormat = 16; break;
+    case GzipInputStream::AUTO: windowBitsFormat = 32; break;
+    case GzipInputStream::ZLIB: windowBitsFormat = 0; break;
+  }
+  return inflateInit2(zcontext, /* windowBits */15 | windowBitsFormat);
+}
+
 int GzipInputStream::Inflate(int flush) {
   if ((zerror_ == Z_OK) && (zcontext_.avail_out == 0)) {
     // previous inflate filled output buffer. don't change input params yet.
@@ -89,14 +100,7 @@
     zcontext_.next_in = static_cast<Bytef*>(const_cast<void*>(in));
     zcontext_.avail_in = in_size;
     if (first) {
-      int windowBitsFormat = 0;
-      switch (format_) {
-        case GZIP: windowBitsFormat = 16; break;
-        case AUTO: windowBitsFormat = 32; break;
-        case ZLIB: windowBitsFormat = 0; break;
-      }
-      int error = inflateInit2(&zcontext_,
-        /* windowBits */15 | windowBitsFormat);
+      int error = internalInflateInit2(&zcontext_, format_);
       if (error != Z_OK) {
         return error;
       }
@@ -127,9 +131,21 @@
     return true;
   }
   if (zerror_ == Z_STREAM_END) {
-    *data = NULL;
-    *size = 0;
-    return false;
+    if (zcontext_.next_out != NULL) {
+      // sub_stream_ may have concatenated streams to follow
+      zerror_ = inflateEnd(&zcontext_);
+      if (zerror_ != Z_OK) {
+        return false;
+      }
+      zerror_ = internalInflateInit2(&zcontext_, format_);
+      if (zerror_ != Z_OK) {
+        return false;
+      }
+    } else {
+      *data = NULL;
+      *size = 0;
+      return false;
+    }
   }
   zerror_ = Inflate(Z_NO_FLUSH);
   if ((zerror_ == Z_STREAM_END) && (zcontext_.next_out == NULL)) {
@@ -251,8 +267,7 @@
     }
     error = deflate(&zcontext_, flush);
   } while (error == Z_OK && zcontext_.avail_out == 0);
-  if (((flush == Z_FULL_FLUSH) || (flush == Z_FINISH))
-      && (zcontext_.avail_out != sub_data_size_)) {
+  if ((flush == Z_FULL_FLUSH) || (flush == Z_FINISH)) {
     // Notify lower layer of data.
     sub_stream_->BackUp(zcontext_.avail_out);
     // We don't own the buffer anymore.
diff --git a/src/google/protobuf/io/printer.cc b/src/google/protobuf/io/printer.cc
index c7d3074..9ab90de 100644
--- a/src/google/protobuf/io/printer.cc
+++ b/src/google/protobuf/io/printer.cc
@@ -132,6 +132,17 @@
   Print(vars, text);
 }
 
+void Printer::Print(const char* text,
+                    const char* variable1, const string& value1,
+                    const char* variable2, const string& value2,
+                    const char* variable3, const string& value3) {
+  map<string, string> vars;
+  vars[variable1] = value1;
+  vars[variable2] = value2;
+  vars[variable3] = value3;
+  Print(vars, text);
+}
+
 void Printer::Indent() {
   indent_ += "  ";
 }
diff --git a/src/google/protobuf/io/printer.h b/src/google/protobuf/io/printer.h
index de08538..5be4854 100644
--- a/src/google/protobuf/io/printer.h
+++ b/src/google/protobuf/io/printer.h
@@ -82,7 +82,11 @@
   // Like the first Print(), except the substitutions are given as parameters.
   void Print(const char* text, const char* variable1, const string& value1,
                                const char* variable2, const string& value2);
-  // TODO(kenton):  Overloaded versions with more variables?  Two seems
+  // Like the first Print(), except the substitutions are given as parameters.
+  void Print(const char* text, const char* variable1, const string& value1,
+                               const char* variable2, const string& value2,
+                               const char* variable3, const string& value3);
+  // TODO(kenton):  Overloaded versions with more variables?  Three seems
   //   to be enough.
 
   // Indent text by two spaces.  After calling Indent(), two spaces will be
diff --git a/src/google/protobuf/io/tokenizer.cc b/src/google/protobuf/io/tokenizer.cc
index 38fa351..513831d 100644
--- a/src/google/protobuf/io/tokenizer.cc
+++ b/src/google/protobuf/io/tokenizer.cc
@@ -193,6 +193,7 @@
 
   current_.line = 0;
   current_.column = 0;
+  current_.end_column = 0;
   current_.type = TYPE_START;
 
   Refresh();
@@ -277,6 +278,7 @@
     current_.text.append(buffer_ + token_start_, buffer_pos_ - token_start_);
   }
   token_start_ = -1;
+  current_.end_column = column_;
 }
 
 // -------------------------------------------------------------------
@@ -462,7 +464,7 @@
 // -------------------------------------------------------------------
 
 bool Tokenizer::Next() {
-  TokenType last_token_type = current_.type;
+  previous_ = current_;
 
   // Did we skip any characters after the last token?
   bool skipped_stuff = false;
@@ -517,7 +519,7 @@
 
         if (TryConsumeOne<Digit>()) {
           // It's a floating-point number.
-          if (last_token_type == TYPE_IDENTIFIER && !skipped_stuff) {
+          if (previous_.type == TYPE_IDENTIFIER && !skipped_stuff) {
             // We don't accept syntax like "blah.123".
             error_collector_->AddError(line_, column_ - 2,
               "Need space between identifier and decimal point.");
@@ -551,6 +553,7 @@
   current_.text.clear();
   current_.line = line_;
   current_.column = column_;
+  current_.end_column = column_;
   return false;
 }
 
diff --git a/src/google/protobuf/io/tokenizer.h b/src/google/protobuf/io/tokenizer.h
index d115161..8f759ab 100644
--- a/src/google/protobuf/io/tokenizer.h
+++ b/src/google/protobuf/io/tokenizer.h
@@ -122,12 +122,17 @@
     // the token within the input stream.  They are zero-based.
     int line;
     int column;
+    int end_column;
   };
 
   // Get the current token.  This is updated when Next() is called.  Before
   // the first call to Next(), current() has type TYPE_START and no contents.
   const Token& current();
 
+  // Return the previous token -- i.e. what current() returned before the
+  // previous call to Next().
+  const Token& previous();
+
   // Advance to the next token.  Returns false if the end of the input is
   // reached.
   bool Next();
@@ -180,6 +185,7 @@
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Tokenizer);
 
   Token current_;           // Returned by current().
+  Token previous_;          // Returned by previous().
 
   ZeroCopyInputStream* input_;
   ErrorCollector* error_collector_;
@@ -291,6 +297,10 @@
   return current_;
 }
 
+inline const Tokenizer::Token& Tokenizer::previous() {
+  return previous_;
+}
+
 inline void Tokenizer::ParseString(const string& text, string* output) {
   output->clear();
   ParseStringAppend(text, output);
diff --git a/src/google/protobuf/io/tokenizer_unittest.cc b/src/google/protobuf/io/tokenizer_unittest.cc
index 358ec56..106d080 100644
--- a/src/google/protobuf/io/tokenizer_unittest.cc
+++ b/src/google/protobuf/io/tokenizer_unittest.cc
@@ -257,6 +257,7 @@
   EXPECT_EQ("", tokenizer.current().text);
   EXPECT_EQ(0, tokenizer.current().line);
   EXPECT_EQ(0, tokenizer.current().column);
+  EXPECT_EQ(0, tokenizer.current().end_column);
 
   // Parse the token.
   ASSERT_TRUE(tokenizer.Next());
@@ -268,6 +269,8 @@
   // Check that it is located at the beginning of the input
   EXPECT_EQ(0, tokenizer.current().line);
   EXPECT_EQ(0, tokenizer.current().column);
+  EXPECT_EQ(kSimpleTokenCases_case.input.size(),
+            tokenizer.current().end_column);
 
   // There should be no more input.
   EXPECT_FALSE(tokenizer.Next());
@@ -277,6 +280,8 @@
   EXPECT_EQ("", tokenizer.current().text);
   EXPECT_EQ(0, tokenizer.current().line);
   EXPECT_EQ(kSimpleTokenCases_case.input.size(), tokenizer.current().column);
+  EXPECT_EQ(kSimpleTokenCases_case.input.size(),
+            tokenizer.current().end_column);
 
   // There should be no errors.
   EXPECT_TRUE(error_collector.text_.empty());
@@ -339,76 +344,83 @@
 
   // Test all token types at the same time.
   { "foo 1 1.2 + 'bar'", {
-    { Tokenizer::TYPE_IDENTIFIER, "foo"  , 0,  0 },
-    { Tokenizer::TYPE_INTEGER   , "1"    , 0,  4 },
-    { Tokenizer::TYPE_FLOAT     , "1.2"  , 0,  6 },
-    { Tokenizer::TYPE_SYMBOL    , "+"    , 0, 10 },
-    { Tokenizer::TYPE_STRING    , "'bar'", 0, 12 },
-    { Tokenizer::TYPE_END       , ""     , 0, 17 },
+    { Tokenizer::TYPE_IDENTIFIER, "foo"  , 0,  0,  3 },
+    { Tokenizer::TYPE_INTEGER   , "1"    , 0,  4,  5 },
+    { Tokenizer::TYPE_FLOAT     , "1.2"  , 0,  6,  9 },
+    { Tokenizer::TYPE_SYMBOL    , "+"    , 0, 10, 11 },
+    { Tokenizer::TYPE_STRING    , "'bar'", 0, 12, 17 },
+    { Tokenizer::TYPE_END       , ""     , 0, 17, 17 },
   }},
 
   // Test that consecutive symbols are parsed as separate tokens.
   { "!@+%", {
-    { Tokenizer::TYPE_SYMBOL    , "!"    , 0, 0 },
-    { Tokenizer::TYPE_SYMBOL    , "@"    , 0, 1 },
-    { Tokenizer::TYPE_SYMBOL    , "+"    , 0, 2 },
-    { Tokenizer::TYPE_SYMBOL    , "%"    , 0, 3 },
-    { Tokenizer::TYPE_END       , ""     , 0, 4 },
+    { Tokenizer::TYPE_SYMBOL    , "!"    , 0, 0, 1 },
+    { Tokenizer::TYPE_SYMBOL    , "@"    , 0, 1, 2 },
+    { Tokenizer::TYPE_SYMBOL    , "+"    , 0, 2, 3 },
+    { Tokenizer::TYPE_SYMBOL    , "%"    , 0, 3, 4 },
+    { Tokenizer::TYPE_END       , ""     , 0, 4, 4 },
   }},
 
   // Test that newlines affect line numbers correctly.
   { "foo bar\nrab oof", {
-    { Tokenizer::TYPE_IDENTIFIER, "foo", 0,  0 },
-    { Tokenizer::TYPE_IDENTIFIER, "bar", 0,  4 },
-    { Tokenizer::TYPE_IDENTIFIER, "rab", 1,  0 },
-    { Tokenizer::TYPE_IDENTIFIER, "oof", 1,  4 },
-    { Tokenizer::TYPE_END       , ""   , 1,  7 },
+    { Tokenizer::TYPE_IDENTIFIER, "foo", 0,  0, 3 },
+    { Tokenizer::TYPE_IDENTIFIER, "bar", 0,  4, 7 },
+    { Tokenizer::TYPE_IDENTIFIER, "rab", 1,  0, 3 },
+    { Tokenizer::TYPE_IDENTIFIER, "oof", 1,  4, 7 },
+    { Tokenizer::TYPE_END       , ""   , 1,  7, 7 },
   }},
 
   // Test that tabs affect column numbers correctly.
   { "foo\tbar  \tbaz", {
-    { Tokenizer::TYPE_IDENTIFIER, "foo", 0,  0 },
-    { Tokenizer::TYPE_IDENTIFIER, "bar", 0,  8 },
-    { Tokenizer::TYPE_IDENTIFIER, "baz", 0, 16 },
-    { Tokenizer::TYPE_END       , ""   , 0, 19 },
+    { Tokenizer::TYPE_IDENTIFIER, "foo", 0,  0,  3 },
+    { Tokenizer::TYPE_IDENTIFIER, "bar", 0,  8, 11 },
+    { Tokenizer::TYPE_IDENTIFIER, "baz", 0, 16, 19 },
+    { Tokenizer::TYPE_END       , ""   , 0, 19, 19 },
+  }},
+
+  // Test that tabs in string literals affect column numbers correctly.
+  { "\"foo\tbar\" baz", {
+    { Tokenizer::TYPE_STRING    , "\"foo\tbar\"", 0,  0, 12 },
+    { Tokenizer::TYPE_IDENTIFIER, "baz"         , 0, 13, 16 },
+    { Tokenizer::TYPE_END       , ""            , 0, 16, 16 },
   }},
 
   // Test that line comments are ignored.
   { "foo // This is a comment\n"
     "bar // This is another comment", {
-    { Tokenizer::TYPE_IDENTIFIER, "foo", 0,  0 },
-    { Tokenizer::TYPE_IDENTIFIER, "bar", 1,  0 },
-    { Tokenizer::TYPE_END       , ""   , 1, 30 },
+    { Tokenizer::TYPE_IDENTIFIER, "foo", 0,  0,  3 },
+    { Tokenizer::TYPE_IDENTIFIER, "bar", 1,  0,  3 },
+    { Tokenizer::TYPE_END       , ""   , 1, 30, 30 },
   }},
 
   // Test that block comments are ignored.
   { "foo /* This is a block comment */ bar", {
-    { Tokenizer::TYPE_IDENTIFIER, "foo", 0,  0 },
-    { Tokenizer::TYPE_IDENTIFIER, "bar", 0, 34 },
-    { Tokenizer::TYPE_END       , ""   , 0, 37 },
+    { Tokenizer::TYPE_IDENTIFIER, "foo", 0,  0,  3 },
+    { Tokenizer::TYPE_IDENTIFIER, "bar", 0, 34, 37 },
+    { Tokenizer::TYPE_END       , ""   , 0, 37, 37 },
   }},
 
   // Test that sh-style comments are not ignored by default.
   { "foo # bar\n"
     "baz", {
-    { Tokenizer::TYPE_IDENTIFIER, "foo", 0,  0 },
-    { Tokenizer::TYPE_SYMBOL    , "#"  , 0,  4 },
-    { Tokenizer::TYPE_IDENTIFIER, "bar", 0,  6 },
-    { Tokenizer::TYPE_IDENTIFIER, "baz", 1,  0 },
-    { Tokenizer::TYPE_END       , ""   , 1, 3 },
+    { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0, 3 },
+    { Tokenizer::TYPE_SYMBOL    , "#"  , 0, 4, 5 },
+    { Tokenizer::TYPE_IDENTIFIER, "bar", 0, 6, 9 },
+    { Tokenizer::TYPE_IDENTIFIER, "baz", 1, 0, 3 },
+    { Tokenizer::TYPE_END       , ""   , 1, 3, 3 },
   }},
 
   // Bytes with the high-order bit set should not be seen as control characters.
   { "\300", {
-    { Tokenizer::TYPE_SYMBOL, "\300", 0, 0 },
-    { Tokenizer::TYPE_END   , ""    , 0, 1 },
+    { Tokenizer::TYPE_SYMBOL, "\300", 0, 0, 1 },
+    { Tokenizer::TYPE_END   , ""    , 0, 1, 1 },
   }},
 
   // Test all whitespace chars
   { "foo\n\t\r\v\fbar", {
-    { Tokenizer::TYPE_IDENTIFIER, "foo", 0,  0 },
-    { Tokenizer::TYPE_IDENTIFIER, "bar", 1, 11 },
-    { Tokenizer::TYPE_END       , ""   , 1, 14 },
+    { Tokenizer::TYPE_IDENTIFIER, "foo", 0,  0,  3 },
+    { Tokenizer::TYPE_IDENTIFIER, "bar", 1, 11, 14 },
+    { Tokenizer::TYPE_END       , ""   , 1, 14, 14 },
   }},
 };
 
@@ -425,6 +437,7 @@
   EXPECT_EQ("", tokenizer.current().text);
   EXPECT_EQ(0, tokenizer.current().line);
   EXPECT_EQ(0, tokenizer.current().column);
+  EXPECT_EQ(0, tokenizer.current().end_column);
 
   // Loop through all expected tokens.
   int i = 0;
@@ -434,6 +447,8 @@
 
     SCOPED_TRACE(testing::Message() << "Token #" << i << ": " << token.text);
 
+    Tokenizer::Token previous = tokenizer.current();
+
     // Next() should only return false when it hits the end token.
     if (token.type != Tokenizer::TYPE_END) {
       ASSERT_TRUE(tokenizer.Next());
@@ -441,11 +456,19 @@
       ASSERT_FALSE(tokenizer.Next());
     }
 
+    // Check that the previous token is set correctly.
+    EXPECT_EQ(previous.type, tokenizer.previous().type);
+    EXPECT_EQ(previous.text, tokenizer.previous().text);
+    EXPECT_EQ(previous.line, tokenizer.previous().line);
+    EXPECT_EQ(previous.column, tokenizer.previous().column);
+    EXPECT_EQ(previous.end_column, tokenizer.previous().end_column);
+
     // Check that the token matches the expected one.
     EXPECT_EQ(token.type, tokenizer.current().type);
     EXPECT_EQ(token.text, tokenizer.current().text);
     EXPECT_EQ(token.line, tokenizer.current().line);
     EXPECT_EQ(token.column, tokenizer.current().column);
+    EXPECT_EQ(token.end_column, tokenizer.current().end_column);
 
   } while (token.type != Tokenizer::TYPE_END);
 
diff --git a/src/google/protobuf/io/zero_copy_stream_unittest.cc b/src/google/protobuf/io/zero_copy_stream_unittest.cc
index 8229ee6..5196d90 100644
--- a/src/google/protobuf/io/zero_copy_stream_unittest.cc
+++ b/src/google/protobuf/io/zero_copy_stream_unittest.cc
@@ -61,6 +61,7 @@
 #include <sstream>
 
 #include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/io/coded_stream.h>
 
 #if HAVE_ZLIB
 #include <google/protobuf/io/gzip_stream.h>
@@ -285,6 +286,57 @@
   }
 }
 
+TEST_F(IoTest, TwoSessionWrite) {
+  // Test that two concatenated write sessions read correctly
+
+  static const char* strA = "0123456789";
+  static const char* strB = "WhirledPeas";
+  const int kBufferSize = 2*1024;
+  uint8* buffer = new uint8[kBufferSize];
+  char* temp_buffer = new char[40];
+
+  for (int i = 0; i < kBlockSizeCount; i++) {
+    for (int j = 0; j < kBlockSizeCount; j++) {
+      ArrayOutputStream* output =
+          new ArrayOutputStream(buffer, kBufferSize, kBlockSizes[i]);
+      CodedOutputStream* coded_output = new CodedOutputStream(output);
+      coded_output->WriteVarint32(strlen(strA));
+      coded_output->WriteRaw(strA, strlen(strA));
+      delete coded_output;  // flush
+      int64 pos = output->ByteCount();
+      delete output;
+      output = new ArrayOutputStream(
+          buffer + pos, kBufferSize - pos, kBlockSizes[i]);
+      coded_output = new CodedOutputStream(output);
+      coded_output->WriteVarint32(strlen(strB));
+      coded_output->WriteRaw(strB, strlen(strB));
+      delete coded_output;  // flush
+      int64 size = pos + output->ByteCount();
+      delete output;
+
+      ArrayInputStream* input =
+          new ArrayInputStream(buffer, size, kBlockSizes[j]);
+      CodedInputStream* coded_input = new CodedInputStream(input);
+      uint32 insize;
+      EXPECT_TRUE(coded_input->ReadVarint32(&insize));
+      EXPECT_EQ(strlen(strA), insize);
+      EXPECT_TRUE(coded_input->ReadRaw(temp_buffer, insize));
+      EXPECT_EQ(0, memcmp(temp_buffer, strA, insize));
+
+      EXPECT_TRUE(coded_input->ReadVarint32(&insize));
+      EXPECT_EQ(strlen(strB), insize);
+      EXPECT_TRUE(coded_input->ReadRaw(temp_buffer, insize));
+      EXPECT_EQ(0, memcmp(temp_buffer, strB, insize));
+
+      delete coded_input;
+      delete input;
+    }
+  }
+
+  delete [] temp_buffer;
+  delete [] buffer;
+}
+
 #if HAVE_ZLIB
 TEST_F(IoTest, GzipIo) {
   const int kBufferSize = 2*1024;
@@ -296,8 +348,12 @@
         int size;
         {
           ArrayOutputStream output(buffer, kBufferSize, kBlockSizes[i]);
-          GzipOutputStream gzout(
-              &output, GzipOutputStream::GZIP, gzip_buffer_size);
+          GzipOutputStream::Options options;
+          options.format = GzipOutputStream::GZIP;
+          if (gzip_buffer_size != -1) {
+            options.buffer_size = gzip_buffer_size;
+          }
+          GzipOutputStream gzout(&output, options);
           WriteStuff(&gzout);
           gzout.Close();
           size = output.ByteCount();
@@ -324,8 +380,12 @@
         int size;
         {
           ArrayOutputStream output(buffer, kBufferSize, kBlockSizes[i]);
-          GzipOutputStream gzout(
-              &output, GzipOutputStream::ZLIB, gzip_buffer_size);
+          GzipOutputStream::Options options;
+          options.format = GzipOutputStream::ZLIB;
+          if (gzip_buffer_size != -1) {
+            options.buffer_size = gzip_buffer_size;
+          }
+          GzipOutputStream gzout(&output, options);
           WriteStuff(&gzout);
           gzout.Close();
           size = output.ByteCount();
@@ -348,7 +408,9 @@
   int size;
   {
     ArrayOutputStream output(buffer, kBufferSize);
-    GzipOutputStream gzout(&output, GzipOutputStream::ZLIB);
+    GzipOutputStream::Options options;
+    options.format = GzipOutputStream::ZLIB;
+    GzipOutputStream gzout(&output, options);
     WriteStuff(&gzout);
     gzout.Close();
     size = output.ByteCount();
@@ -360,7 +422,9 @@
   }
   {
     ArrayOutputStream output(buffer, kBufferSize);
-    GzipOutputStream gzout(&output, GzipOutputStream::GZIP);
+    GzipOutputStream::Options options;
+    options.format = GzipOutputStream::GZIP;
+    GzipOutputStream gzout(&output, options);
     WriteStuff(&gzout);
     gzout.Close();
     size = output.ByteCount();
@@ -432,6 +496,71 @@
   EXPECT_TRUE(Uncompress(gzip_compressed) == golden);
   EXPECT_TRUE(Uncompress(zlib_compressed) == golden);
 }
+
+TEST_F(IoTest, TwoSessionWriteGzip) {
+  // Test that two concatenated gzip streams can be read correctly
+
+  static const char* strA = "0123456789";
+  static const char* strB = "QuickBrownFox";
+  const int kBufferSize = 2*1024;
+  uint8* buffer = new uint8[kBufferSize];
+  char* temp_buffer = new char[40];
+
+  for (int i = 0; i < kBlockSizeCount; i++) {
+    for (int j = 0; j < kBlockSizeCount; j++) {
+      ArrayOutputStream* output =
+          new ArrayOutputStream(buffer, kBufferSize, kBlockSizes[i]);
+      GzipOutputStream* gzout = new GzipOutputStream(output);
+      CodedOutputStream* coded_output = new CodedOutputStream(gzout);
+      int32 outlen = strlen(strA) + 1;
+      coded_output->WriteVarint32(outlen);
+      coded_output->WriteRaw(strA, outlen);
+      delete coded_output;  // flush
+      delete gzout;  // flush
+      int64 pos = output->ByteCount();
+      delete output;
+      output = new ArrayOutputStream(
+          buffer + pos, kBufferSize - pos, kBlockSizes[i]);
+      gzout = new GzipOutputStream(output);
+      coded_output = new CodedOutputStream(gzout);
+      outlen = strlen(strB) + 1;
+      coded_output->WriteVarint32(outlen);
+      coded_output->WriteRaw(strB, outlen);
+      delete coded_output;  // flush
+      delete gzout;  // flush
+      int64 size = pos + output->ByteCount();
+      delete output;
+
+      ArrayInputStream* input =
+          new ArrayInputStream(buffer, size, kBlockSizes[j]);
+      GzipInputStream* gzin = new GzipInputStream(input);
+      CodedInputStream* coded_input = new CodedInputStream(gzin);
+      uint32 insize;
+      EXPECT_TRUE(coded_input->ReadVarint32(&insize));
+      EXPECT_EQ(strlen(strA) + 1, insize);
+      EXPECT_TRUE(coded_input->ReadRaw(temp_buffer, insize));
+      EXPECT_EQ(0, memcmp(temp_buffer, strA, insize))
+          << "strA=" << strA << " in=" << temp_buffer;
+
+      EXPECT_TRUE(coded_input->ReadVarint32(&insize));
+      EXPECT_EQ(strlen(strB) + 1, insize);
+      EXPECT_TRUE(coded_input->ReadRaw(temp_buffer, insize));
+      EXPECT_EQ(0, memcmp(temp_buffer, strB, insize))
+          << " out_block_size=" << kBlockSizes[i]
+          << " in_block_size=" << kBlockSizes[j]
+          << " pos=" << pos
+          << " size=" << size
+          << " strB=" << strB << " in=" << temp_buffer;
+
+      delete coded_input;
+      delete gzin;
+      delete input;
+    }
+  }
+
+  delete [] temp_buffer;
+  delete [] buffer;
+}
 #endif
 
 // There is no string input, only string output.  Also, it doesn't support
diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h
index d117fe2..4bbc641 100644
--- a/src/google/protobuf/message.h
+++ b/src/google/protobuf/message.h
@@ -123,6 +123,7 @@
 
 #include <google/protobuf/stubs/common.h>
 
+
 namespace google {
 namespace protobuf {
 
diff --git a/src/google/protobuf/repeated_field.cc b/src/google/protobuf/repeated_field.cc
index f7beb11..0937774 100644
--- a/src/google/protobuf/repeated_field.cc
+++ b/src/google/protobuf/repeated_field.cc
@@ -32,11 +32,14 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
+#include <algorithm>
+
 #include <google/protobuf/repeated_field.h>
 #include <google/protobuf/stubs/common.h>
 
 namespace google {
 namespace protobuf {
+
 namespace internal {
 
 void RepeatedPtrFieldBase::Reserve(int new_size) {
@@ -88,8 +91,8 @@
   delete value;
 }
 
+}  // namespace internal
 
-} // namespace internal
 
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h
index cc07fdb..ae96107 100644
--- a/src/google/protobuf/repeated_field.h
+++ b/src/google/protobuf/repeated_field.h
@@ -72,8 +72,11 @@
 class RepeatedField {
  public:
   RepeatedField();
+  RepeatedField(const RepeatedField& other);
   ~RepeatedField();
 
+  RepeatedField& operator=(const RepeatedField& other);
+
   int size() const;
 
   const Element& Get(int index) const;
@@ -90,6 +93,7 @@
   void RemoveLast();
   void Clear();
   void MergeFrom(const RepeatedField& other);
+  void CopyFrom(const RepeatedField& other);
 
   // Reserve space to expand the field to at least the given size.  If the
   // array is grown, it will always be at least doubled in size.
@@ -116,6 +120,7 @@
   // STL-like iterator support
   typedef Element* iterator;
   typedef const Element* const_iterator;
+  typedef Element value_type;
 
   iterator begin();
   const_iterator begin() const;
@@ -127,8 +132,6 @@
   int SpaceUsedExcludingSelf() const;
 
  private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedField);
-
   static const int kInitialSize = 4;
 
   Element* elements_;
@@ -203,6 +206,8 @@
   void Clear();
   template <typename TypeHandler>
   void MergeFrom(const RepeatedPtrFieldBase& other);
+  template <typename TypeHandler>
+  void CopyFrom(const RepeatedPtrFieldBase& other);
 
   void Reserve(int new_size);
 
@@ -300,7 +305,7 @@
   static void Merge(const string& from, string* to) { *to = from; }
 };
 
-class StringTypeHandler : public StringTypeHandlerBase {
+class LIBPROTOBUF_EXPORT StringTypeHandler : public StringTypeHandlerBase {
  public:
   static int SpaceUsed(const string& value)  {
     return sizeof(value) + StringSpaceUsedExcludingSelf(value);
@@ -316,9 +321,11 @@
 class RepeatedPtrField : public internal::RepeatedPtrFieldBase {
  public:
   RepeatedPtrField();
-
+  RepeatedPtrField(const RepeatedPtrField& other);
   ~RepeatedPtrField();
 
+  RepeatedPtrField& operator=(const RepeatedPtrField& other);
+
   int size() const;
 
   const Element& Get(int index) const;
@@ -327,6 +334,7 @@
   void RemoveLast();  // Remove the last element in the array.
   void Clear();
   void MergeFrom(const RepeatedPtrField& other);
+  void CopyFrom(const RepeatedPtrField& other);
 
   // Reserve space to expand the field to at least the given size.  This only
   // resizes the pointer array; it doesn't allocate any objects.  If the
@@ -349,6 +357,7 @@
   // STL-like iterator support
   typedef internal::RepeatedPtrIterator<Element> iterator;
   typedef internal::RepeatedPtrIterator<const Element> const_iterator;
+  typedef Element value_type;
 
   iterator begin();
   const_iterator begin() const;
@@ -365,11 +374,6 @@
   // excluding sizeof(*this).
   int SpaceUsedExcludingSelf() const;
 
-  // The spaced used just by the pointer array, not counting the objects pointed
-  // at.  Returns zero if the array is inlined (i.e. initial_space_ is being
-  // used).
-  int SpaceUsedByArray() const;
-
   // Advanced memory management --------------------------------------
   // When hardcore memory management becomes necessary -- as it often
   // does here at Google -- the following methods may be useful.
@@ -410,9 +414,6 @@
   //   methods on RepeatedPtrFieldBase.
   class TypeHandler;
 
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPtrField);
 };
 
 // implementation ====================================================
@@ -425,6 +426,14 @@
 }
 
 template <typename Element>
+inline RepeatedField<Element>::RepeatedField(const RepeatedField& other)
+  : elements_(initial_space_),
+    current_size_(0),
+    total_size_(kInitialSize) {
+  CopyFrom(other);
+}
+
+template <typename Element>
 RepeatedField<Element>::~RepeatedField() {
   if (elements_ != initial_space_) {
     delete [] elements_;
@@ -432,6 +441,13 @@
 }
 
 template <typename Element>
+inline RepeatedField<Element>&
+RepeatedField<Element>::operator=(const RepeatedField& other) {
+  CopyFrom(other);
+  return *this;
+}
+
+template <typename Element>
 inline int RepeatedField<Element>::size() const {
   return current_size_;
 }
@@ -502,6 +518,12 @@
 }
 
 template <typename Element>
+inline void RepeatedField<Element>::CopyFrom(const RepeatedField& other) {
+  Clear();
+  MergeFrom(other);
+}
+
+template <typename Element>
 inline Element* RepeatedField<Element>::mutable_data() {
   return elements_;
 }
@@ -679,6 +701,12 @@
   }
 }
 
+template <typename TypeHandler>
+inline void RepeatedPtrFieldBase::CopyFrom(const RepeatedPtrFieldBase& other) {
+  RepeatedPtrFieldBase::Clear<TypeHandler>();
+  RepeatedPtrFieldBase::MergeFrom<TypeHandler>(other);
+}
+
 inline int RepeatedPtrFieldBase::Capacity() const {
   return total_size_;
 }
@@ -805,11 +833,24 @@
 inline RepeatedPtrField<Element>::RepeatedPtrField() {}
 
 template <typename Element>
+inline RepeatedPtrField<Element>::RepeatedPtrField(
+    const RepeatedPtrField& other) {
+  CopyFrom(other);
+}
+
+template <typename Element>
 RepeatedPtrField<Element>::~RepeatedPtrField() {
   Destroy<TypeHandler>();
 }
 
 template <typename Element>
+inline RepeatedPtrField<Element>& RepeatedPtrField<Element>::operator=(
+    const RepeatedPtrField& other) {
+  CopyFrom(other);
+  return *this;
+}
+
+template <typename Element>
 inline int RepeatedPtrField<Element>::size() const {
   return RepeatedPtrFieldBase::size();
 }
@@ -846,6 +887,12 @@
 }
 
 template <typename Element>
+inline void RepeatedPtrField<Element>::CopyFrom(
+    const RepeatedPtrField& other) {
+  RepeatedPtrFieldBase::CopyFrom<TypeHandler>(other);
+}
+
+template <typename Element>
 inline Element** RepeatedPtrField<Element>::mutable_data() {
   return RepeatedPtrFieldBase::mutable_data<TypeHandler>();
 }
@@ -944,7 +991,7 @@
   template<typename OtherElement>
   RepeatedPtrIterator(const RepeatedPtrIterator<OtherElement>& other)
       : it_(other.it_) {
-    // Force a compiler error if the other type is not convertable to ours.
+    // Force a compiler error if the other type is not convertible to ours.
     if (false) {
       implicit_cast<Element*, OtherElement*>(0);
     }
diff --git a/src/google/protobuf/repeated_field_unittest.cc b/src/google/protobuf/repeated_field_unittest.cc
index 7c35f60..e7e1e99 100644
--- a/src/google/protobuf/repeated_field_unittest.cc
+++ b/src/google/protobuf/repeated_field_unittest.cc
@@ -232,6 +232,54 @@
   EXPECT_EQ(5, destination.Get(4));
 }
 
+TEST(RepeatedField, CopyFrom) {
+  RepeatedField<int> source, destination;
+
+  source.Add(4);
+  source.Add(5);
+
+  destination.Add(1);
+  destination.Add(2);
+  destination.Add(3);
+
+  destination.CopyFrom(source);
+
+  ASSERT_EQ(2, destination.size());
+
+  EXPECT_EQ(4, destination.Get(0));
+  EXPECT_EQ(5, destination.Get(1));
+}
+
+TEST(RepeatedField, CopyConstruct) {
+  RepeatedField<int> source;
+  source.Add(1);
+  source.Add(2);
+
+  RepeatedField<int> destination(source);
+
+  ASSERT_EQ(2, destination.size());
+  EXPECT_EQ(1, destination.Get(0));
+  EXPECT_EQ(2, destination.Get(1));
+}
+
+TEST(RepeatedField, CopyAssign) {
+  RepeatedField<int> source, destination;
+
+  source.Add(4);
+  source.Add(5);
+
+  destination.Add(1);
+  destination.Add(2);
+  destination.Add(3);
+
+  destination = source;
+
+  ASSERT_EQ(2, destination.size());
+
+  EXPECT_EQ(4, destination.Get(0));
+  EXPECT_EQ(5, destination.Get(1));
+}
+
 TEST(RepeatedField, MutableDataIsMutable) {
   RepeatedField<int> field;
   field.Add(1);
@@ -536,6 +584,55 @@
   EXPECT_EQ("5", destination.Get(4));
 }
 
+TEST(RepeatedPtrField, CopyFrom) {
+  RepeatedPtrField<string> source, destination;
+
+  source.Add()->assign("4");
+  source.Add()->assign("5");
+
+  destination.Add()->assign("1");
+  destination.Add()->assign("2");
+  destination.Add()->assign("3");
+
+  destination.CopyFrom(source);
+
+  ASSERT_EQ(2, destination.size());
+
+  EXPECT_EQ("4", destination.Get(0));
+  EXPECT_EQ("5", destination.Get(1));
+}
+
+TEST(RepeatedPtrField, CopyConstruct) {
+  RepeatedPtrField<string> source;
+
+  source.Add()->assign("1");
+  source.Add()->assign("2");
+
+  RepeatedPtrField<string> destination(source);
+
+  ASSERT_EQ(2, destination.size());
+  EXPECT_EQ("1", destination.Get(0));
+  EXPECT_EQ("2", destination.Get(1));
+}
+
+TEST(RepeatedPtrField, CopyAssign) {
+  RepeatedPtrField<string> source, destination;
+
+  source.Add()->assign("4");
+  source.Add()->assign("5");
+
+  destination.Add()->assign("1");
+  destination.Add()->assign("2");
+  destination.Add()->assign("3");
+
+  destination = source;
+
+  ASSERT_EQ(2, destination.size());
+
+  EXPECT_EQ("4", destination.Get(0));
+  EXPECT_EQ("5", destination.Get(1));
+}
+
 TEST(RepeatedPtrField, MutableDataIsMutable) {
   RepeatedPtrField<string> field;
   *field.Add() = "1";
@@ -564,7 +661,8 @@
 TEST_F(RepeatedFieldIteratorTest, Convertible) {
   RepeatedField<int>::iterator iter = proto_array_.begin();
   RepeatedField<int>::const_iterator c_iter = iter;
-  EXPECT_EQ(0, *c_iter);
+  RepeatedField<int>::value_type value = *c_iter;
+  EXPECT_EQ(0, value);
 }
 
 TEST_F(RepeatedFieldIteratorTest, MutableIteration) {
@@ -613,6 +711,8 @@
 TEST_F(RepeatedPtrFieldIteratorTest, Convertible) {
   RepeatedPtrField<string>::iterator iter = proto_array_.begin();
   RepeatedPtrField<string>::const_iterator c_iter = iter;
+  RepeatedPtrField<string>::value_type value = *c_iter;
+  EXPECT_EQ("foo", value);
 }
 
 TEST_F(RepeatedPtrFieldIteratorTest, MutableIteration) {
diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc
index 137cbce..1494ebd 100644
--- a/src/google/protobuf/text_format.cc
+++ b/src/google/protobuf/text_format.cc
@@ -37,6 +37,7 @@
 #include <stdio.h>
 #include <stack>
 #include <limits>
+#include <vector>
 
 #include <google/protobuf/text_format.h>
 
@@ -118,8 +119,10 @@
   ParserImpl(const Descriptor* root_message_type,
              io::ZeroCopyInputStream* input_stream,
              io::ErrorCollector* error_collector,
+             TextFormat::Finder* finder,
              SingularOverwritePolicy singular_overwrite_policy)
     : error_collector_(error_collector),
+      finder_(finder),
       tokenizer_error_collector_(this),
       tokenizer_(input_stream, &tokenizer_error_collector_),
       root_message_type_(root_message_type),
@@ -249,7 +252,9 @@
       }
       DO(Consume("]"));
 
-      field = reflection->FindKnownExtensionByName(field_name);
+      field = (finder_ != NULL
+               ? finder_->FindExtension(message, field_name)
+               : reflection->FindKnownExtensionByName(field_name));
 
       if (field == NULL) {
         ReportError("Extension \"" + field_name + "\" is not defined or "
@@ -301,9 +306,24 @@
       DO(ConsumeFieldMessage(message, reflection, field));
     } else {
       DO(Consume(":"));
-      DO(ConsumeFieldValue(message, reflection, field));
+      if (field->is_repeated() && TryConsume("[")) {
+        // Short repeated format, e.g.  "foo: [1, 2, 3]"
+        while (true) {
+          DO(ConsumeFieldValue(message, reflection, field));
+          if (TryConsume("]")) {
+            break;
+          }
+          DO(Consume(","));
+        }
+      } else {
+        DO(ConsumeFieldValue(message, reflection, field));
+      }
     }
 
+    // For historical reasons, fields may optionally be separated by commas or
+    // semicolons.
+    TryConsume(";") || TryConsume(",");
+
     if (field->options().deprecated()) {
       ReportWarning("text format contains deprecated field \""
                     + field_name + "\"");
@@ -397,29 +417,46 @@
       }
 
       case FieldDescriptor::CPPTYPE_BOOL: {
-        string value;
-        DO(ConsumeIdentifier(&value));
-
-        if (value == "true") {
-          SET_FIELD(Bool, true);
-        } else if (value == "false") {
-          SET_FIELD(Bool, false);
+        if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) {
+          uint64 value;
+          DO(ConsumeUnsignedInteger(&value, 1));
+          SET_FIELD(Bool, value);
         } else {
-          ReportError("Invalid value for boolean field \"" + field->name()
-                      + "\". Value: \"" + value  + "\".");
-          return false;
+          string value;
+          DO(ConsumeIdentifier(&value));
+          if (value == "true" || value == "t") {
+            SET_FIELD(Bool, true);
+          } else if (value == "false" || value == "f") {
+            SET_FIELD(Bool, false);
+          } else {
+            ReportError("Invalid value for boolean field \"" + field->name()
+                        + "\". Value: \"" + value  + "\".");
+            return false;
+          }
         }
         break;
       }
 
       case FieldDescriptor::CPPTYPE_ENUM: {
         string value;
-        DO(ConsumeIdentifier(&value));
-
-        // Find the enumeration value.
         const EnumDescriptor* enum_type = field->enum_type();
-        const EnumValueDescriptor* enum_value
-            = enum_type->FindValueByName(value);
+        const EnumValueDescriptor* enum_value = NULL;
+
+        if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) {
+          DO(ConsumeIdentifier(&value));
+          // Find the enumeration value.
+          enum_value = enum_type->FindValueByName(value);
+
+        } else if (LookingAt("-") ||
+                   LookingAtType(io::Tokenizer::TYPE_INTEGER)) {
+          int64 int_value;
+          DO(ConsumeSignedInteger(&int_value, kint32max));
+          value = SimpleItoa(int_value);        // for error reporting
+          enum_value = enum_type->FindValueByNumber(int_value);
+        } else {
+          ReportError("Expected integer or identifier.");
+          return false;
+        }
 
         if (enum_value == NULL) {
           ReportError("Unknown enumeration value of \"" + value  + "\" for "
@@ -632,6 +669,7 @@
   };
 
   io::ErrorCollector* error_collector_;
+  TextFormat::Finder* finder_;
   ParserErrorCollector tokenizer_error_collector_;
   io::Tokenizer tokenizer_;
   const Descriptor* root_message_type_;
@@ -765,9 +803,14 @@
 
 // ===========================================================================
 
+TextFormat::Finder::~Finder() {
+}
+
 TextFormat::Parser::Parser()
   : error_collector_(NULL),
-    allow_partial_(false) {}
+    finder_(NULL),
+    allow_partial_(false) {
+}
 
 TextFormat::Parser::~Parser() {}
 
@@ -775,7 +818,7 @@
                                Message* output) {
   output->Clear();
   ParserImpl parser(output->GetDescriptor(), input, error_collector_,
-                    ParserImpl::FORBID_SINGULAR_OVERWRITES);
+                    finder_, ParserImpl::FORBID_SINGULAR_OVERWRITES);
   return MergeUsingImpl(input, output, &parser);
 }
 
@@ -788,7 +831,7 @@
 bool TextFormat::Parser::Merge(io::ZeroCopyInputStream* input,
                                Message* output) {
   ParserImpl parser(output->GetDescriptor(), input, error_collector_,
-                    ParserImpl::ALLOW_SINGULAR_OVERWRITES);
+                    finder_, ParserImpl::ALLOW_SINGULAR_OVERWRITES);
   return MergeUsingImpl(input, output, &parser);
 }
 
@@ -818,7 +861,7 @@
     Message* output) {
   io::ArrayInputStream input_stream(input.data(), input.size());
   ParserImpl parser(output->GetDescriptor(), &input_stream, error_collector_,
-                    ParserImpl::ALLOW_SINGULAR_OVERWRITES);
+                    finder_, ParserImpl::ALLOW_SINGULAR_OVERWRITES);
   return parser.ParseField(field, output);
 }
 
@@ -853,7 +896,7 @@
 TextFormat::Printer::~Printer() {}
 
 bool TextFormat::Printer::PrintToString(const Message& message,
-                                        string* output) {
+                                        string* output) const {
   GOOGLE_DCHECK(output) << "output specified is NULL";
 
   output->clear();
@@ -866,7 +909,7 @@
 
 bool TextFormat::Printer::PrintUnknownFieldsToString(
     const UnknownFieldSet& unknown_fields,
-    string* output) {
+    string* output) const {
   GOOGLE_DCHECK(output) << "output specified is NULL";
 
   output->clear();
@@ -875,7 +918,7 @@
 }
 
 bool TextFormat::Printer::Print(const Message& message,
-                                io::ZeroCopyOutputStream* output) {
+                                io::ZeroCopyOutputStream* output) const {
   TextGenerator generator(output, initial_indent_level_);
 
   Print(message, generator);
@@ -886,7 +929,7 @@
 
 bool TextFormat::Printer::PrintUnknownFields(
     const UnknownFieldSet& unknown_fields,
-    io::ZeroCopyOutputStream* output) {
+    io::ZeroCopyOutputStream* output) const {
   TextGenerator generator(output, initial_indent_level_);
 
   PrintUnknownFields(unknown_fields, generator);
@@ -896,7 +939,7 @@
 }
 
 void TextFormat::Printer::Print(const Message& message,
-                                TextGenerator& generator) {
+                                TextGenerator& generator) const {
   const Reflection* reflection = message.GetReflection();
   vector<const FieldDescriptor*> fields;
   reflection->ListFields(message, &fields);
@@ -910,7 +953,7 @@
     const Message& message,
     const FieldDescriptor* field,
     int index,
-    string* output) {
+    string* output) const {
 
   GOOGLE_DCHECK(output) << "output specified is NULL";
 
@@ -924,7 +967,7 @@
 void TextFormat::Printer::PrintField(const Message& message,
                                      const Reflection* reflection,
                                      const FieldDescriptor* field,
-                                     TextGenerator& generator) {
+                                     TextGenerator& generator) const {
   if (use_short_repeated_primitives_ &&
       field->is_repeated() &&
       field->cpp_type() != FieldDescriptor::CPPTYPE_STRING &&
@@ -980,10 +1023,11 @@
   }
 }
 
-void TextFormat::Printer::PrintShortRepeatedField(const Message& message,
-                                                  const Reflection* reflection,
-                                                  const FieldDescriptor* field,
-                                                  TextGenerator& generator) {
+void TextFormat::Printer::PrintShortRepeatedField(
+    const Message& message,
+    const Reflection* reflection,
+    const FieldDescriptor* field,
+    TextGenerator& generator) const {
   // Print primitive repeated field in short form.
   PrintFieldName(message, reflection, field, generator);
 
@@ -1003,7 +1047,7 @@
 void TextFormat::Printer::PrintFieldName(const Message& message,
                                          const Reflection* reflection,
                                          const FieldDescriptor* field,
-                                         TextGenerator& generator) {
+                                         TextGenerator& generator) const {
   if (field->is_extension()) {
     generator.Print("[");
     // We special-case MessageSet elements for compatibility with proto1.
@@ -1031,7 +1075,7 @@
     const Reflection* reflection,
     const FieldDescriptor* field,
     int index,
-    TextGenerator& generator) {
+    TextGenerator& generator) const {
   GOOGLE_DCHECK(field->is_repeated() || (index == -1))
       << "Index must be -1 for non-repeated fields";
 
@@ -1143,7 +1187,7 @@
 }
 
 void TextFormat::Printer::PrintUnknownFields(
-    const UnknownFieldSet& unknown_fields, TextGenerator& generator) {
+    const UnknownFieldSet& unknown_fields, TextGenerator& generator) const {
   for (int i = 0; i < unknown_fields.field_count(); i++) {
     const UnknownField& field = unknown_fields.field(i);
     string field_number = SimpleItoa(field.number());
diff --git a/src/google/protobuf/text_format.h b/src/google/protobuf/text_format.h
index e78e104..03c0491 100644
--- a/src/google/protobuf/text_format.h
+++ b/src/google/protobuf/text_format.h
@@ -90,20 +90,20 @@
     ~Printer();
 
     // Like TextFormat::Print
-    bool Print(const Message& message, io::ZeroCopyOutputStream* output);
+    bool Print(const Message& message, io::ZeroCopyOutputStream* output) const;
     // Like TextFormat::PrintUnknownFields
     bool PrintUnknownFields(const UnknownFieldSet& unknown_fields,
-                            io::ZeroCopyOutputStream* output);
+                            io::ZeroCopyOutputStream* output) const;
     // Like TextFormat::PrintToString
-    bool PrintToString(const Message& message, string* output);
+    bool PrintToString(const Message& message, string* output) const;
     // Like TextFormat::PrintUnknownFieldsToString
     bool PrintUnknownFieldsToString(const UnknownFieldSet& unknown_fields,
-                                    string* output);
+                                    string* output) const;
     // Like TextFormat::PrintFieldValueToString
     void PrintFieldValueToString(const Message& message,
                                  const FieldDescriptor* field,
                                  int index,
-                                 string* output);
+                                 string* output) const;
 
     // Adjust the initial indent level of all output.  Each indent level is
     // equal to two spaces.
@@ -121,8 +121,7 @@
     //   field_name: [1, 2, 3, 4]
     // instead of printing each value on its own line.  Short format applies
     // only to primitive values -- i.e. everything except strings and
-    // sub-messages/groups.  Note that at present this format is not recognized
-    // by the parser.
+    // sub-messages/groups.
     void SetUseShortRepeatedPrimitives(bool use_short_repeated_primitives) {
       use_short_repeated_primitives_ = use_short_repeated_primitives;
     }
@@ -143,26 +142,26 @@
     // Internal Print method, used for writing to the OutputStream via
     // the TextGenerator class.
     void Print(const Message& message,
-               TextGenerator& generator);
+               TextGenerator& generator) const;
 
     // Print a single field.
     void PrintField(const Message& message,
                     const Reflection* reflection,
                     const FieldDescriptor* field,
-                    TextGenerator& generator);
+                    TextGenerator& generator) const;
 
     // Print a repeated primitive field in short form.
     void PrintShortRepeatedField(const Message& message,
                                  const Reflection* reflection,
                                  const FieldDescriptor* field,
-                                 TextGenerator& generator);
+                                 TextGenerator& generator) const;
 
     // Print the name of a field -- i.e. everything that comes before the
     // ':' for a single name/value pair.
     void PrintFieldName(const Message& message,
                         const Reflection* reflection,
                         const FieldDescriptor* field,
-                        TextGenerator& generator);
+                        TextGenerator& generator) const;
 
     // Outputs a textual representation of the value of the field supplied on
     // the message supplied or the default value if not set.
@@ -170,13 +169,13 @@
                          const Reflection* reflection,
                          const FieldDescriptor* field,
                          int index,
-                         TextGenerator& generator);
+                         TextGenerator& generator) const;
 
     // Print the fields in an UnknownFieldSet.  They are printed by tag number
     // only.  Embedded messages are heuristically identified by attempting to
     // parse them.
     void PrintUnknownFields(const UnknownFieldSet& unknown_fields,
-                            TextGenerator& generator);
+                            TextGenerator& generator) const;
 
     int initial_indent_level_;
 
@@ -207,6 +206,20 @@
                                         const FieldDescriptor* field,
                                         Message* message);
 
+  // Interface that TextFormat::Parser can use to find extensions.
+  // This class may be extended in the future to find more information
+  // like fields, etc.
+  class LIBPROTOBUF_EXPORT Finder {
+   public:
+    virtual ~Finder();
+
+    // Try to find an extension of *message by fully-qualified field
+    // name.  Returns NULL if no extension is known for this name or number.
+    virtual const FieldDescriptor* FindExtension(
+        Message* message,
+        const string& name) const = 0;
+  };
+
   // For more control over parsing, use this class.
   class LIBPROTOBUF_EXPORT Parser {
    public:
@@ -228,6 +241,13 @@
       error_collector_ = error_collector;
     }
 
+    // Set how parser finds extensions.  If NULL (the default), the
+    // parser will use the standard Reflection object associated with
+    // the message being parsed.
+    void SetFinder(Finder* finder) {
+      finder_ = finder;
+    }
+
     // Normally parsing fails if, after parsing, output->IsInitialized()
     // returns false.  Call AllowPartialMessage(true) to skip this check.
     void AllowPartialMessage(bool allow) {
@@ -251,6 +271,7 @@
                         ParserImpl* parser_impl);
 
     io::ErrorCollector* error_collector_;
+    Finder* finder_;
     bool allow_partial_;
   };
 
diff --git a/src/google/protobuf/text_format_unittest.cc b/src/google/protobuf/text_format_unittest.cc
index ddf8ff7..00ea8c3 100644
--- a/src/google/protobuf/text_format_unittest.cc
+++ b/src/google/protobuf/text_format_unittest.cc
@@ -353,6 +353,25 @@
   TestUtil::ExpectAllExtensionsSet(proto_);
 }
 
+TEST_F(TextFormatTest, ParseEnumFieldFromNumber) {
+  // Create a parse string with a numerical value for an enum field.
+  string parse_string = strings::Substitute("optional_nested_enum: $0",
+                                            unittest::TestAllTypes::BAZ);
+  EXPECT_TRUE(TextFormat::ParseFromString(parse_string, &proto_));
+  EXPECT_TRUE(proto_.has_optional_nested_enum());
+  EXPECT_EQ(unittest::TestAllTypes::BAZ, proto_.optional_nested_enum());
+}
+
+TEST_F(TextFormatTest, ParseEnumFieldFromNegativeNumber) {
+  ASSERT_LT(unittest::SPARSE_E, 0);
+  string parse_string = strings::Substitute("sparse_enum: $0",
+                                            unittest::SPARSE_E);
+  unittest::SparseEnumMessage proto;
+  EXPECT_TRUE(TextFormat::ParseFromString(parse_string, &proto));
+  EXPECT_TRUE(proto.has_sparse_enum());
+  EXPECT_EQ(unittest::SPARSE_E, proto.sparse_enum());
+}
+
 TEST_F(TextFormatTest, ParseStringEscape) {
   // Create a parse string with escpaed characters in it.
   string parse_string = "optional_string: "
@@ -406,6 +425,34 @@
   EXPECT_EQ(1.0, proto_.optional_float());
 }
 
+TEST_F(TextFormatTest, ParseShortRepeatedForm) {
+  string parse_string =
+      // Mixed short-form and long-form are simply concatenated.
+      "repeated_int32: 1\n"
+      "repeated_int32: [456, 789]\n"
+      "repeated_nested_enum: [  FOO ,BAR, # comment\n"
+      "                         3]\n"
+      // Note that while the printer won't print repeated strings in short-form,
+      // the parser will accept them.
+      "repeated_string: [ \"foo\", 'bar' ]\n";
+
+  ASSERT_TRUE(TextFormat::ParseFromString(parse_string, &proto_));
+
+  ASSERT_EQ(3, proto_.repeated_int32_size());
+  EXPECT_EQ(1, proto_.repeated_int32(0));
+  EXPECT_EQ(456, proto_.repeated_int32(1));
+  EXPECT_EQ(789, proto_.repeated_int32(2));
+
+  ASSERT_EQ(3, proto_.repeated_nested_enum_size());
+  EXPECT_EQ(unittest::TestAllTypes::FOO, proto_.repeated_nested_enum(0));
+  EXPECT_EQ(unittest::TestAllTypes::BAR, proto_.repeated_nested_enum(1));
+  EXPECT_EQ(unittest::TestAllTypes::BAZ, proto_.repeated_nested_enum(2));
+
+  ASSERT_EQ(2, proto_.repeated_string_size());
+  EXPECT_EQ("foo", proto_.repeated_string(0));
+  EXPECT_EQ("bar", proto_.repeated_string(1));
+}
+
 TEST_F(TextFormatTest, Comments) {
   // Test that comments are ignored.
 
@@ -771,7 +818,12 @@
   // bool
   EXPECT_FIELD(bool, true, "true");
   EXPECT_FIELD(bool, false, "false");
-  EXPECT_INVALID(bool, "1");
+  EXPECT_FIELD(bool, true, "1");
+  EXPECT_FIELD(bool, true, "t");
+  EXPECT_FIELD(bool, false, "0");
+  EXPECT_FIELD(bool, false, "f");
+  EXPECT_INVALID(bool, "2");
+  EXPECT_INVALID(bool, "-0");
   EXPECT_INVALID(bool, "on");
   EXPECT_INVALID(bool, "a");
   EXPECT_INVALID(bool, "True");
@@ -799,7 +851,8 @@
 
   // enum
   EXPECT_FIELD(nested_enum, unittest::TestAllTypes::BAR, "BAR");
-  EXPECT_INVALID(nested_enum, "1");  // number not supported
+  EXPECT_FIELD(nested_enum, unittest::TestAllTypes::BAZ,
+               SimpleItoa(unittest::TestAllTypes::BAZ));
   EXPECT_INVALID(nested_enum, "FOOBAR");
 
   // message
@@ -820,7 +873,7 @@
   ExpectFailure("optional_bool: true\n-5\n", "Expected identifier.",
                 2, 1);
 
-  ExpectFailure("optional_bool: true;\n", "Expected identifier.", 1, 20);
+  ExpectFailure("optional_bool: true!\n", "Expected identifier.", 1, 20);
   ExpectFailure("\"some string\"", "Expected identifier.", 1, 1);
 }
 
@@ -890,7 +943,7 @@
 
   // Invalid values for a boolean field.
   ExpectFailure("optional_bool: \"hello\"\n", "Expected identifier.", 1, 16);
-  ExpectFailure("optional_bool: 5\n", "Expected identifier.", 1, 16);
+  ExpectFailure("optional_bool: 5\n", "Integer out of range.", 1, 16);
   ExpectFailure("optional_bool: -7.5\n", "Expected identifier.", 1, 16);
   ExpectFailure("optional_bool: !\n", "Expected identifier.", 1, 16);
 
@@ -911,12 +964,18 @@
                 1, 17);
 
   // Invalid values for an enumeration field.
-  ExpectFailure("optional_nested_enum: \"hello\"\n", "Expected identifier.",
-                1, 23);
+  ExpectFailure("optional_nested_enum: \"hello\"\n",
+                "Expected integer or identifier.", 1, 23);
 
-  ExpectFailure("optional_nested_enum: 5\n", "Expected identifier.", 1, 23);
-  ExpectFailure("optional_nested_enum: -7.5\n", "Expected identifier.", 1, 23);
-  ExpectFailure("optional_nested_enum: !\n", "Expected identifier.", 1, 23);
+  // Valid token, but enum value is not defined.
+  ExpectFailure("optional_nested_enum: 5\n",
+                "Unknown enumeration value of \"5\" for field "
+                "\"optional_nested_enum\".", 2, 1);
+  // We consume the negative sign, so the error position starts one character
+  // later.
+  ExpectFailure("optional_nested_enum: -7.5\n", "Expected integer.", 1, 24);
+  ExpectFailure("optional_nested_enum: !\n",
+                "Expected integer or identifier.", 1, 23);
 
   ExpectFailure(
       "optional_nested_enum: grah\n",
@@ -986,6 +1045,14 @@
   EXPECT_EQ(2, message.c());
 }
 
+TEST_F(TextFormatParserTest, ExplicitDelimiters) {
+  unittest::TestRequired message;
+  EXPECT_TRUE(TextFormat::ParseFromString("a:1,b:2;c:3", &message));
+  EXPECT_EQ(1, message.a());
+  EXPECT_EQ(2, message.b());
+  EXPECT_EQ(3, message.c());
+}
+
 TEST_F(TextFormatParserTest, PrintErrorsToStderr) {
   vector<string> errors;
 
diff --git a/src/google/protobuf/unittest.proto b/src/google/protobuf/unittest.proto
index d51fa1e..de4425b 100644
--- a/src/google/protobuf/unittest.proto
+++ b/src/google/protobuf/unittest.proto
@@ -35,6 +35,12 @@
 // A proto file we will use for unit testing.
 
 
+// Some generic_services option(s) added automatically.
+// See:  http://go/proto2-generic-services-default
+option cc_generic_services = true;     // auto-added
+option java_generic_services = true;   // auto-added
+option py_generic_services = true;     // auto-added
+
 import "google/protobuf/unittest_import.proto";
 
 // We don't put this in a package within proto2 because we need to make sure
@@ -489,6 +495,10 @@
   optional float nan_float = 19 [default = nan];
 }
 
+message SparseEnumMessage {
+  optional TestSparseEnum sparse_enum = 1;
+}
+
 // Test String and Bytes: string is for valid UTF-8 strings
 message OneString {
   optional string data = 1;
@@ -598,6 +608,7 @@
   repeated uint64  repeated_uint64  = 262143;
 }
 
+
 // Test that RPC services work.
 message FooRequest  {}
 message FooResponse {}
diff --git a/src/google/protobuf/unittest_custom_options.proto b/src/google/protobuf/unittest_custom_options.proto
index b6ee03d..a610785 100644
--- a/src/google/protobuf/unittest_custom_options.proto
+++ b/src/google/protobuf/unittest_custom_options.proto
@@ -35,6 +35,12 @@
 // A proto file used to test the "custom options" feature of proto2.
 
 
+// Some generic_services option(s) added automatically.
+// See:  http://go/proto2-generic-services-default
+option cc_generic_services = true;     // auto-added
+option java_generic_services = true;   // auto-added
+option py_generic_services = true;
+
 // A custom file option (defined below).
 option (file_opt1) = 9876543210;
 
@@ -273,3 +279,88 @@
   option (complex_opt3).complexoptiontype5.plugh = 22;
   option (complexopt6).xyzzy = 24;
 }
+
+// ------------------------------------------------------
+// Definitions for testing aggregate option parsing.
+// See descriptor_unittest.cc.
+
+message AggregateMessageSet {
+  option message_set_wire_format = true;
+  extensions 4 to max;
+}
+
+message AggregateMessageSetElement {
+  extend AggregateMessageSet {
+    optional AggregateMessageSetElement message_set_extension = 15447542;
+  }
+  optional string s = 1;
+}
+
+// A helper type used to test aggregate option parsing
+message Aggregate {
+  optional int32 i = 1;
+  optional string s = 2;
+
+  // A nested object
+  optional Aggregate sub = 3;
+
+  // To test the parsing of extensions inside aggregate values
+  optional google.protobuf.FileOptions file = 4;
+  extend google.protobuf.FileOptions {
+    optional Aggregate nested = 15476903;
+  }
+
+  // An embedded message set
+  optional AggregateMessageSet mset = 5;
+}
+
+// Allow Aggregate to be used as an option at all possible locations
+// in the .proto grammer.
+extend google.protobuf.FileOptions      { optional Aggregate fileopt    = 15478479; }
+extend google.protobuf.MessageOptions   { optional Aggregate msgopt     = 15480088; }
+extend google.protobuf.FieldOptions     { optional Aggregate fieldopt   = 15481374; }
+extend google.protobuf.EnumOptions      { optional Aggregate enumopt    = 15483218; }
+extend google.protobuf.EnumValueOptions { optional Aggregate enumvalopt = 15486921; }
+extend google.protobuf.ServiceOptions   { optional Aggregate serviceopt = 15497145; }
+extend google.protobuf.MethodOptions    { optional Aggregate methodopt  = 15512713; }
+
+// Try using AggregateOption at different points in the proto grammar
+option (fileopt) = {
+  s: 'FileAnnotation'
+  // Also test the handling of comments
+  /* of both types */ i: 100
+
+  sub { s: 'NestedFileAnnotation' }
+
+  // Include a google.protobuf.FileOptions and recursively extend it with
+  // another fileopt.
+  file {
+    [protobuf_unittest.fileopt] {
+      s:'FileExtensionAnnotation'
+    }
+  }
+
+  // A message set inside an option value
+  mset {
+    [protobuf_unittest.AggregateMessageSetElement.message_set_extension] {
+      s: 'EmbeddedMessageSetElement'
+    }
+  }
+};
+
+message AggregateMessage {
+  option (msgopt) = { i:101 s:'MessageAnnotation' };
+  optional int32 fieldname = 1 [(fieldopt) = { s:'FieldAnnotation' }];
+}
+
+service AggregateService {
+  option (serviceopt) = { s:'ServiceAnnotation' };
+  rpc Method (AggregateMessage) returns (AggregateMessage) {
+    option (methodopt) = { s:'MethodAnnotation' };
+  }
+}
+
+enum AggregateEnum {
+  option (enumopt) = { s:'EnumAnnotation' };
+  VALUE = 1 [(enumvalopt) = { s:'EnumValueAnnotation' }];
+}
diff --git a/src/google/protobuf/unittest_no_generic_services.proto b/src/google/protobuf/unittest_no_generic_services.proto
index fcae421..cffb412 100644
--- a/src/google/protobuf/unittest_no_generic_services.proto
+++ b/src/google/protobuf/unittest_no_generic_services.proto
@@ -32,9 +32,7 @@
 
 package google.protobuf.no_generic_services_test;
 
-option cc_generic_services = false;
-option java_generic_services = false;
-option py_generic_services = false;
+// *_generic_services are false by default.
 
 message TestMessage {
   optional int32 a = 1;
diff --git a/src/google/protobuf/wire_format_lite_inl.h b/src/google/protobuf/wire_format_lite_inl.h
index d7b2c30..a461a6c 100644
--- a/src/google/protobuf/wire_format_lite_inl.h
+++ b/src/google/protobuf/wire_format_lite_inl.h
@@ -368,12 +368,24 @@
   return true;
 }
 
-template<typename MessageType>
-inline bool WireFormatLite::ReadGroupNoVirtual(int field_number,
-                                               io::CodedInputStream* input,
-                                               MessageType* value) {
+// We name the template parameter something long and extremely unlikely to occur
+// elsewhere because a *qualified* member access expression designed to avoid
+// virtual dispatch, C++03 [basic.lookup.classref] 3.4.5/4 requires that the
+// name of the qualifying class to be looked up both in the context of the full
+// expression (finding the template parameter) and in the context of the object
+// whose member we are accessing. This could potentially find a nested type
+// within that object. The standard goes on to require these names to refer to
+// the same entity, which this collision would violate. The lack of a safe way
+// to avoid this collision appears to be a defect in the standard, but until it
+// is corrected, we choose the name to avoid accidental collisions.
+template<typename MessageType_WorkAroundCppLookupDefect>
+inline bool WireFormatLite::ReadGroupNoVirtual(
+    int field_number, io::CodedInputStream* input,
+    MessageType_WorkAroundCppLookupDefect* value) {
   if (!input->IncrementRecursionDepth()) return false;
-  if (!value->MessageType::MergePartialFromCodedStream(input)) return false;
+  if (!value->
+      MessageType_WorkAroundCppLookupDefect::MergePartialFromCodedStream(input))
+    return false;
   input->DecrementRecursionDepth();
   // Make sure the last thing read was an end tag for this group.
   if (!input->LastTagWas(MakeTag(field_number, WIRETYPE_END_GROUP))) {
@@ -381,14 +393,16 @@
   }
   return true;
 }
-template<typename MessageType>
-inline bool WireFormatLite::ReadMessageNoVirtual(io::CodedInputStream* input,
-                                                 MessageType* value) {
+template<typename MessageType_WorkAroundCppLookupDefect>
+inline bool WireFormatLite::ReadMessageNoVirtual(
+    io::CodedInputStream* input, MessageType_WorkAroundCppLookupDefect* value) {
   uint32 length;
   if (!input->ReadVarint32(&length)) return false;
   if (!input->IncrementRecursionDepth()) return false;
   io::CodedInputStream::Limit limit = input->PushLimit(length);
-  if (!value->MessageType::MergePartialFromCodedStream(input)) return false;
+  if (!value->
+      MessageType_WorkAroundCppLookupDefect::MergePartialFromCodedStream(input))
+    return false;
   // Make sure that parsing stopped when the limit was hit, not at an endgroup
   // tag.
   if (!input->ConsumedEntireMessage()) return false;
@@ -461,21 +475,24 @@
   output->WriteVarint32SignExtended(value);
 }
 
-template<typename MessageType>
-inline void WireFormatLite::WriteGroupNoVirtual(int field_number,
-                                                const MessageType& value,
-                                                io::CodedOutputStream* output) {
+// See comment on ReadGroupNoVirtual to understand the need for this template
+// parameter name.
+template<typename MessageType_WorkAroundCppLookupDefect>
+inline void WireFormatLite::WriteGroupNoVirtual(
+    int field_number, const MessageType_WorkAroundCppLookupDefect& value,
+    io::CodedOutputStream* output) {
   WriteTag(field_number, WIRETYPE_START_GROUP, output);
-  value.MessageType::SerializeWithCachedSizes(output);
+  value.MessageType_WorkAroundCppLookupDefect::SerializeWithCachedSizes(output);
   WriteTag(field_number, WIRETYPE_END_GROUP, output);
 }
-template<typename MessageType>
-inline void WireFormatLite::WriteMessageNoVirtual(int field_number,
-                                                const MessageType& value,
-                                                io::CodedOutputStream* output) {
+template<typename MessageType_WorkAroundCppLookupDefect>
+inline void WireFormatLite::WriteMessageNoVirtual(
+    int field_number, const MessageType_WorkAroundCppLookupDefect& value,
+    io::CodedOutputStream* output) {
   WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
-  output->WriteVarint32(value.MessageType::GetCachedSize());
-  value.MessageType::SerializeWithCachedSizes(output);
+  output->WriteVarint32(
+      value.MessageType_WorkAroundCppLookupDefect::GetCachedSize());
+  value.MessageType_WorkAroundCppLookupDefect::SerializeWithCachedSizes(output);
 }
 
 // ===================================================================
@@ -672,20 +689,26 @@
   return value.SerializeWithCachedSizesToArray(target);
 }
 
-template<typename MessageType>
+// See comment on ReadGroupNoVirtual to understand the need for this template
+// parameter name.
+template<typename MessageType_WorkAroundCppLookupDefect>
 inline uint8* WireFormatLite::WriteGroupNoVirtualToArray(
-    int field_number, const MessageType& value, uint8* target) {
+    int field_number, const MessageType_WorkAroundCppLookupDefect& value,
+    uint8* target) {
   target = WriteTagToArray(field_number, WIRETYPE_START_GROUP, target);
-  target = value.MessageType::SerializeWithCachedSizesToArray(target);
+  target = value.MessageType_WorkAroundCppLookupDefect
+      ::SerializeWithCachedSizesToArray(target);
   return WriteTagToArray(field_number, WIRETYPE_END_GROUP, target);
 }
-template<typename MessageType>
+template<typename MessageType_WorkAroundCppLookupDefect>
 inline uint8* WireFormatLite::WriteMessageNoVirtualToArray(
-    int field_number, const MessageType& value, uint8* target) {
+    int field_number, const MessageType_WorkAroundCppLookupDefect& value,
+    uint8* target) {
   target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target);
   target = io::CodedOutputStream::WriteVarint32ToArray(
-    value.MessageType::GetCachedSize(), target);
-  return value.MessageType::SerializeWithCachedSizesToArray(target);
+    value.MessageType_WorkAroundCppLookupDefect::GetCachedSize(), target);
+  return value.MessageType_WorkAroundCppLookupDefect
+      ::SerializeWithCachedSizesToArray(target);
 }
 
 // ===================================================================
@@ -730,13 +753,17 @@
   return io::CodedOutputStream::VarintSize32(size) + size;
 }
 
-template<typename MessageType>
-inline int WireFormatLite::GroupSizeNoVirtual(const MessageType& value) {
-  return value.MessageType::ByteSize();
+// See comment on ReadGroupNoVirtual to understand the need for this template
+// parameter name.
+template<typename MessageType_WorkAroundCppLookupDefect>
+inline int WireFormatLite::GroupSizeNoVirtual(
+    const MessageType_WorkAroundCppLookupDefect& value) {
+  return value.MessageType_WorkAroundCppLookupDefect::ByteSize();
 }
-template<typename MessageType>
-inline int WireFormatLite::MessageSizeNoVirtual(const MessageType& value) {
-  int size = value.MessageType::ByteSize();
+template<typename MessageType_WorkAroundCppLookupDefect>
+inline int WireFormatLite::MessageSizeNoVirtual(
+    const MessageType_WorkAroundCppLookupDefect& value) {
+  int size = value.MessageType_WorkAroundCppLookupDefect::ByteSize();
   return io::CodedOutputStream::VarintSize32(size) + size;
 }