Integrate google internal changes.
diff --git a/src/google/protobuf/any.cc b/src/google/protobuf/any.cc
index f3ca06b..f7b1d31 100644
--- a/src/google/protobuf/any.cc
+++ b/src/google/protobuf/any.cc
@@ -35,10 +35,15 @@
 namespace internal {
 
 namespace {
-string GetTypeUrl(const Descriptor* message) {
-  return string(kTypeGoogleApisComPrefix) + message->full_name();
+string GetTypeUrl(const Descriptor* message,
+                  const string& type_url_prefix) {
+  if (!type_url_prefix.empty() &&
+      type_url_prefix[type_url_prefix.size() - 1] == '/') {
+    return type_url_prefix + message->full_name();
+  } else {
+    return type_url_prefix + "/" + message->full_name();
+  }
 }
-
 }  // namespace
 
 const char kAnyFullTypeName[] = "google.protobuf.Any";
@@ -50,8 +55,13 @@
 }
 
 void AnyMetadata::PackFrom(const Message& message) {
+  PackFrom(message, kTypeGoogleApisComPrefix);
+}
+
+void AnyMetadata::PackFrom(const Message& message,
+                           const string& type_url_prefix) {
   type_url_->SetNoArena(&::google::protobuf::internal::GetEmptyString(),
-                        GetTypeUrl(message.GetDescriptor()));
+                        GetTypeUrl(message.GetDescriptor(), type_url_prefix));
   message.SerializeToString(value_->MutableNoArena(
       &::google::protobuf::internal::GetEmptyStringAlreadyInited()));
 }
@@ -67,30 +77,20 @@
 bool AnyMetadata::InternalIs(const Descriptor* descriptor) const {
   const string type_url = type_url_->GetNoArena(
              &::google::protobuf::internal::GetEmptyString());
-  const string full_name = descriptor->full_name();
-  if (type_url.length() < full_name.length()) {
-      return false;
+  string full_name;
+  if (!ParseAnyTypeUrl(type_url, &full_name)) {
+    return false;
   }
-  return (0 == type_url.compare(
-    type_url.length() - full_name.length(),
-    full_name.length(),
-    full_name));
+  return full_name == descriptor->full_name();
 }
 
 bool ParseAnyTypeUrl(const string& type_url, string* full_type_name) {
-  static const char* prefix[] = {
-    kTypeGoogleApisComPrefix,
-    kTypeGoogleProdComPrefix
-  };
-  for (int i = 0; i < 2; i++) {
-    const int prefix_len = strlen(prefix[i]);
-    if (strncmp(type_url.c_str(), prefix[i], prefix_len) == 0) {
-      full_type_name->assign(type_url.data() + prefix_len,
-                             type_url.size() - prefix_len);
-      return true;
-    }
+  size_t pos = type_url.find_last_of("/");
+  if (pos == string::npos || pos + 1 == type_url.size()) {
+    return false;
   }
-  return false;
+  *full_type_name = type_url.substr(pos + 1);
+  return true;
 }
 
 
diff --git a/src/google/protobuf/any.h b/src/google/protobuf/any.h
index c8dbef1..04e5416 100644
--- a/src/google/protobuf/any.h
+++ b/src/google/protobuf/any.h
@@ -50,10 +50,26 @@
   // AnyMetadata does not take ownership of "type_url" and "value".
   AnyMetadata(UrlType* type_url, ValueType* value);
 
+  // Packs a message using the default type URL prefix: "type.googleapis.com".
+  // The resulted type URL will be "type.googleapis.com/<message_full_name>".
   void PackFrom(const Message& message);
+  // Packs a message using the given type URL prefix. The type URL will be
+  // constructed by concatenating the message type's full name to the prefix
+  // with an optional "/" separator if the prefix doesn't already end up "/".
+  // For example, both PackFrom(message, "type.googleapis.com") and
+  // PackFrom(message, "type.googleapis.com/") yield the same result type
+  // URL: "type.googleapis.com/<message_full_name>".
+  void PackFrom(const Message& message, const string& type_url_prefix);
 
+  // Unpacks the payload into the given message. Returns false if the message's
+  // type doesn't match the type specified in the type URL (i.e., the full
+  // name after the last "/" of the type URL doesn't match the message's actaul
+  // full name) or parsing the payload has failed.
   bool UnpackTo(Message* message) const;
 
+  // Checks whether the type specified in the type URL matches the given type.
+  // A type is consdiered matching if its full name matches the full name after
+  // the last "/" in the type URL.
   template<typename T>
   bool Is() const {
     return InternalIs(T::default_instance().GetDescriptor());
diff --git a/src/google/protobuf/any.pb.cc b/src/google/protobuf/any.pb.cc
index 0bf523b..e8878ba 100644
--- a/src/google/protobuf/any.pb.cc
+++ b/src/google/protobuf/any.pb.cc
@@ -83,9 +83,10 @@
   ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
     "\n\031google/protobuf/any.proto\022\017google.prot"
     "obuf\"&\n\003Any\022\020\n\010type_url\030\001 \001(\t\022\r\n\005value\030\002"
-    " \001(\014BK\n\023com.google.protobufB\010AnyProtoP\001\240"
-    "\001\001\242\002\003GPB\252\002\036Google.Protobuf.WellKnownType"
-    "sb\006proto3", 169);
+    " \001(\014Br\n\023com.google.protobufB\010AnyProtoP\001Z"
+    "%github.com/golang/protobuf/ptypes/any\240\001"
+    "\001\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTypes"
+    "b\006proto3", 208);
   ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
     "google/protobuf/any.proto", &protobuf_RegisterTypes);
   Any::default_instance_ = new Any();
@@ -116,6 +117,11 @@
   _any_metadata_.PackFrom(message);
 }
 
+void Any::PackFrom(const ::google::protobuf::Message& message,
+                           const ::std::string& type_url_prefix) {
+  _any_metadata_.PackFrom(message, type_url_prefix);
+}
+
 bool Any::UnpackTo(::google::protobuf::Message* message) const {
   return _any_metadata_.UnpackTo(message);
 }
diff --git a/src/google/protobuf/any.pb.h b/src/google/protobuf/any.pb.h
index 97982ec..82c70ad 100644
--- a/src/google/protobuf/any.pb.h
+++ b/src/google/protobuf/any.pb.h
@@ -60,6 +60,8 @@
   // implements Any -----------------------------------------------
 
   void PackFrom(const ::google::protobuf::Message& message);
+  void PackFrom(const ::google::protobuf::Message& message,
+                const ::std::string& type_url_prefix);
   bool UnpackTo(::google::protobuf::Message* message) const;
   template<typename T> bool Is() const {
     return _any_metadata_.Is<T>();
diff --git a/src/google/protobuf/any.proto b/src/google/protobuf/any.proto
index e8a18bc..47d288c 100644
--- a/src/google/protobuf/any.proto
+++ b/src/google/protobuf/any.proto
@@ -33,14 +33,43 @@
 package google.protobuf;
 
 option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option go_package = "github.com/golang/protobuf/ptypes/any";
 option java_package = "com.google.protobuf";
 option java_outer_classname = "AnyProto";
 option java_multiple_files = true;
 option java_generate_equals_and_hash = true;
 option objc_class_prefix = "GPB";
 
-// `Any` contains an arbitrary serialized message along with a URL
-// that describes the type of the serialized message.
+// `Any` contains an arbitrary serialized protocol buffer message along with a
+// URL that describes the type of the serialized message.
+//
+// Protobuf library provides support to pack/unpack Any values in the form
+// of utility functions or additional generated methods of the Any type.
+//
+// Example 1: Pack and unpack a message in C++.
+//
+//     Foo foo = ...;
+//     Any any;
+//     any.PackFrom(foo);
+//     ...
+//     if (any.UnpackTo(&foo)) {
+//       ...
+//     }
+//
+// Example 2: Pack and unpack a message in Java.
+//
+//     Foo foo = ...;
+//     Any any = Any.pack(foo);
+//     ...
+//     if (any.is(Foo.class)) {
+//       foo = any.unpack(Foo.class);
+//     }
+//
+// The pack methods provided by protobuf library will by default use
+// 'type.googleapis.com/full.type.name' as the type URL and the unpack
+// methods only use the fully qualified type name after the last '/'
+// in the type URL, for example "foo.bar.com/x/y.z" will yield type
+// name "y.z".
 //
 //
 // JSON
@@ -73,7 +102,7 @@
 //
 message Any {
   // A URL/resource name whose content describes the type of the
-  // serialized message.
+  // serialized protocol buffer message.
   //
   // For URLs which use the schema `http`, `https`, or no schema, the
   // following restrictions and interpretations apply:
@@ -94,6 +123,6 @@
   //
   string type_url = 1;
 
-  // Must be valid serialized data of the above specified type.
+  // Must be a valid serialized protocol buffer of the above specified type.
   bytes value = 2;
 }
diff --git a/src/google/protobuf/arena.cc b/src/google/protobuf/arena.cc
index cd0b21a..e856f5b 100755
--- a/src/google/protobuf/arena.cc
+++ b/src/google/protobuf/arena.cc
@@ -37,6 +37,7 @@
 namespace google {
 namespace protobuf {
 
+
 google::protobuf::internal::SequenceNumber Arena::lifecycle_id_generator_;
 #if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
 Arena::ThreadCache& Arena::thread_cache() {
diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h
index 5ad94fa..9ab0a0f 100644
--- a/src/google/protobuf/arena.h
+++ b/src/google/protobuf/arena.h
@@ -56,6 +56,7 @@
 #include <google/protobuf/stubs/mutex.h>
 #include <google/protobuf/stubs/type_traits.h>
 
+
 namespace google {
 namespace protobuf {
 
@@ -230,6 +231,7 @@
   // if it was passed in.
   ~Arena();
 
+
   // API to create proto2 message objects on the arena. If the arena passed in
   // is NULL, then a heap allocated object is returned. Type T must be a message
   // defined in a .proto file with cc_enable_arenas set to true, otherwise a
@@ -507,11 +509,11 @@
   //
   // This is inside Arena because only Arena has the friend relationships
   // necessary to see the underlying generated code traits.
-  template<typename T>
-  struct is_arena_constructable :
-      public google::protobuf::internal::integral_constant<bool,
-          sizeof(InternalIsArenaConstructableHelper::ArenaConstructable<
-                 const T>(static_cast<const T*>(0))) == sizeof(char)> {
+  template <typename T>
+  struct is_arena_constructable
+      : public google::protobuf::internal::integral_constant<
+            bool, sizeof(InternalIsArenaConstructableHelper::ArenaConstructable<
+                         const T>(static_cast<const T*>(0))) == sizeof(char)> {
   };
 
  private:
diff --git a/src/google/protobuf/arena_nc_test.py b/src/google/protobuf/arena_nc_test.py
index 87a69b2..56a7dd0 100644
--- a/src/google/protobuf/arena_nc_test.py
+++ b/src/google/protobuf/arena_nc_test.py
@@ -35,7 +35,7 @@
 import unittest
 
 from google3.testing.pybase import fake_target_util
-import unittest
+from google3.testing.pybase import unittest
 
 
 class ArenaNcTest(unittest.TestCase):
diff --git a/src/google/protobuf/arenastring.h b/src/google/protobuf/arenastring.h
index e2e2f25..590ffce 100755
--- a/src/google/protobuf/arenastring.h
+++ b/src/google/protobuf/arenastring.h
@@ -134,7 +134,8 @@
   // UnsafeArenaRelease() on another field of a message in the same arena. Used
   // to implement unsafe_arena_set_allocated_<field> in generated classes.
   inline void UnsafeArenaSetAllocated(const ::std::string* default_value,
-                                      ::std::string* value, ::google::protobuf::Arena* /* arena */) {
+                                      ::std::string* value,
+                                      ::google::protobuf::Arena* /* arena */) {
     if (value != NULL) {
       ptr_ = value;
     } else {
diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc
index 3a816b0..87843f6 100644
--- a/src/google/protobuf/compiler/command_line_interface.cc
+++ b/src/google/protobuf/compiler/command_line_interface.cc
@@ -49,7 +49,7 @@
 #include <iostream>
 #include <ctype.h>
 
-#ifdef GOOGLE_PROTOBUF_ARCH_SPARC 
+#ifdef GOOGLE_PROTOBUF_ARCH_SPARC
 #include <limits.h> //For PATH_MAX
 #endif
 
diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc
index dda007d..e3dd229 100644
--- a/src/google/protobuf/compiler/command_line_interface_unittest.cc
+++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc
@@ -63,13 +63,13 @@
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
 
-namespace google {
-namespace protobuf {
-namespace compiler {
 
 // Disable the whole test when we use tcmalloc for "draconian" heap checks, in
 // which case tcmalloc will print warnings that fail the plugin tests.
 #if !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN
+namespace google {
+namespace protobuf {
+namespace compiler {
 
 #if defined(_WIN32)
 #ifndef STDIN_FILENO
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.cc b/src/google/protobuf/compiler/cpp/cpp_enum.cc
index 5ee6f00..415ae60 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum.cc
@@ -69,11 +69,12 @@
 
 EnumGenerator::~EnumGenerator() {}
 
-void EnumGenerator::FillForwardDeclaration(set<string>* enum_names) {
+void EnumGenerator::FillForwardDeclaration(
+    map<string, const EnumDescriptor*>* enum_names) {
   if (!options_.proto_h) {
     return;
   }
-  enum_names->insert(classname_);
+  (*enum_names)[classname_] = descriptor_;
 }
 
 void EnumGenerator::GenerateDefinition(io::Printer* printer) {
@@ -83,6 +84,7 @@
   vars["enumbase"] = classname_ + (options_.proto_h ? " : int" : "");
 
   printer->Print(vars, "enum $enumbase$ {\n");
+  printer->Annotate("enumbase", descriptor_);
   printer->Indent();
 
   const EnumValueDescriptor* min_value = descriptor_->value(0);
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.h b/src/google/protobuf/compiler/cpp/cpp_enum.h
index f3aa72e..61e4034 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum.h
+++ b/src/google/protobuf/compiler/cpp/cpp_enum.h
@@ -64,8 +64,10 @@
   // Fills the name to use when declaring the enum. This is for use when
   // generating other .proto.h files. This code should be placed within the
   // enum's package namespace, but NOT within any class, even for nested
-  // enums.
-  void FillForwardDeclaration(set<string>* enum_names);
+  // enums. A given key in enum_names will map from an enum class name to the
+  // EnumDescriptor that was responsible for its inclusion in the map. This can
+  // be used to associate the descriptor with the code generated for it.
+  void FillForwardDeclaration(map<string, const EnumDescriptor*>* enum_names);
 
   // Generate header code defining the enum.  This code should be placed
   // within the enum's package namespace, but NOT within any class, even for
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc
index 37e4bae..d48171b 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_file.cc
@@ -94,7 +94,8 @@
 
 FileGenerator::~FileGenerator() {}
 
-void FileGenerator::GenerateProtoHeader(io::Printer* printer) {
+void FileGenerator::GenerateProtoHeader(io::Printer* printer,
+                                        const string& info_path) {
   if (!options_.proto_h) {
     return;
   }
@@ -114,6 +115,8 @@
       "dependency", dependency);
   }
 
+  GenerateMetadataPragma(printer, info_path);
+
   printer->Print(
     "// @@protoc_insertion_point(includes)\n");
 
@@ -167,7 +170,8 @@
   GenerateBottomHeaderGuard(printer, filename_identifier);
 }
 
-void FileGenerator::GeneratePBHeader(io::Printer* printer) {
+void FileGenerator::GeneratePBHeader(io::Printer* printer,
+                                     const string& info_path) {
   string filename_identifier =
       FilenameIdentifier(file_->name() + (options_.proto_h ? ".pb.h" : ""));
   GenerateTopHeaderGuard(printer, filename_identifier);
@@ -179,6 +183,7 @@
     GenerateLibraryIncludes(printer);
   }
   GenerateDependencyIncludes(printer);
+  GenerateMetadataPragma(printer, info_path);
 
   printer->Print(
     "// @@protoc_insertion_point(includes)\n");
@@ -237,7 +242,7 @@
 }
 
 void FileGenerator::GenerateSource(io::Printer* printer) {
-  bool well_known = IsWellKnownMessage(file_);
+  const bool use_system_include = IsWellKnownMessage(file_);
   string header =
       StripProto(file_->name()) + (options_.proto_h ? ".proto.h" : ".pb.h");
   printer->Print(
@@ -258,8 +263,8 @@
     "#include <google/protobuf/wire_format_lite_inl.h>\n",
     "filename", file_->name(),
     "header", header,
-    "left", well_known ? "<" : "\"",
-    "right", well_known ? ">" : "\"");
+    "left", use_system_include ? "<" : "\"",
+    "right", use_system_include ? ">" : "\"");
 
   // Unknown fields implementation in lite mode uses StringOutputStream
   if (!UseUnknownFieldSet(file_) && file_->message_type_count() > 0) {
@@ -401,20 +406,24 @@
     return ns;
   }
 
-  set<string>& classes() { return classes_; }
-  set<string>& enums() { return enums_; }
+  map<string, const Descriptor*>& classes() { return classes_; }
+  map<string, const EnumDescriptor*>& enums() { return enums_; }
 
   void Print(io::Printer* printer) const {
-    for (set<string>::const_iterator it = enums_.begin(), end = enums_.end();
+    for (map<string, const EnumDescriptor *>::const_iterator
+             it = enums_.begin(),
+             end = enums_.end();
          it != end; ++it) {
-      printer->Print("enum $enumname$ : int;\n"
-                     "bool $enumname$_IsValid(int value);\n",
-                     "enumname", it->c_str());
+      printer->Print("enum $enumname$ : int;\n", "enumname", it->first);
+      printer->Annotate("enumname", it->second);
+      printer->Print("bool $enumname$_IsValid(int value);\n", "enumname",
+                     it->first);
     }
-    for (set<string>::const_iterator it = classes_.begin(),
-                                     end = classes_.end();
+    for (map<string, const Descriptor *>::const_iterator it = classes_.begin(),
+                                                         end = classes_.end();
          it != end; ++it) {
-      printer->Print("class $classname$;\n", "classname", it->c_str());
+      printer->Print("class $classname$;\n", "classname", it->first);
+      printer->Annotate("classname", it->second);
     }
     for (map<string, ForwardDeclarations *>::const_iterator
              it = namespaces_.begin(),
@@ -431,8 +440,8 @@
 
  private:
   map<string, ForwardDeclarations*> namespaces_;
-  set<string> classes_;
-  set<string> enums_;
+  map<string, const Descriptor*> classes_;
+  map<string, const EnumDescriptor*> enums_;
 };
 
 void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
@@ -854,6 +863,19 @@
   }
 }
 
+void FileGenerator::GenerateMetadataPragma(io::Printer* printer,
+                                           const string& info_path) {
+  if (!info_path.empty() && !options_.annotation_pragma_name.empty() &&
+      !options_.annotation_guard_name.empty()) {
+    printer->Print(
+        "#ifdef $guard$\n"
+        "#pragma $pragma$ \"$info_path$\"\n"
+        "#endif  // $guard$\n",
+        "guard", options_.annotation_guard_name, "pragma",
+        options_.annotation_pragma_name, "info_path", info_path);
+  }
+}
+
 void FileGenerator::GenerateDependencyIncludes(io::Printer* printer) {
   set<string> public_import_names;
   for (int i = 0; i < file_->public_dependency_count(); i++) {
@@ -861,16 +883,17 @@
   }
 
   for (int i = 0; i < file_->dependency_count(); i++) {
-    bool well_known = IsWellKnownMessage(file_->dependency(i));
+    const bool use_system_include = IsWellKnownMessage(file_->dependency(i));
     const string& name = file_->dependency(i)->name();
     bool public_import = (public_import_names.count(name) != 0);
 
+
     printer->Print(
       "#include $left$$dependency$.pb.h$right$$iwyu$\n",
       "dependency", StripProto(name),
       "iwyu", (public_import) ? "  // IWYU pragma: export" : "",
-      "left", well_known ? "<" : "\"",
-      "right", well_known ? ">" : "\"");
+      "left", use_system_include ? "<" : "\"",
+      "right", use_system_include ? ">" : "\"");
   }
 }
 
@@ -897,13 +920,15 @@
 }
 
 void FileGenerator::GenerateMessageForwardDeclarations(io::Printer* printer) {
-  set<string> classes;
+  map<string, const Descriptor*> classes;
   for (int i = 0; i < file_->message_type_count(); i++) {
     message_generators_[i]->FillMessageForwardDeclarations(&classes);
   }
-  for (set<string>::const_iterator it = classes.begin(), end = classes.end();
+  for (map<string, const Descriptor *>::const_iterator it = classes.begin(),
+                                                       end = classes.end();
        it != end; ++it) {
-    printer->Print("class $classname$;\n", "classname", it->c_str());
+    printer->Print("class $classname$;\n", "classname", it->first);
+    printer->Annotate("classname", it->second);
   }
 }
 
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.h b/src/google/protobuf/compiler/cpp/cpp_file.h
index 29cdaea..ebe990c 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.h
+++ b/src/google/protobuf/compiler/cpp/cpp_file.h
@@ -69,8 +69,14 @@
                          const Options& options);
   ~FileGenerator();
 
-  void GenerateProtoHeader(io::Printer* printer);
-  void GeneratePBHeader(io::Printer* printer);
+  // info_path, if non-empty, should be the path (relative to printer's output)
+  // to the metadata file describing this proto header.
+  void GenerateProtoHeader(io::Printer* printer,
+                           const string& info_path);
+  // info_path, if non-empty, should be the path (relative to printer's output)
+  // to the metadata file describing this PB header.
+  void GeneratePBHeader(io::Printer* printer,
+                        const string& info_path);
   void GenerateSource(io::Printer* printer);
 
  private:
@@ -102,6 +108,10 @@
   void GenerateLibraryIncludes(io::Printer* printer);
   void GenerateDependencyIncludes(io::Printer* printer);
 
+  // Generate a pragma to pull in metadata using the given info_path (if
+  // non-empty). info_path should be relative to printer's output.
+  void GenerateMetadataPragma(io::Printer* printer, const string& info_path);
+
   // Generates a couple of different pieces before definitions:
   void GenerateGlobalStateFunctionDeclarations(io::Printer* printer);
 
diff --git a/src/google/protobuf/compiler/cpp/cpp_generator.cc b/src/google/protobuf/compiler/cpp/cpp_generator.cc
index 781526b..c7aec93 100644
--- a/src/google/protobuf/compiler/cpp/cpp_generator.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_generator.cc
@@ -90,6 +90,12 @@
       file_options.dllexport_decl = options[i].second;
     } else if (options[i].first == "safe_boundary_check") {
       file_options.safe_boundary_check = true;
+    } else if (options[i].first == "annotate_headers") {
+      file_options.annotate_headers = true;
+    } else if (options[i].first == "annotation_pragma_name") {
+      file_options.annotation_pragma_name = options[i].second;
+    } else if (options[i].first == "annotation_guard_name") {
+      file_options.annotation_guard_name = options[i].second;
     } else {
       *error = "Unknown generator option: " + options[i].first;
       return false;
@@ -107,16 +113,40 @@
   if (file_options.proto_h) {
     google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
         generator_context->Open(basename + ".proto.h"));
-    io::Printer printer(output.get(), '$');
-    file_generator.GenerateProtoHeader(&printer);
+    GeneratedCodeInfo annotations;
+    io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
+        &annotations);
+    string info_path = basename + ".proto.h.meta";
+    io::Printer printer(output.get(), '$', file_options.annotate_headers
+                                               ? &annotation_collector
+                                               : NULL);
+    file_generator.GenerateProtoHeader(
+        &printer, file_options.annotate_headers ? info_path : "");
+    if (file_options.annotate_headers) {
+      scoped_ptr<io::ZeroCopyOutputStream> info_output(
+          generator_context->Open(info_path));
+      annotations.SerializeToZeroCopyStream(info_output.get());
+    }
   }
 
   basename.append(".pb");
   {
     google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
         generator_context->Open(basename + ".h"));
-    io::Printer printer(output.get(), '$');
-    file_generator.GeneratePBHeader(&printer);
+    GeneratedCodeInfo annotations;
+    io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
+        &annotations);
+    string info_path = basename + ".h.meta";
+    io::Printer printer(output.get(), '$', file_options.annotate_headers
+                                               ? &annotation_collector
+                                               : NULL);
+    file_generator.GeneratePBHeader(
+        &printer, file_options.annotate_headers ? info_path : "");
+    if (file_options.annotate_headers) {
+      scoped_ptr<io::ZeroCopyOutputStream> info_output(
+          generator_context->Open(info_path));
+      annotations.SerializeToZeroCopyStream(info_output.get());
+    }
   }
 
   // Generate cc file.
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
index 8304ebb..c316661 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -423,8 +423,8 @@
 MessageGenerator::~MessageGenerator() {}
 
 void MessageGenerator::
-FillMessageForwardDeclarations(set<string>* class_names) {
-  class_names->insert(classname_);
+FillMessageForwardDeclarations(map<string, const Descriptor*>* class_names) {
+  (*class_names)[classname_] = descriptor_;
 
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
     // map entry message doesn't need forward declaration. Since map entry
@@ -436,7 +436,7 @@
 }
 
 void MessageGenerator::
-FillEnumForwardDeclarations(set<string>* enum_names) {
+FillEnumForwardDeclarations(map<string, const EnumDescriptor*>* enum_names) {
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
     nested_generators_[i]->FillEnumForwardDeclarations(enum_names);
   }
@@ -892,6 +892,7 @@
   }
   printer->Print(vars,
     "class $dllexport$$classname$ : public $superclass$ {\n");
+  printer->Annotate("classname", descriptor_);
   if (use_dependent_base_) {
     printer->Print(vars, "  friend class $superclass$;\n");
   }
@@ -1027,6 +1028,8 @@
       "// implements Any -----------------------------------------------\n"
       "\n"
       "void PackFrom(const ::google::protobuf::Message& message);\n"
+      "void PackFrom(const ::google::protobuf::Message& message,\n"
+      "              const ::std::string& type_url_prefix);\n"
       "bool UnpackTo(::google::protobuf::Message* message) const;\n"
       "template<typename T> bool Is() const {\n"
       "  return _any_metadata_.Is<T>();\n"
@@ -1789,6 +1792,11 @@
       "  _any_metadata_.PackFrom(message);\n"
       "}\n"
       "\n"
+      "void $classname$::PackFrom(const ::google::protobuf::Message& message,\n"
+      "                           const ::std::string& type_url_prefix) {\n"
+      "  _any_metadata_.PackFrom(message, type_url_prefix);\n"
+      "}\n"
+      "\n"
       "bool $classname$::UnpackTo(::google::protobuf::Message* message) const {\n"
       "  return _any_metadata_.UnpackTo(message);\n"
       "}\n"
@@ -1899,11 +1907,10 @@
 
 void MessageGenerator::
 GenerateOffsets(io::Printer* printer) {
-  printer->Print(
-    "static const int $classname$_offsets_[$field_count$] = {\n",
-    "classname", classname_,
-    "field_count", SimpleItoa(max(
-        1, descriptor_->field_count() + descriptor_->oneof_decl_count())));
+  printer->Print("static const int $classname$_offsets_[$field_count$] = {\n",
+                 "classname", classname_, "field_count",
+                 SimpleItoa(std::max(1, descriptor_->field_count() +
+                                            descriptor_->oneof_decl_count())));
   printer->Indent();
 
   for (int i = 0; i < descriptor_->field_count(); i++) {
@@ -2907,7 +2914,7 @@
     // on the CodedOutputStream.
     printer->Print(
       "  ::google::protobuf::io::LazyStringOutputStream unknown_fields_string(\n"
-      "      ::google::protobuf::internal::NewPermanentCallback(\n"
+      "      google::protobuf::internal::NewPermanentCallback(\n"
       "          &MutableUnknownFieldsFor$classname$, this));\n"
       "  ::google::protobuf::io::CodedOutputStream unknown_fields_stream(\n"
       "      &unknown_fields_string, false);\n",
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.h b/src/google/protobuf/compiler/cpp/cpp_message.h
index 8e19a3f..31223e1 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message.h
@@ -67,9 +67,13 @@
   // Header stuff.
 
   // Return names for foward declarations of this class and all its nested
-  // types.
-  void FillMessageForwardDeclarations(set<string>* class_names);
-  void FillEnumForwardDeclarations(set<string>* enum_names);
+  // types. A given key in {class,enum}_names will map from a class name to the
+  // descriptor that was responsible for its inclusion in the map. This can be
+  // used to associate the descriptor with the code generated for it.
+  void FillMessageForwardDeclarations(
+      map<string, const Descriptor*>* class_names);
+  void FillEnumForwardDeclarations(
+      map<string, const EnumDescriptor*>* enum_names);
 
   // Generate definitions of all nested enums (must come before class
   // definitions because those classes use the enums definitions).
diff --git a/src/google/protobuf/compiler/cpp/cpp_options.h b/src/google/protobuf/compiler/cpp/cpp_options.h
index 4463f20..e908362 100644
--- a/src/google/protobuf/compiler/cpp/cpp_options.h
+++ b/src/google/protobuf/compiler/cpp/cpp_options.h
@@ -43,11 +43,14 @@
 
 // Generator options (see generator.cc for a description of each):
 struct Options {
-  Options() : safe_boundary_check(false), proto_h(false) {
-  }
+  Options()
+      : safe_boundary_check(false), proto_h(false), annotate_headers(false) {}
   string dllexport_decl;
   bool safe_boundary_check;
   bool proto_h;
+  bool annotate_headers;
+  string annotation_pragma_name;
+  string annotation_guard_name;
 };
 
 }  // namespace cpp
diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
index 9942a34..148da88 100644
--- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
@@ -82,7 +82,6 @@
 
 namespace google {
 namespace protobuf {
-using internal::NewPermanentCallback;
 namespace compiler {
 namespace cpp {
 
@@ -1253,7 +1252,7 @@
       foo_(descriptor_->FindMethodByName("Foo")),
       bar_(descriptor_->FindMethodByName("Bar")),
       stub_(&mock_channel_),
-      done_(NewPermanentCallback(&DoNothing)) {}
+      done_(google::protobuf::internal::NewPermanentCallback(&DoNothing)) {}
 
   virtual void SetUp() {
     ASSERT_TRUE(foo_ != NULL);
diff --git a/src/google/protobuf/compiler/cpp/metadata_test.cc b/src/google/protobuf/compiler/cpp/metadata_test.cc
index 422eb73..61dc283 100644
--- a/src/google/protobuf/compiler/cpp/metadata_test.cc
+++ b/src/google/protobuf/compiler/cpp/metadata_test.cc
@@ -51,6 +51,189 @@
 namespace cpp {
 namespace {
 
+// A CodeGenerator that captures the FileDescriptor it's passed as a
+// FileDescriptorProto.
+class DescriptorCapturingGenerator : public CodeGenerator {
+ public:
+  // Does not own file; file must outlive the Generator.
+  explicit DescriptorCapturingGenerator(FileDescriptorProto* file)
+      : file_(file) {}
+
+  virtual bool Generate(const FileDescriptor* file, const string& parameter,
+                        GeneratorContext* context, string* error) const {
+    file->CopyTo(file_);
+    return true;
+  }
+
+ private:
+  FileDescriptorProto* file_;
+};
+
+class CppMetadataTest : public ::testing::Test {
+ public:
+  // Adds a file with name `filename` and content `data`.
+  void AddFile(const string& filename, const string& data) {
+    GOOGLE_CHECK_OK(File::SetContents(TestTempDir() + "/" + filename, data,
+                               true));
+  }
+
+  // Tries to capture a FileDescriptorProto, GeneratedCodeInfo, and output
+  // code from the previously added file with name `filename`. Returns true on
+  // success. If pb_h is non-null, expects a .pb.h and a .pb.h.meta (copied to
+  // pb_h and pb_h_info respecfively); similarly for proto_h and proto_h_info.
+  bool CaptureMetadata(const string& filename, FileDescriptorProto* file,
+                       string* pb_h, GeneratedCodeInfo* pb_h_info,
+                       string* proto_h, GeneratedCodeInfo* proto_h_info,
+                       string* pb_cc) {
+    google::protobuf::compiler::CommandLineInterface cli;
+    cli.SetInputsAreProtoPathRelative(true);
+
+    CppGenerator cpp_generator;
+    DescriptorCapturingGenerator capturing_generator(file);
+    cli.RegisterGenerator("--cpp_out", &cpp_generator, "");
+    cli.RegisterGenerator("--capture_out", &capturing_generator, "");
+
+    string proto_path = "-I" + TestTempDir();
+    string cpp_out =
+        "--cpp_out=annotate_headers=true,"
+        "annotation_pragma_name=pragma_name,"
+        "annotation_guard_name=guard_name:" +
+        TestTempDir();
+    string capture_out = "--capture_out=" + TestTempDir();
+
+    const char* argv[] = {"protoc", proto_path.c_str(), cpp_out.c_str(),
+                          capture_out.c_str(), filename.c_str()};
+
+    if (cli.Run(5, argv) != 0) {
+      return false;
+    }
+
+    string output_base = TestTempDir() + "/" + StripProto(filename);
+
+    if (pb_cc != NULL) {
+      GOOGLE_CHECK_OK(
+          File::GetContents(output_base + ".pb.cc", pb_cc, true));
+    }
+
+    if (pb_h != NULL && pb_h_info != NULL) {
+      GOOGLE_CHECK_OK(
+          File::GetContents(output_base + ".pb.h", pb_h, true));
+      if (!DecodeMetadata(output_base + ".pb.h.meta", pb_h_info)) {
+        return false;
+      }
+    }
+
+    if (proto_h != NULL && proto_h_info != NULL) {
+      GOOGLE_CHECK_OK(File::GetContents(output_base + ".proto.h", proto_h,
+                                 true));
+      if (!DecodeMetadata(output_base + ".proto.h.meta", proto_h_info)) {
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+ private:
+  // Decodes GeneratedCodeInfo stored in path and copies it to info.
+  // Returns true on success.
+  bool DecodeMetadata(const string& path, GeneratedCodeInfo* info) {
+    string data;
+    GOOGLE_CHECK_OK(File::GetContents(path, &data, true));
+    io::ArrayInputStream input(data.data(), data.size());
+    return info->ParseFromZeroCopyStream(&input);
+  }
+};
+
+const char kSmallTestFile[] =
+    "syntax = \"proto2\";\n"
+    "package foo;\n"
+    "enum Enum { VALUE = 0; }\n"
+    "message Message { }\n";
+
+// Finds the Annotation for a given source file and path (or returns null if it
+// couldn't).
+const GeneratedCodeInfo::Annotation* FindAnnotationOnPath(
+    const GeneratedCodeInfo& info, const string& source_file,
+    const vector<int>& path) {
+  for (int i = 0; i < info.annotation_size(); ++i) {
+    const GeneratedCodeInfo::Annotation* annotation = &info.annotation(i);
+    if (annotation->source_file() != source_file ||
+        annotation->path_size() != path.size()) {
+      continue;
+    }
+    int node = 0;
+    for (; node < path.size(); ++node) {
+      if (annotation->path(node) != path[node]) {
+        break;
+      }
+    }
+    if (node == path.size()) {
+      return annotation;
+    }
+  }
+  return NULL;
+}
+
+// Returns true if the provided annotation covers a given substring in
+// file_content.
+bool AnnotationMatchesSubstring(const string& file_content,
+                                const GeneratedCodeInfo::Annotation* annotation,
+                                const string& expected_text) {
+  uint32 begin = annotation->begin();
+  uint32 end = annotation->end();
+  if (end < begin || end > file_content.size()) {
+    return false;
+  }
+  return file_content.substr(begin, end - begin) == expected_text;
+}
+
+TEST_F(CppMetadataTest, CapturesEnumNames) {
+  FileDescriptorProto file;
+  GeneratedCodeInfo info;
+  string pb_h;
+  AddFile("test.proto", kSmallTestFile);
+  EXPECT_TRUE(
+      CaptureMetadata("test.proto", &file, &pb_h, &info, NULL, NULL, NULL));
+  EXPECT_EQ("Enum", file.enum_type(0).name());
+  vector<int> enum_path;
+  enum_path.push_back(FileDescriptorProto::kEnumTypeFieldNumber);
+  enum_path.push_back(0);
+  const GeneratedCodeInfo::Annotation* enum_annotation =
+      FindAnnotationOnPath(info, "test.proto", enum_path);
+  EXPECT_TRUE(NULL != enum_annotation);
+  EXPECT_TRUE(AnnotationMatchesSubstring(pb_h, enum_annotation, "Enum"));
+}
+
+TEST_F(CppMetadataTest, AddsPragma) {
+  FileDescriptorProto file;
+  GeneratedCodeInfo info;
+  string pb_h;
+  AddFile("test.proto", kSmallTestFile);
+  EXPECT_TRUE(
+      CaptureMetadata("test.proto", &file, &pb_h, &info, NULL, NULL, NULL));
+  EXPECT_TRUE(pb_h.find("#ifdef guard_name") != string::npos);
+  EXPECT_TRUE(pb_h.find("#pragma pragma_name \"test.pb.h.meta\"") !=
+              string::npos);
+}
+
+TEST_F(CppMetadataTest, CapturesMessageNames) {
+  FileDescriptorProto file;
+  GeneratedCodeInfo info;
+  string pb_h;
+  AddFile("test.proto", kSmallTestFile);
+  EXPECT_TRUE(
+      CaptureMetadata("test.proto", &file, &pb_h, &info, NULL, NULL, NULL));
+  EXPECT_EQ("Message", file.message_type(0).name());
+  vector<int> message_path;
+  message_path.push_back(FileDescriptorProto::kMessageTypeFieldNumber);
+  message_path.push_back(0);
+  const GeneratedCodeInfo::Annotation* message_annotation =
+      FindAnnotationOnPath(info, "test.proto", message_path);
+  EXPECT_TRUE(NULL != message_annotation);
+  EXPECT_TRUE(AnnotationMatchesSubstring(pb_h, message_annotation, "Message"));
+}
+
 }  // namespace
 }  // namespace cpp
 }  // namespace compiler
diff --git a/src/google/protobuf/compiler/java/java_context.cc b/src/google/protobuf/compiler/java/java_context.cc
index 7d21fe6..0a11288 100644
--- a/src/google/protobuf/compiler/java/java_context.cc
+++ b/src/google/protobuf/compiler/java/java_context.cc
@@ -43,7 +43,7 @@
 namespace java {
 
 Context::Context(const FileDescriptor* file)
-    : name_resolver_(new ClassNameResolver) {
+    : name_resolver_(new ClassNameResolver), enforce_lite_(false) {
   InitializeFieldGeneratorInfo(file);
 }
 
@@ -189,6 +189,13 @@
   return result;
 }
 
+// Does this message class have generated parsing, serialization, and other
+// standard methods for which reflection-based fallback implementations exist?
+bool Context::HasGeneratedMethods(const Descriptor* descriptor) const {
+  return enforce_lite_ || descriptor->file()->options().optimize_for() !=
+           FileOptions::CODE_SIZE;
+}
+
 }  // namespace java
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/java/java_context.h b/src/google/protobuf/compiler/java/java_context.h
index 5b595d0..a480e45 100644
--- a/src/google/protobuf/compiler/java/java_context.h
+++ b/src/google/protobuf/compiler/java/java_context.h
@@ -46,6 +46,7 @@
   class FieldDescriptor;
   class OneofDescriptor;
   class Descriptor;
+  class EnumDescriptor;
   namespace compiler {
     namespace java {
       class ClassNameResolver;  // name_resolver.h
@@ -78,6 +79,20 @@
   const OneofGeneratorInfo* GetOneofGeneratorInfo(
       const OneofDescriptor* oneof) const;
 
+  // Enforces all the files (including transitive dependencies) to use
+  // LiteRuntime.
+  void SetEnforceLite(bool enforce_lite) {
+    enforce_lite_ = enforce_lite;
+  }
+
+  bool EnforceLite() const {
+    return enforce_lite_;
+  }
+
+  // Does this message class have generated parsing, serialization, and other
+  // standard methods for which reflection-based fallback implementations exist?
+  bool HasGeneratedMethods(const Descriptor* descriptor) const;
+
  private:
   void InitializeFieldGeneratorInfo(const FileDescriptor* file);
   void InitializeFieldGeneratorInfoForMessage(const Descriptor* message);
@@ -87,6 +102,7 @@
   google::protobuf::scoped_ptr<ClassNameResolver> name_resolver_;
   map<const FieldDescriptor*, FieldGeneratorInfo> field_generator_info_map_;
   map<const OneofDescriptor*, OneofGeneratorInfo> oneof_generator_info_map_;
+  bool enforce_lite_;
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Context);
 };
 
diff --git a/src/google/protobuf/compiler/java/java_enum.cc b/src/google/protobuf/compiler/java/java_enum.cc
index 5fc9b00..9eea873 100644
--- a/src/google/protobuf/compiler/java/java_enum.cc
+++ b/src/google/protobuf/compiler/java/java_enum.cc
@@ -64,6 +64,7 @@
                              bool immutable_api,
                              Context* context)
   : descriptor_(descriptor), immutable_api_(immutable_api),
+    context_(context),
     name_resolver_(context->GetNameResolver())  {
   for (int i = 0; i < descriptor_->value_count(); i++) {
     const EnumValueDescriptor* value = descriptor_->value(i);
@@ -150,7 +151,15 @@
     "  return value;\n"
     "}\n"
     "\n"
+    "/**\n"
+    " * @deprecated Use {@link #forNumber(int)} instead.\n"
+    " */\n"
+    "@java.lang.Deprecated\n"
     "public static $classname$ valueOf(int value) {\n"
+    "  return forNumber(value);\n"
+    "}\n"
+    "\n"
+    "public static $classname$ forNumber(int value) {\n"
     "  switch (value) {\n",
     "classname", descriptor_->name());
   printer->Indent();
@@ -178,7 +187,7 @@
     "    $classname$> internalValueMap =\n"
     "      new com.google.protobuf.Internal.EnumLiteMap<$classname$>() {\n"
     "        public $classname$ findValueByNumber(int number) {\n"
-    "          return $classname$.valueOf(number);\n"
+    "          return $classname$.forNumber(number);\n"
     "        }\n"
     "      };\n"
     "\n",
@@ -187,7 +196,7 @@
   // -----------------------------------------------------------------
   // Reflection
 
-  if (HasDescriptorMethods(descriptor_)) {
+  if (HasDescriptorMethods(descriptor_, context_->EnforceLite())) {
     printer->Print(
       "public final com.google.protobuf.Descriptors.EnumValueDescriptor\n"
       "    getValueDescriptor() {\n"
@@ -229,7 +238,7 @@
             "      (com.google.protobuf.Descriptors.FileDescriptor)\n"
             "          m.invoke(immutableFileClass);\n"
             "  return file.getEnumTypes().get($index$);\n"
-            "} catch (Exception e) {\n"
+            "} catch (java.lang.Exception e) {\n"
             // Immutable classes cannot be found. Proceed as if custom options
             // don't exist.
             "}\n",
@@ -313,7 +322,7 @@
     "private final int value;\n\n"
     "private $classname$(int index, int value) {\n",
     "classname", descriptor_->name());
-  if (HasDescriptorMethods(descriptor_)) {
+  if (HasDescriptorMethods(descriptor_, context_->EnforceLite())) {
     printer->Print("  this.index = index;\n");
   }
   printer->Print(
diff --git a/src/google/protobuf/compiler/java/java_enum_field.cc b/src/google/protobuf/compiler/java/java_enum_field.cc
index 558da96..3e54be3 100644
--- a/src/google/protobuf/compiler/java/java_enum_field.cc
+++ b/src/google/protobuf/compiler/java/java_enum_field.cc
@@ -68,21 +68,14 @@
   (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
   (*variables)["default_number"] = SimpleItoa(
       descriptor->default_value_enum()->number());
-  if (descriptor->is_packed()) {
-    (*variables)["tag"] = SimpleItoa(internal::WireFormatLite::MakeTag(
-        descriptor->number(),
-        internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED));
-  } else {
-    (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(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();" : "";
+  (*variables)["on_changed"] = "onChanged();";
 
   if (SupportFieldPresence(descriptor->file())) {
     // For singular messages and builders, one bit is used for the hasField bit.
@@ -198,7 +191,7 @@
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public $type$ get$capitalized_name$() {\n"
-    "  $type$ result = $type$.valueOf($name$_);\n"
+    "  $type$ result = $type$.forNumber($name$_);\n"
     "  return result == null ? $unknown$ : result;\n"
     "}\n");
 }
@@ -231,7 +224,7 @@
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public $type$ get$capitalized_name$() {\n"
-    "  $type$ result = $type$.valueOf($name$_);\n"
+    "  $type$ result = $type$.forNumber($name$_);\n"
     "  return result == null ? $unknown$ : result;\n"
     "}\n");
   WriteFieldDocComment(printer, descriptor_);
@@ -311,7 +304,7 @@
   } else {
     printer->Print(variables_,
       "int rawValue = input.readEnum();\n"
-      "$type$ value = $type$.valueOf(rawValue);\n"
+      "$type$ value = $type$.forNumber(rawValue);\n"
       "if (value == null) {\n");
     if (PreserveUnknownFields(descriptor_->containing_type())) {
       printer->Print(variables_,
@@ -405,7 +398,7 @@
   printer->Print(variables_,
     "$deprecation$public $type$ get$capitalized_name$() {\n"
     "  if ($has_oneof_case_message$) {\n"
-    "    $type$ result =  $type$.valueOf((java.lang.Integer) $oneof_name$_);\n"
+    "    $type$ result = $type$.forNumber((java.lang.Integer) $oneof_name$_);\n"
     "    return result == null ? $unknown$ : result;\n"
     "  }\n"
     "  return $default$;\n"
@@ -443,7 +436,7 @@
   printer->Print(variables_,
     "$deprecation$public $type$ get$capitalized_name$() {\n"
     "  if ($has_oneof_case_message$) {\n"
-    "    $type$ result =  $type$.valueOf((java.lang.Integer) $oneof_name$_);\n"
+    "    $type$ result = $type$.forNumber((java.lang.Integer) $oneof_name$_);\n"
     "    return result == null ? $unknown$ : result;\n"
     "  }\n"
     "  return $default$;\n"
@@ -500,7 +493,7 @@
   } else {
     printer->Print(variables_,
       "int rawValue = input.readEnum();\n"
-      "$type$ value = $type$.valueOf(rawValue);\n"
+      "$type$ value = $type$.forNumber(rawValue);\n"
       "if (value == null) {\n");
     if (PreserveUnknownFields(descriptor_->containing_type())) {
       printer->Print(variables_,
@@ -613,7 +606,7 @@
     "        new com.google.protobuf.Internal.ListAdapter.Converter<\n"
     "            java.lang.Integer, $type$>() {\n"
     "          public $type$ convert(java.lang.Integer from) {\n"
-    "            $type$ result = $type$.valueOf(from);\n"
+    "            $type$ result = $type$.forNumber(from);\n"
     "            return result == null ? $unknown$ : result;\n"
     "          }\n"
     "        };\n");
@@ -649,7 +642,7 @@
   }
 
   if (descriptor_->is_packed() &&
-      HasGeneratedMethods(descriptor_->containing_type())) {
+      context_->HasGeneratedMethods(descriptor_->containing_type())) {
     printer->Print(variables_,
       "private int $name$MemoizedSerializedSize;\n");
   }
@@ -846,7 +839,7 @@
   } else {
     printer->Print(variables_,
       "int rawValue = input.readEnum();\n"
-      "$type$ value = $type$.valueOf(rawValue);\n"
+      "$type$ value = $type$.forNumber(rawValue);\n"
         "if (value == null) {\n");
     if (PreserveUnknownFields(descriptor_->containing_type())) {
       printer->Print(variables_,
diff --git a/src/google/protobuf/compiler/java/java_enum_field_lite.cc b/src/google/protobuf/compiler/java/java_enum_field_lite.cc
index e3e87c5..5b98637 100644
--- a/src/google/protobuf/compiler/java/java_enum_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_enum_field_lite.cc
@@ -75,8 +75,6 @@
   // by the proto compiler
   (*variables)["deprecation"] = descriptor->options().deprecated()
       ? "@java.lang.Deprecated " : "";
-  (*variables)["on_changed"] =
-      HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
 
   if (SupportFieldPresence(descriptor->file())) {
     // For singular messages and builders, one bit is used for the hasField bit.
@@ -179,7 +177,7 @@
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public $type$ get$capitalized_name$() {\n"
-    "  $type$ result = $type$.valueOf($name$_);\n"
+    "  $type$ result = $type$.forNumber($name$_);\n"
     "  return result == null ? $unknown$ : result;\n"
     "}\n");
 
@@ -228,7 +226,7 @@
     printer->Print(variables_,
       "$deprecation$public Builder set$capitalized_name$Value(int value) {\n"
       "  copyOnWrite();\n"
-      "  instance.set$capitalized_name$Value(int value);\n"
+      "  instance.set$capitalized_name$Value(value);\n"
       "  return this;\n"
       "}\n");
   }
@@ -295,7 +293,7 @@
   } else {
     printer->Print(variables_,
       "int rawValue = input.readEnum();\n"
-      "$type$ value = $type$.valueOf(rawValue);\n"
+      "$type$ value = $type$.forNumber(rawValue);\n"
       "if (value == null) {\n");
     if (PreserveUnknownFields(descriptor_->containing_type())) {
       printer->Print(variables_,
@@ -389,7 +387,7 @@
   printer->Print(variables_,
     "$deprecation$public $type$ get$capitalized_name$() {\n"
     "  if ($has_oneof_case_message$) {\n"
-    "    $type$ result =  $type$.valueOf((java.lang.Integer) $oneof_name$_);\n"
+    "    $type$ result = $type$.forNumber((java.lang.Integer) $oneof_name$_);\n"
     "    return result == null ? $unknown$ : result;\n"
     "  }\n"
     "  return $default$;\n"
@@ -488,7 +486,7 @@
   } else {
     printer->Print(variables_,
       "int rawValue = input.readEnum();\n"
-      "$type$ value = $type$.valueOf(rawValue);\n"
+      "$type$ value = $type$.forNumber(rawValue);\n"
       "if (value == null) {\n");
     if (PreserveUnknownFields(descriptor_->containing_type())) {
       printer->Print(variables_,
@@ -602,7 +600,7 @@
     "        new com.google.protobuf.Internal.ListAdapter.Converter<\n"
     "            java.lang.Integer, $type$>() {\n"
     "          public $type$ convert(java.lang.Integer from) {\n"
-    "            $type$ result = $type$.valueOf(from);\n"
+    "            $type$ result = $type$.forNumber(from);\n"
     "            return result == null ? $unknown$ : result;\n"
     "          }\n"
     "        };\n");
@@ -638,7 +636,7 @@
   }
 
   if (descriptor_->options().packed() &&
-      HasGeneratedMethods(descriptor_->containing_type())) {
+      context_->HasGeneratedMethods(descriptor_->containing_type())) {
     printer->Print(variables_,
       "private int $name$MemoizedSerializedSize;\n");
   }
@@ -821,7 +819,6 @@
     "    ensure$capitalized_name$IsMutable();\n"
     "    $name$_.addAll(other.$name$_);\n"
     "  }\n"
-    "  $on_changed$\n"
     "}\n");
 }
 
@@ -844,7 +841,7 @@
   } else {
     printer->Print(variables_,
       "int rawValue = input.readEnum();\n"
-      "$type$ value = $type$.valueOf(rawValue);\n"
+      "$type$ value = $type$.forNumber(rawValue);\n"
         "if (value == null) {\n");
     if (PreserveUnknownFields(descriptor_->containing_type())) {
       printer->Print(variables_,
diff --git a/src/google/protobuf/compiler/java/java_enum_lite.cc b/src/google/protobuf/compiler/java/java_enum_lite.cc
index ed415ee..c22da8d 100644
--- a/src/google/protobuf/compiler/java/java_enum_lite.cc
+++ b/src/google/protobuf/compiler/java/java_enum_lite.cc
@@ -141,7 +141,15 @@
     "  return value;\n"
     "}\n"
     "\n"
+    "/**\n"
+    " * @deprecated Use {@link #forNumber(int)} instead.\n"
+    " */\n"
+    "@java.lang.Deprecated\n"
     "public static $classname$ valueOf(int value) {\n"
+    "  return forNumber(value);\n"
+    "}\n"
+    "\n"
+    "public static $classname$ forNumber(int value) {\n"
     "  switch (value) {\n",
     "classname", descriptor_->name());
   printer->Indent();
@@ -169,7 +177,7 @@
     "    $classname$> internalValueMap =\n"
     "      new com.google.protobuf.Internal.EnumLiteMap<$classname$>() {\n"
     "        public $classname$ findValueByNumber(int number) {\n"
-    "          return $classname$.valueOf(number);\n"
+    "          return $classname$.forNumber(number);\n"
     "        }\n"
     "      };\n"
     "\n",
diff --git a/src/google/protobuf/compiler/java/java_extension.cc b/src/google/protobuf/compiler/java/java_extension.cc
index 4db7085..46b5faa 100644
--- a/src/google/protobuf/compiler/java/java_extension.cc
+++ b/src/google/protobuf/compiler/java/java_extension.cc
@@ -118,75 +118,38 @@
       "public static final int $constant_name$ = $number$;\n");
 
   WriteFieldDocComment(printer, descriptor_);
-  if (HasDescriptorMethods(descriptor_->file())) {
-    // 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 {
-      // 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");
-    }
+  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 {
-    // 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"
-          "      $singular_type$.class);\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"
-          "      $singular_type$.class);\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");
   }
 }
 
 int ImmutableExtensionGenerator::GenerateNonNestedInitializationCode(
     io::Printer* printer) {
   int bytecode_estimate = 0;
-  if (descriptor_->extension_scope() == NULL &&
-      HasDescriptorMethods(descriptor_->file())) {
-    // Only applies to non-nested, non-lite extensions.
+  if (descriptor_->extension_scope() == NULL) {
+    // Only applies to non-nested extensions.
     printer->Print(
         "$name$.internalInit(descriptor.getExtensions().get($index$));\n",
         "name", UnderscoresToCamelCase(descriptor_),
diff --git a/src/google/protobuf/compiler/java/java_extension_lite.cc b/src/google/protobuf/compiler/java/java_extension_lite.cc
index e69de29..23261ba 100644
--- a/src/google/protobuf/compiler/java/java_extension_lite.cc
+++ b/src/google/protobuf/compiler/java/java_extension_lite.cc
@@ -0,0 +1,118 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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.
+
+#include <google/protobuf/compiler/java/java_extension_lite.h>
+
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+ImmutableExtensionLiteGenerator::ImmutableExtensionLiteGenerator(
+    const FieldDescriptor* descriptor, Context* context)
+  : descriptor_(descriptor), context_(context),
+    name_resolver_(context->GetNameResolver()) {
+  if (descriptor_->extension_scope() != NULL) {
+    scope_ = name_resolver_->GetImmutableClassName(
+        descriptor_->extension_scope());
+  } else {
+    scope_ = name_resolver_->GetImmutableClassName(descriptor_->file());
+  }
+}
+
+ImmutableExtensionLiteGenerator::~ImmutableExtensionLiteGenerator() {}
+
+void ImmutableExtensionLiteGenerator::Generate(io::Printer* printer) {
+  map<string, string> vars;
+  const bool kUseImmutableNames = true;
+  InitTemplateVars(descriptor_, scope_, kUseImmutableNames, name_resolver_,
+                   &vars);
+  printer->Print(vars,
+      "public static final int $constant_name$ = $number$;\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  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"
+        "      $singular_type$.class);\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"
+        "      $singular_type$.class);\n");
+  }
+}
+
+int ImmutableExtensionLiteGenerator::GenerateNonNestedInitializationCode(
+    io::Printer* printer) {
+  return 0;
+}
+
+int ImmutableExtensionLiteGenerator::GenerateRegistrationCode(
+    io::Printer* printer) {
+  printer->Print(
+    "registry.add($scope$.$name$);\n",
+    "scope", scope_,
+    "name", UnderscoresToCamelCase(descriptor_));
+  return 7;
+}
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/java/java_extension_lite.h b/src/google/protobuf/compiler/java/java_extension_lite.h
index e69de29..4cd49bd 100644
--- a/src/google/protobuf/compiler/java/java_extension_lite.h
+++ b/src/google/protobuf/compiler/java/java_extension_lite.h
@@ -0,0 +1,76 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_LITE_H__
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/java/java_extension.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+// Generates code for a lite extension, which may be within the scope of some
+// message or may be at file scope.  This is much simpler than FieldGenerator
+// since extensions are just simple identifiers with interesting types.
+class ImmutableExtensionLiteGenerator : public ExtensionGenerator {
+ public:
+  explicit ImmutableExtensionLiteGenerator(const FieldDescriptor* descriptor,
+                                           Context* context);
+  virtual ~ImmutableExtensionLiteGenerator();
+
+  virtual void Generate(io::Printer* printer);
+
+  // Returns an estimate of the number of bytes the printed code will compile to
+  virtual int GenerateNonNestedInitializationCode(io::Printer* printer);
+
+  // Returns an estimate of the number of bytes the printed code will compile to
+  virtual int GenerateRegistrationCode(io::Printer* printer);
+
+ private:
+  const FieldDescriptor* descriptor_;
+  Context* context_;
+  ClassNameResolver* name_resolver_;
+  string scope_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableExtensionLiteGenerator);
+};
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_LITE_H__
diff --git a/src/google/protobuf/compiler/java/java_field.cc b/src/google/protobuf/compiler/java/java_field.cc
index c543476..3c7bc5c 100644
--- a/src/google/protobuf/compiler/java/java_field.cc
+++ b/src/google/protobuf/compiler/java/java_field.cc
@@ -77,7 +77,7 @@
           return new ImmutableMapFieldGenerator(
               field, messageBitIndex, builderBitIndex, context);
         } else {
-          if (IsLazy(field)) {
+          if (IsLazy(field, context->EnforceLite())) {
             return new RepeatedImmutableLazyMessageFieldGenerator(
                 field, messageBitIndex, builderBitIndex, context);
           } else {
@@ -99,7 +99,7 @@
     if (field->containing_oneof()) {
       switch (GetJavaType(field)) {
         case JAVATYPE_MESSAGE:
-          if (IsLazy(field)) {
+          if (IsLazy(field, context->EnforceLite())) {
             return new ImmutableLazyMessageOneofFieldGenerator(
                 field, messageBitIndex, builderBitIndex, context);
           } else {
@@ -119,7 +119,7 @@
     } else {
       switch (GetJavaType(field)) {
         case JAVATYPE_MESSAGE:
-          if (IsLazy(field)) {
+          if (IsLazy(field, context->EnforceLite())) {
             return new ImmutableLazyMessageFieldGenerator(
                 field, messageBitIndex, builderBitIndex, context);
           } else {
@@ -150,7 +150,7 @@
           return new ImmutableMapFieldLiteGenerator(
               field, messageBitIndex, builderBitIndex, context);
         } else {
-          if (IsLazy(field)) {
+          if (IsLazy(field, context->EnforceLite())) {
             return new RepeatedImmutableLazyMessageFieldLiteGenerator(
                 field, messageBitIndex, builderBitIndex, context);
           } else {
@@ -172,7 +172,7 @@
     if (field->containing_oneof()) {
       switch (GetJavaType(field)) {
         case JAVATYPE_MESSAGE:
-          if (IsLazy(field)) {
+          if (IsLazy(field, context->EnforceLite())) {
             return new ImmutableLazyMessageOneofFieldLiteGenerator(
                 field, messageBitIndex, builderBitIndex, context);
           } else {
@@ -192,7 +192,7 @@
     } else {
       switch (GetJavaType(field)) {
         case JAVATYPE_MESSAGE:
-          if (IsLazy(field)) {
+          if (IsLazy(field, context->EnforceLite())) {
             return new ImmutableLazyMessageFieldLiteGenerator(
                 field, messageBitIndex, builderBitIndex, context);
           } else {
diff --git a/src/google/protobuf/compiler/java/java_file.cc b/src/google/protobuf/compiler/java/java_file.cc
index c817233..c53aae6 100644
--- a/src/google/protobuf/compiler/java/java_file.cc
+++ b/src/google/protobuf/compiler/java/java_file.cc
@@ -177,7 +177,7 @@
   // since otherwise we hit a hardcoded limit in the jvm and javac will
   // then fail with the error "code too large". This limit lets our
   // estimates be off by a factor of two and still we're okay.
-  static const int bytesPerMethod = 1<<15;  // aka 32K
+  static const int bytesPerMethod = kMaxStaticSize;
 
   if ((*bytecode_estimate) > bytesPerMethod) {
     ++(*method_num);
@@ -193,7 +193,8 @@
 
 }  // namespace
 
-FileGenerator::FileGenerator(const FileDescriptor* file, bool immutable_api)
+FileGenerator::FileGenerator(const FileDescriptor* file, bool immutable_api,
+                             bool enforce_lite)
     : file_(file),
       java_package_(FileJavaPackage(file, immutable_api)),
       message_generators_(
@@ -204,6 +205,7 @@
       name_resolver_(context_->GetNameResolver()),
       immutable_api_(immutable_api) {
   classname_ = name_resolver_->GetFileClassName(file, immutable_api);
+  context_->SetEnforceLite(enforce_lite);
   generator_factory_.reset(
       new ImmutableGeneratorFactory(context_.get()));
   for (int i = 0; i < file_->message_type_count(); ++i) {
@@ -262,7 +264,8 @@
   printer->Print(
     "public static void registerAllExtensions(\n"
     "    com.google.protobuf.ExtensionRegistry$lite$ registry) {\n",
-    "lite", HasDescriptorMethods(file_) ? "" : "Lite");
+    "lite",
+    HasDescriptorMethods(file_, context_->EnforceLite()) ? "" : "Lite");
 
   printer->Indent();
 
@@ -282,7 +285,7 @@
 
   if (!MultipleJavaFiles(file_, immutable_api_)) {
     for (int i = 0; i < file_->enum_type_count(); i++) {
-      if (HasDescriptorMethods(file_)) {
+      if (HasDescriptorMethods(file_, context_->EnforceLite())) {
         EnumGenerator(file_->enum_type(i), immutable_api_, context_.get())
             .Generate(printer);
       } else {
@@ -294,7 +297,7 @@
       message_generators_[i]->GenerateInterface(printer);
       message_generators_[i]->Generate(printer);
     }
-    if (HasGenericServices(file_)) {
+    if (HasGenericServices(file_, context_->EnforceLite())) {
       for (int i = 0; i < file_->service_count(); i++) {
         google::protobuf::scoped_ptr<ServiceGenerator> generator(
             generator_factory_->NewServiceGenerator(file_->service(i)));
@@ -309,14 +312,18 @@
     extension_generators_[i]->Generate(printer);
   }
 
-  // Static variables.
+  // Static variables. We'd like them to be final if possible, but due to
+  // the JVM's 64k size limit on static blocks, we have to initialize some
+  // of them in methods; thus they cannot be final.
+  int static_block_bytecode_estimate = 0;
   for (int i = 0; i < file_->message_type_count(); i++) {
-    message_generators_[i]->GenerateStaticVariables(printer);
+    message_generators_[i]->GenerateStaticVariables(
+        printer, &static_block_bytecode_estimate);
   }
 
   printer->Print("\n");
 
-  if (HasDescriptorMethods(file_)) {
+  if (HasDescriptorMethods(file_, context_->EnforceLite())) {
     if (immutable_api_) {
       GenerateDescriptorInitializationCodeForImmutable(printer);
     } else {
@@ -358,9 +365,11 @@
     "    getDescriptor() {\n"
     "  return descriptor;\n"
     "}\n"
-    "private static com.google.protobuf.Descriptors.FileDescriptor\n"
+    "private static $final$ com.google.protobuf.Descriptors.FileDescriptor\n"
     "    descriptor;\n"
-    "static {\n");
+    "static {\n",
+    // TODO(dweis): Mark this as final.
+    "final", "");
   printer->Indent();
 
   SharedCodeGenerator shared_code_generator(file_);
@@ -453,7 +462,7 @@
     "    getDescriptor() {\n"
     "  return descriptor;\n"
     "}\n"
-    "private static com.google.protobuf.Descriptors.FileDescriptor\n"
+    "private static final com.google.protobuf.Descriptors.FileDescriptor\n"
     "    descriptor;\n"
     "static {\n");
   printer->Indent();
@@ -549,7 +558,7 @@
                                      vector<string>* file_list) {
   if (MultipleJavaFiles(file_, immutable_api_)) {
     for (int i = 0; i < file_->enum_type_count(); i++) {
-      if (HasDescriptorMethods(file_)) {
+      if (HasDescriptorMethods(file_, context_->EnforceLite())) {
         EnumGenerator generator(file_->enum_type(i), immutable_api_,
                                 context_.get());
         GenerateSibling<EnumGenerator>(package_dir, java_package_,
@@ -582,7 +591,7 @@
                                         message_generators_[i].get(),
                                         &MessageGenerator::Generate);
     }
-    if (HasGenericServices(file_)) {
+    if (HasGenericServices(file_, context_->EnforceLite())) {
       for (int i = 0; i < file_->service_count(); i++) {
         google::protobuf::scoped_ptr<ServiceGenerator> generator(
             generator_factory_->NewServiceGenerator(file_->service(i)));
diff --git a/src/google/protobuf/compiler/java/java_file.h b/src/google/protobuf/compiler/java/java_file.h
index 080b342..7dbeb94 100644
--- a/src/google/protobuf/compiler/java/java_file.h
+++ b/src/google/protobuf/compiler/java/java_file.h
@@ -67,7 +67,8 @@
 
 class FileGenerator {
  public:
-  FileGenerator(const FileDescriptor* file, bool immutable_api = true);
+  FileGenerator(const FileDescriptor* file, bool immutable_api = true,
+                bool enforce_lite = false);
   ~FileGenerator();
 
   // Checks for problems that would otherwise lead to cryptic compile errors.
diff --git a/src/google/protobuf/compiler/java/java_generator.cc b/src/google/protobuf/compiler/java/java_generator.cc
index 6c6f728..a46c7fc 100644
--- a/src/google/protobuf/compiler/java/java_generator.cc
+++ b/src/google/protobuf/compiler/java/java_generator.cc
@@ -75,6 +75,7 @@
   bool generate_immutable_code = false;
   bool generate_mutable_code = false;
   bool generate_shared_code = false;
+  bool enforce_lite = false;
   for (int i = 0; i < options.size(); i++) {
     if (options[i].first == "output_list_file") {
       output_list_file = options[i].second;
@@ -84,12 +85,21 @@
       generate_mutable_code = true;
     } else if (options[i].first == "shared") {
       generate_shared_code = true;
+    } else if (options[i].first == "lite") {
+      // When set, the protoc will generate the current files and all the
+      // transitive dependencies as lite runtime.
+      enforce_lite = true;
     } else {
       *error = "Unknown generator option: " + options[i].first;
       return false;
     }
   }
 
+  if (enforce_lite && generate_mutable_code) {
+    *error = "lite runtime generator option cannot be used with mutable API.";
+    return false;
+  }
+
   // By default we generate immutable code and shared code for immutable API.
   if (!generate_immutable_code && !generate_mutable_code &&
       !generate_shared_code) {
@@ -105,10 +115,12 @@
 
   vector<FileGenerator*> file_generators;
   if (generate_immutable_code) {
-    file_generators.push_back(new FileGenerator(file, /* immutable = */ true));
+    file_generators.push_back(
+        new FileGenerator(file, /* immutable = */ true, enforce_lite));
   }
   if (generate_mutable_code) {
-    file_generators.push_back(new FileGenerator(file, /* mutable = */ false));
+    file_generators.push_back(
+        new FileGenerator(file, /* mutable = */ false, enforce_lite));
   }
   for (int i = 0; i < file_generators.size(); ++i) {
     if (!file_generators[i]->Validate(error)) {
diff --git a/src/google/protobuf/compiler/java/java_generator_factory.cc b/src/google/protobuf/compiler/java/java_generator_factory.cc
index 92ef851..3218b41 100644
--- a/src/google/protobuf/compiler/java/java_generator_factory.cc
+++ b/src/google/protobuf/compiler/java/java_generator_factory.cc
@@ -35,6 +35,7 @@
 #include <google/protobuf/compiler/java/java_context.h>
 #include <google/protobuf/compiler/java/java_enum_field.h>
 #include <google/protobuf/compiler/java/java_extension.h>
+#include <google/protobuf/compiler/java/java_extension_lite.h>
 #include <google/protobuf/compiler/java/java_field.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/compiler/java/java_message.h>
@@ -58,17 +59,20 @@
 
 MessageGenerator* ImmutableGeneratorFactory::NewMessageGenerator(
     const Descriptor* descriptor) const {
-  if (descriptor->file()->options().optimize_for() ==
-      FileOptions::LITE_RUNTIME) {
-    return new ImmutableMessageLiteGenerator(descriptor, context_);
-  } else {
+  if (HasDescriptorMethods(descriptor, context_->EnforceLite())) {
     return new ImmutableMessageGenerator(descriptor, context_);
+  } else {
+    return new ImmutableMessageLiteGenerator(descriptor, context_);
   }
 }
 
 ExtensionGenerator* ImmutableGeneratorFactory::NewExtensionGenerator(
     const FieldDescriptor* descriptor) const {
-  return new ImmutableExtensionGenerator(descriptor, context_);
+  if (HasDescriptorMethods(descriptor->file(), context_->EnforceLite())) {
+    return new ImmutableExtensionGenerator(descriptor, context_);
+  } else {
+    return new ImmutableExtensionLiteGenerator(descriptor, context_);
+  }
 }
 
 ServiceGenerator* ImmutableGeneratorFactory::NewServiceGenerator(
diff --git a/src/google/protobuf/compiler/java/java_helpers.h b/src/google/protobuf/compiler/java/java_helpers.h
index 5392d6d..c850423 100644
--- a/src/google/protobuf/compiler/java/java_helpers.h
+++ b/src/google/protobuf/compiler/java/java_helpers.h
@@ -170,44 +170,41 @@
 }
 bool IsDefaultValueJavaDefault(const FieldDescriptor* field);
 
-// Does this message class have generated parsing, serialization, and other
-// standard methods for which reflection-based fallback implementations exist?
-inline bool HasGeneratedMethods(const Descriptor* descriptor) {
-  return descriptor->file()->options().optimize_for() !=
-           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() !=
-           FileOptions::LITE_RUNTIME;
+inline bool HasDescriptorMethods(const Descriptor* descriptor,
+                                 bool enforce_lite) {
+  return !enforce_lite &&
+         descriptor->file()->options().optimize_for() !=
+             FileOptions::LITE_RUNTIME;
 }
-inline bool HasDescriptorMethods(const EnumDescriptor* descriptor) {
-  return descriptor->file()->options().optimize_for() !=
-           FileOptions::LITE_RUNTIME;
+inline bool HasDescriptorMethods(const EnumDescriptor* descriptor,
+                                 bool enforce_lite) {
+  return !enforce_lite &&
+         descriptor->file()->options().optimize_for() !=
+             FileOptions::LITE_RUNTIME;
 }
-inline bool HasDescriptorMethods(const FileDescriptor* descriptor) {
-  return descriptor->options().optimize_for() !=
-           FileOptions::LITE_RUNTIME;
+inline bool HasDescriptorMethods(const FileDescriptor* descriptor,
+                                 bool enforce_lite) {
+  return !enforce_lite &&
+         descriptor->options().optimize_for() != FileOptions::LITE_RUNTIME;
 }
 
 // Should we generate generic services for this file?
-inline bool HasGenericServices(const FileDescriptor *file) {
+inline bool HasGenericServices(const FileDescriptor *file, bool enforce_lite) {
   return file->service_count() > 0 &&
-         file->options().optimize_for() != FileOptions::LITE_RUNTIME &&
+         HasDescriptorMethods(file, enforce_lite) &&
          file->options().java_generic_services();
 }
 
-inline bool IsLazy(const FieldDescriptor* descriptor) {
+inline bool IsLazy(const FieldDescriptor* descriptor, bool enforce_lite) {
   // Currently, the proto-lite version suports lazy field.
   // TODO(niwasaki): Support lazy fields also for other proto runtimes.
-  if (descriptor->file()->options().optimize_for() !=
-      FileOptions::LITE_RUNTIME) {
+  if (HasDescriptorMethods(descriptor->file(), enforce_lite)) {
     return false;
   }
   return descriptor->options().lazy();
diff --git a/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc b/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc
index 283ba1d..a648f1c 100644
--- a/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc
@@ -193,7 +193,7 @@
 void ImmutableLazyMessageFieldLiteGenerator::
 GenerateParsingCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "$name$_.setByteString(input.readBytes(), extensionRegistry);\n");
+    "$name$_.mergeFrom(input, extensionRegistry);\n");
   printer->Print(variables_,
     "$set_has_field_bit_message$;\n");
 }
@@ -378,8 +378,7 @@
     "if (!($has_oneof_case_message$)) {\n"
     "  $oneof_name$_ = new $lazy_type$();\n"
     "}\n"
-    "(($lazy_type$) $oneof_name$_).setByteString(\n"
-    "    input.readBytes(), extensionRegistry);\n"
+    "(($lazy_type$) $oneof_name$_).mergeFrom(input, extensionRegistry);\n"
     "$set_oneof_case_message$;\n");
 }
 
diff --git a/src/google/protobuf/compiler/java/java_map_field.cc b/src/google/protobuf/compiler/java/java_map_field.cc
index 3e035c8..17c3646 100644
--- a/src/google/protobuf/compiler/java/java_map_field.cc
+++ b/src/google/protobuf/compiler/java/java_map_field.cc
@@ -79,9 +79,10 @@
                          int messageBitIndex,
                          int builderBitIndex,
                          const FieldGeneratorInfo* info,
-                         ClassNameResolver* name_resolver,
+                         Context* context,
                          map<string, string>* variables) {
   SetCommonFieldVariables(descriptor, info, variables);
+  ClassNameResolver* name_resolver = context->GetNameResolver();
 
   (*variables)["type"] =
       name_resolver->GetImmutableClassName(descriptor->message_type());
@@ -123,8 +124,7 @@
   // by the proto compiler
   (*variables)["deprecation"] = descriptor->options().deprecated()
       ? "@java.lang.Deprecated " : "";
-  (*variables)["on_changed"] =
-      HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
+  (*variables)["on_changed"] = "onChanged();";
 
   // For repeated fields, one bit is used for whether the array is immutable
   // in the parsing constructor.
@@ -135,18 +135,12 @@
 
   (*variables)["default_entry"] = (*variables)["capitalized_name"] +
       "DefaultEntryHolder.defaultEntry";
-  if (HasDescriptorMethods(descriptor->file())) {
-    (*variables)["lite"] = "";
-    (*variables)["map_field_parameter"] = (*variables)["default_entry"];
-    (*variables)["descriptor"] =
-        name_resolver->GetImmutableClassName(descriptor->file()) +
-        ".internal_" + UniqueFileScopeIdentifier(descriptor->message_type()) +
-        "_descriptor, ";
-  } else {
-    (*variables)["lite"] = "Lite";
-    (*variables)["map_field_parameter"] = "";
-    (*variables)["descriptor"] = "";
-  }
+  (*variables)["lite"] = "";
+  (*variables)["map_field_parameter"] = (*variables)["default_entry"];
+  (*variables)["descriptor"] =
+      name_resolver->GetImmutableClassName(descriptor->file()) +
+      ".internal_" + UniqueFileScopeIdentifier(descriptor->message_type()) +
+      "_descriptor, ";
 }
 
 }  // namespace
@@ -159,7 +153,7 @@
   : descriptor_(descriptor), name_resolver_(context->GetNameResolver())  {
   SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
                       context->GetFieldGeneratorInfo(descriptor),
-                      name_resolver_, &variables_);
+                      context, &variables_);
 }
 
 ImmutableMapFieldGenerator::
@@ -424,7 +418,7 @@
         "$name$ = $default_entry$.getParserForType().parseFrom(bytes);\n");
     printer->Print(
         variables_,
-        "if ($value_enum_type$.valueOf($name$.getValue()) == null) {\n"
+        "if ($value_enum_type$.forNumber($name$.getValue()) == null) {\n"
         "  unknownFields.mergeLengthDelimitedField($number$, bytes);\n"
         "} else {\n"
         "  $name$_.getMutableMap().put($name$.getKey(), $name$.getValue());\n"
diff --git a/src/google/protobuf/compiler/java/java_map_field_lite.cc b/src/google/protobuf/compiler/java/java_map_field_lite.cc
index d203940..6bdebb0 100644
--- a/src/google/protobuf/compiler/java/java_map_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_map_field_lite.cc
@@ -79,10 +79,11 @@
                          int messageBitIndex,
                          int builderBitIndex,
                          const FieldGeneratorInfo* info,
-                         ClassNameResolver* name_resolver,
+                         Context* context,
                          map<string, string>* variables) {
   SetCommonFieldVariables(descriptor, info, variables);
 
+  ClassNameResolver* name_resolver = context->GetNameResolver();
   (*variables)["type"] =
       name_resolver->GetImmutableClassName(descriptor->message_type());
   const FieldDescriptor* key = KeyField(descriptor);
@@ -123,8 +124,6 @@
   // by the proto compiler
   (*variables)["deprecation"] = descriptor->options().deprecated()
       ? "@java.lang.Deprecated " : "";
-  (*variables)["on_changed"] =
-      HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
 
   (*variables)["default_entry"] = (*variables)["capitalized_name"] +
       "DefaultEntryHolder.defaultEntry";
@@ -142,7 +141,7 @@
   : descriptor_(descriptor), name_resolver_(context->GetNameResolver())  {
   SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
                       context->GetFieldGeneratorInfo(descriptor),
-                      name_resolver_, &variables_);
+                      context, &variables_);
 }
 
 ImmutableMapFieldLiteGenerator::
@@ -404,7 +403,7 @@
         "$name$ = $default_entry$.getParserForType().parseFrom(bytes);\n");
     printer->Print(
         variables_,
-        "if ($value_enum_type$.valueOf($name$.getValue()) == null) {\n"
+        "if ($value_enum_type$.forNumber($name$.getValue()) == null) {\n"
         "  super.mergeLengthDelimitedField($number$, bytes);\n"
         "} else {\n"
         "  $name$_.getMutableMap().put($name$.getKey(), $name$.getValue());\n"
diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc
index 22a70c3..dfd8ad0 100644
--- a/src/google/protobuf/compiler/java/java_message.cc
+++ b/src/google/protobuf/compiler/java/java_message.cc
@@ -95,13 +95,15 @@
   : MessageGenerator(descriptor), context_(context),
     name_resolver_(context->GetNameResolver()),
     field_generators_(descriptor, context_) {
-  GOOGLE_CHECK_NE(
-      FileOptions::LITE_RUNTIME, descriptor->file()->options().optimize_for());
+  GOOGLE_CHECK(HasDescriptorMethods(descriptor->file(), context->EnforceLite()))
+      << "Generator factory error: A non-lite message generator is used to "
+         "generate lite messages.";
 }
 
 ImmutableMessageGenerator::~ImmutableMessageGenerator() {}
 
-void ImmutableMessageGenerator::GenerateStaticVariables(io::Printer* printer) {
+void ImmutableMessageGenerator::GenerateStaticVariables(
+    io::Printer* printer, int* bytecode_estimate) {
   // Because descriptor.proto (com.google.protobuf.DescriptorProtos) is
   // used in the construction of descriptors, we have a tricky bootstrapping
   // problem.  To help control static initialization order, we make sure all
@@ -124,23 +126,29 @@
   } else {
     vars["private"] = "private ";
   }
+  if (*bytecode_estimate <= kMaxStaticSize) {
+    vars["final"] = "final ";
+  } else {
+    vars["final"] = "";
+  }
 
   // The descriptor for this type.
   printer->Print(vars,
     // TODO(teboring): final needs to be added back. The way to fix it is to
     // generate methods that can construct the types, and then still declare the
     // types, and then init them in clinit with the new method calls.
-    "$private$static com.google.protobuf.Descriptors.Descriptor\n"
+    "$private$static $final$com.google.protobuf.Descriptors.Descriptor\n"
     "  internal_$identifier$_descriptor;\n");
+  *bytecode_estimate += 30;
 
   // And the FieldAccessorTable.
-  GenerateFieldAccessorTable(printer);
+  GenerateFieldAccessorTable(printer, bytecode_estimate);
 
   // Generate static members for all nested types.
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
     // TODO(kenton):  Reuse MessageGenerator objects?
     ImmutableMessageGenerator(descriptor_->nested_type(i), context_)
-      .GenerateStaticVariables(printer);
+        .GenerateStaticVariables(printer, bytecode_estimate);
   }
 }
 
@@ -183,7 +191,7 @@
 }
 
 void ImmutableMessageGenerator::
-GenerateFieldAccessorTable(io::Printer* printer) {
+GenerateFieldAccessorTable(io::Printer* printer, int* bytecode_estimate) {
   map<string, string> vars;
   vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
   if (MultipleJavaFiles(descriptor_->file(), /* immutable = */ true)) {
@@ -193,10 +201,19 @@
   } else {
     vars["private"] = "private ";
   }
+  if (*bytecode_estimate <= kMaxStaticSize) {
+    vars["final"] = "final ";
+  } else {
+    vars["final"] = "";
+  }
   printer->Print(vars,
-    "$private$static\n"
+    "$private$static $final$\n"
     "  com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
     "    internal_$identifier$_fieldAccessorTable;\n");
+
+  // 6 bytes per field and oneof
+  *bytecode_estimate += 10 + 6 * descriptor_->field_count()
+      + 6 * descriptor_->oneof_decl_count();
 }
 
 int ImmutableMessageGenerator::
@@ -342,7 +359,7 @@
   printer->Print(
     "}\n");
 
-  if (HasGeneratedMethods(descriptor_)) {
+  if (context_->HasGeneratedMethods(descriptor_)) {
     GenerateParsingConstructor(printer);
   }
 
@@ -408,12 +425,20 @@
       "cap_oneof_name",
       ToUpper(vars["oneof_name"]));
     printer->Print(vars,
-      "private int value = 0;\n"
+      "private final int value;\n"
       "private $oneof_capitalized_name$Case(int value) {\n"
       "  this.value = value;\n"
       "}\n");
     printer->Print(vars,
+      "/**\n"
+      " * @deprecated Use {@link #forNumber(int)} instead.\n"
+      " */\n"
+      "@java.lang.Deprecated\n"
       "public static $oneof_capitalized_name$Case valueOf(int value) {\n"
+      "  return forNumber(value);\n"
+      "}\n"
+      "\n"
+      "public static $oneof_capitalized_name$Case forNumber(int value) {\n"
       "  switch (value) {\n");
     for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
       const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
@@ -426,8 +451,7 @@
     }
     printer->Print(
       "    case 0: return $cap_oneof_name$_NOT_SET;\n"
-      "    default: throw new java.lang.IllegalArgumentException(\n"
-      "      \"Value is undefined for this oneof enum.\");\n"
+      "    default: return null;\n"
       "  }\n"
       "}\n"
       "public int getNumber() {\n"
@@ -440,7 +464,7 @@
     printer->Print(vars,
       "public $oneof_capitalized_name$Case\n"
       "get$oneof_capitalized_name$Case() {\n"
-      "  return $oneof_capitalized_name$Case.valueOf(\n"
+      "  return $oneof_capitalized_name$Case.forNumber(\n"
       "      $oneof_name$Case_);\n"
       "}\n"
       "\n");
@@ -459,7 +483,7 @@
     printer->Print("\n");
   }
 
-  if (HasGeneratedMethods(descriptor_)) {
+  if (context_->HasGeneratedMethods(descriptor_)) {
     GenerateIsInitialized(printer);
     GenerateMessageSerializationMethods(printer);
   }
@@ -664,34 +688,40 @@
     "}\n"
     "public static $classname$ parseFrom(java.io.InputStream input)\n"
     "    throws java.io.IOException {\n"
-    "  return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input);"
+    "  return com.google.protobuf.GeneratedMessage\n"
+    "      .parseWithIOException(PARSER, input);\n"
     "}\n"
     "public static $classname$ parseFrom(\n"
     "    java.io.InputStream input,\n"
     "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
     "    throws java.io.IOException {\n"
-    "  return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input, extensionRegistry);"
+    "  return com.google.protobuf.GeneratedMessage\n"
+    "      .parseWithIOException(PARSER, input, extensionRegistry);\n"
     "}\n"
     "public static $classname$ parseDelimitedFrom(java.io.InputStream input)\n"
     "    throws java.io.IOException {\n"
-    "  return com.google.protobuf.GeneratedMessage.parseDelimitedWithIOException(PARSER, input);"
+    "  return com.google.protobuf.GeneratedMessage\n"
+    "      .parseDelimitedWithIOException(PARSER, input);\n"
     "}\n"
     "public static $classname$ parseDelimitedFrom(\n"
     "    java.io.InputStream input,\n"
     "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
     "    throws java.io.IOException {\n"
-    "  return com.google.protobuf.GeneratedMessage.parseDelimitedWithIOException(PARSER, input, extensionRegistry);"
+    "  return com.google.protobuf.GeneratedMessage\n"
+    "      .parseDelimitedWithIOException(PARSER, input, extensionRegistry);\n"
     "}\n"
     "public static $classname$ parseFrom(\n"
     "    com.google.protobuf.CodedInputStream input)\n"
     "    throws java.io.IOException {\n"
-    "  return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input);"
+    "  return com.google.protobuf.GeneratedMessage\n"
+    "      .parseWithIOException(PARSER, input);\n"
     "}\n"
     "public static $classname$ parseFrom(\n"
     "    com.google.protobuf.CodedInputStream input,\n"
     "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
     "    throws java.io.IOException {\n"
-    "  return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input, extensionRegistry);"
+    "  return com.google.protobuf.GeneratedMessage\n"
+    "      .parseWithIOException(PARSER, input, extensionRegistry);\n"
     "}\n"
     "\n",
     "classname", name_resolver_->GetImmutableClassName(descriptor_));
@@ -1049,22 +1079,52 @@
 
   printer->Print("hash = (19 * hash) + getDescriptorForType().hashCode();\n");
 
+  // hashCode non-oneofs.
   for (int i = 0; i < descriptor_->field_count(); i++) {
     const FieldDescriptor* field = descriptor_->field(i);
-    const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
-    bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field);
-    if (check_has_bits) {
-      printer->Print(
-        "if (has$name$()) {\n",
-        "name", info->capitalized_name);
-      printer->Indent();
-    }
-    field_generators_.get(field).GenerateHashCode(printer);
-    if (check_has_bits) {
-      printer->Outdent();
-      printer->Print("}\n");
+    if (field->containing_oneof() == NULL) {
+      const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+      bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field);
+      if (check_has_bits) {
+        printer->Print(
+          "if (has$name$()) {\n",
+          "name", info->capitalized_name);
+        printer->Indent();
+      }
+      field_generators_.get(field).GenerateHashCode(printer);
+      if (check_has_bits) {
+        printer->Outdent();
+        printer->Print("}\n");
+      }
     }
   }
+
+  // hashCode oneofs.
+  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+    printer->Print(
+      "switch ($oneof_name$Case_) {\n",
+      "oneof_name",
+      context_->GetOneofGeneratorInfo(
+          descriptor_->oneof_decl(i))->name);
+    printer->Indent();
+    for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
+      const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
+      printer->Print(
+        "case $field_number$:\n",
+        "field_number",
+        SimpleItoa(field->number()));
+      printer->Indent();
+      field_generators_.get(field).GenerateHashCode(printer);
+      printer->Print("break;\n");
+      printer->Outdent();
+    }
+    printer->Print(
+      "case 0:\n"
+      "default:\n");
+    printer->Outdent();
+    printer->Print("}\n");
+  }
+
   if (descriptor_->extension_range_count() > 0) {
     printer->Print(
       "hash = hashFields(hash, getExtensionFields());\n");
@@ -1105,7 +1165,8 @@
   printer->Print(
       "private $classname$(\n"
       "    com.google.protobuf.CodedInputStream input,\n"
-      "    com.google.protobuf.ExtensionRegistryLite extensionRegistry) {\n",
+      "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+      "    throws com.google.protobuf.InvalidProtocolBufferException {\n",
       "classname", descriptor_->name());
   printer->Indent();
 
@@ -1215,10 +1276,10 @@
   printer->Outdent();
   printer->Print(
       "} catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
-      "  throw new RuntimeException(e.setUnfinishedMessage(this));\n"
+      "  throw e.setUnfinishedMessage(this);\n"
       "} catch (java.io.IOException e) {\n"
-      "  throw new RuntimeException(new com.google.protobuf.InvalidProtocolBufferException(e)\n"
-      "      .setUnfinishedMessage(this));\n"
+      "  throw new com.google.protobuf.InvalidProtocolBufferException(\n"
+      "      e).setUnfinishedMessage(this);\n"
       "} finally {\n");
   printer->Indent();
 
@@ -1260,20 +1321,9 @@
       "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
       "    throws com.google.protobuf.InvalidProtocolBufferException {\n",
       "classname", descriptor_->name());
-  if (HasGeneratedMethods(descriptor_)) {
-    // The parsing constructor throws an InvalidProtocolBufferException via a
-    // RuntimeException to aid in method pruning. We unwrap it here.
+  if (context_->HasGeneratedMethods(descriptor_)) {
     printer->Print(
-        "  try {\n"
-        "    return new $classname$(input, extensionRegistry);\n"
-        "  } catch (RuntimeException e) {\n"
-        "    if (e.getCause() instanceof\n"
-        "        com.google.protobuf.InvalidProtocolBufferException) {\n"
-        "      throw (com.google.protobuf.InvalidProtocolBufferException)\n"
-        "          e.getCause();\n"
-        "    }\n"
-        "    throw e;\n"
-        "  }\n",
+        "    return new $classname$(input, extensionRegistry);\n",
         "classname", descriptor_->name());
   } else {
     // When parsing constructor isn't generated, use builder to parse
@@ -1328,14 +1378,39 @@
 void ImmutableMessageGenerator::GenerateAnyMethods(io::Printer* printer) {
   printer->Print(
     "private static String getTypeUrl(\n"
+    "    java.lang.String typeUrlPrefix,\n"
     "    com.google.protobuf.Descriptors.Descriptor descriptor) {\n"
-    "  return \"type.googleapis.com/\" + descriptor.getFullName();\n"
+    "  return typeUrlPrefix.endsWith(\"/\")\n"
+    "      ? typeUrlPrefix + descriptor.getFullName()\n"
+    "      : typeUrlPrefix + \"/\" + descriptor.getFullName();\n"
+    "}\n"
+    "\n"
+    "private static String getTypeNameFromTypeUrl(\n"
+    "    java.lang.String typeUrl) {\n"
+    "  int pos = typeUrl.lastIndexOf('/');\n"
+    "  return pos == -1 ? \"\" : typeUrl.substring(pos + 1);\n"
     "}\n"
     "\n"
     "public static <T extends com.google.protobuf.Message> Any pack(\n"
     "    T message) {\n"
     "  return Any.newBuilder()\n"
-    "      .setTypeUrl(getTypeUrl(message.getDescriptorForType()))\n"
+    "      .setTypeUrl(getTypeUrl(\"type.googleapis.com\",\n"
+    "                             message.getDescriptorForType()))\n"
+    "      .setValue(message.toByteString())\n"
+    "      .build();\n"
+    "}\n"
+    "\n"
+    "/**\n"
+    " * Packs a message uisng the given type URL prefix. The type URL will\n"
+    " * be constructed by concatenating the message type's full name to the\n"
+    " * prefix with an optional \"/\" separator if the prefix doesn't end\n"
+    " * with \"/\" already.\n"
+    " */\n"
+    "public static <T extends com.google.protobuf.Message> Any pack(\n"
+    "    T message, java.lang.String typeUrlPrefix) {\n"
+    "  return Any.newBuilder()\n"
+    "      .setTypeUrl(getTypeUrl(typeUrlPrefix,\n"
+    "                             message.getDescriptorForType()))\n"
     "      .setValue(message.toByteString())\n"
     "      .build();\n"
     "}\n"
@@ -1344,8 +1419,8 @@
     "    java.lang.Class<T> clazz) {\n"
     "  T defaultInstance =\n"
     "      com.google.protobuf.Internal.getDefaultInstance(clazz);\n"
-    "  return getTypeUrl().equals(\n"
-    "      getTypeUrl(defaultInstance.getDescriptorForType()));\n"
+    "  return getTypeNameFromTypeUrl(getTypeUrl()).equals(\n"
+    "      defaultInstance.getDescriptorForType().getFullName());\n"
     "}\n"
     "\n"
     "private volatile com.google.protobuf.Message cachedUnpackValue;\n"
diff --git a/src/google/protobuf/compiler/java/java_message.h b/src/google/protobuf/compiler/java/java_message.h
index be5bfb0..e9fc57c 100644
--- a/src/google/protobuf/compiler/java/java_message.h
+++ b/src/google/protobuf/compiler/java/java_message.h
@@ -56,6 +56,8 @@
 namespace compiler {
 namespace java {
 
+static const int kMaxStaticSize = 1 << 15;  // aka 32k
+
 class MessageGenerator {
  public:
   explicit MessageGenerator(const Descriptor* descriptor);
@@ -64,7 +66,8 @@
   // All static variables have to be declared at the top-level of the file
   // so that we can control initialization order, which is important for
   // DescriptorProto bootstrapping to work.
-  virtual void GenerateStaticVariables(io::Printer* printer) = 0;
+  virtual void GenerateStaticVariables(
+      io::Printer* printer, int* bytecode_estimate) = 0;
 
   // Output code which initializes the static variables generated by
   // GenerateStaticVariables(). Returns an estimate of bytecode size.
@@ -96,14 +99,15 @@
   virtual void Generate(io::Printer* printer);
   virtual void GenerateInterface(io::Printer* printer);
   virtual void GenerateExtensionRegistrationCode(io::Printer* printer);
-  virtual void GenerateStaticVariables(io::Printer* printer);
+  virtual void GenerateStaticVariables(
+      io::Printer* printer, int* bytecode_estimate);
 
   // Returns an estimate of the number of bytes the printed code will compile to
   virtual int GenerateStaticVariableInitializers(io::Printer* printer);
 
  private:
 
-  void GenerateFieldAccessorTable(io::Printer* printer);
+  void GenerateFieldAccessorTable(io::Printer* printer, int* bytecode_estimate);
 
   // Returns an estimate of the number of bytes the printed code will compile to
   int GenerateFieldAccessorTableInitializer(io::Printer* printer);
diff --git a/src/google/protobuf/compiler/java/java_message_builder.cc b/src/google/protobuf/compiler/java/java_message_builder.cc
index 5d53503..b3e9e98 100644
--- a/src/google/protobuf/compiler/java/java_message_builder.cc
+++ b/src/google/protobuf/compiler/java/java_message_builder.cc
@@ -81,8 +81,9 @@
   : descriptor_(descriptor), context_(context),
     name_resolver_(context->GetNameResolver()),
     field_generators_(descriptor, context_) {
-  GOOGLE_CHECK_NE(
-      FileOptions::LITE_RUNTIME, descriptor->file()->options().optimize_for());
+  GOOGLE_CHECK(HasDescriptorMethods(descriptor->file(), context->EnforceLite()))
+      << "Generator factory error: A non-lite message generator is used to "
+         "generate lite messages.";
 }
 
 MessageBuilderGenerator::~MessageBuilderGenerator() {}
@@ -113,7 +114,7 @@
   GenerateDescriptorMethods(printer);
   GenerateCommonBuilderMethods(printer);
 
-  if (HasGeneratedMethods(descriptor_)) {
+  if (context_->HasGeneratedMethods(descriptor_)) {
     GenerateIsInitialized(printer);
     GenerateBuilderParsingMethods(printer);
   }
@@ -134,7 +135,7 @@
     printer->Print(vars,
       "public $oneof_capitalized_name$Case\n"
       "    get$oneof_capitalized_name$Case() {\n"
-      "  return $oneof_capitalized_name$Case.valueOf(\n"
+      "  return $oneof_capitalized_name$Case.forNumber(\n"
       "      $oneof_name$Case_);\n"
       "}\n"
       "\n"
@@ -439,7 +440,7 @@
 
   // -----------------------------------------------------------------
 
-  if (HasGeneratedMethods(descriptor_)) {
+  if (context_->HasGeneratedMethods(descriptor_)) {
     printer->Print(
       "public Builder mergeFrom(com.google.protobuf.Message other) {\n"
       "  if (other instanceof $classname$) {\n"
diff --git a/src/google/protobuf/compiler/java/java_message_builder_lite.cc b/src/google/protobuf/compiler/java/java_message_builder_lite.cc
index 8719d00..dd429dc 100644
--- a/src/google/protobuf/compiler/java/java_message_builder_lite.cc
+++ b/src/google/protobuf/compiler/java/java_message_builder_lite.cc
@@ -81,8 +81,9 @@
   : descriptor_(descriptor), context_(context),
     name_resolver_(context->GetNameResolver()),
     field_generators_(descriptor, context_) {
-  GOOGLE_CHECK_EQ(
-      FileOptions::LITE_RUNTIME, descriptor->file()->options().optimize_for());
+  GOOGLE_CHECK(!HasDescriptorMethods(descriptor->file(), context->EnforceLite()))
+      << "Generator factory error: A lite message generator is used to "
+         "generate non-lite messages.";
 }
 
 MessageBuilderLiteGenerator::~MessageBuilderLiteGenerator() {}
@@ -148,20 +149,6 @@
                      .GenerateBuilderMembers(printer);
   }
 
-  if (!PreserveUnknownFields(descriptor_)) {
-    printer->Print(
-      "public final Builder setUnknownFields(\n"
-      "    final com.google.protobuf.UnknownFieldSet unknownFields) {\n"
-      "  return this;\n"
-      "}\n"
-      "\n"
-      "public final Builder mergeUnknownFields(\n"
-      "    final com.google.protobuf.UnknownFieldSet unknownFields) {\n"
-      "  return this;\n"
-      "}\n"
-      "\n");
-  }
-
   printer->Print(
     "\n"
     "// @@protoc_insertion_point(builder_scope:$full_name$)\n",
diff --git a/src/google/protobuf/compiler/java/java_message_field.cc b/src/google/protobuf/compiler/java/java_message_field.cc
index b5f8e62..455516f 100644
--- a/src/google/protobuf/compiler/java/java_message_field.cc
+++ b/src/google/protobuf/compiler/java/java_message_field.cc
@@ -70,8 +70,7 @@
   // by the proto compiler
   (*variables)["deprecation"] = descriptor->options().deprecated()
       ? "@java.lang.Deprecated " : "";
-  (*variables)["on_changed"] =
-      HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
+  (*variables)["on_changed"] = "onChanged();";
 
   if (SupportFieldPresence(descriptor->file())) {
     // For singular messages and builders, one bit is used for the hasField bit.
diff --git a/src/google/protobuf/compiler/java/java_message_field_lite.cc b/src/google/protobuf/compiler/java/java_message_field_lite.cc
index 356520e..049679d 100644
--- a/src/google/protobuf/compiler/java/java_message_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_message_field_lite.cc
@@ -70,8 +70,6 @@
   // by the proto compiler
   (*variables)["deprecation"] = descriptor->options().deprecated()
       ? "@java.lang.Deprecated " : "";
-  (*variables)["on_changed"] =
-      HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
 
   if (SupportFieldPresence(descriptor->file())) {
     // For singular messages and builders, one bit is used for the hasField bit.
@@ -867,7 +865,6 @@
     "    ensure$capitalized_name$IsMutable();\n"
     "    $name$_.addAll(other.$name$_);\n"
     "  }\n"
-    "  $on_changed$\n"
     "}\n");
 }
 
diff --git a/src/google/protobuf/compiler/java/java_message_lite.cc b/src/google/protobuf/compiler/java/java_message_lite.cc
index 94ed2c3..14cc908 100644
--- a/src/google/protobuf/compiler/java/java_message_lite.cc
+++ b/src/google/protobuf/compiler/java/java_message_lite.cc
@@ -46,7 +46,7 @@
 #include <google/protobuf/compiler/java/java_context.h>
 #include <google/protobuf/compiler/java/java_doc_comment.h>
 #include <google/protobuf/compiler/java/java_enum_lite.h>
-#include <google/protobuf/compiler/java/java_extension.h>
+#include <google/protobuf/compiler/java/java_extension_lite.h>
 #include <google/protobuf/compiler/java/java_generator_factory.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/compiler/java/java_message_builder.h>
@@ -87,19 +87,20 @@
   : MessageGenerator(descriptor), context_(context),
     name_resolver_(context->GetNameResolver()),
     field_generators_(descriptor, context_) {
-  GOOGLE_CHECK_EQ(
-      FileOptions::LITE_RUNTIME, descriptor->file()->options().optimize_for());
+  GOOGLE_CHECK(!HasDescriptorMethods(descriptor->file(), context->EnforceLite()))
+      << "Generator factory error: A lite message generator is used to "
+         "generate non-lite messages.";
 }
 
 ImmutableMessageLiteGenerator::~ImmutableMessageLiteGenerator() {}
 
 void ImmutableMessageLiteGenerator::GenerateStaticVariables(
-    io::Printer* printer) {
+    io::Printer* printer, int* bytecode_estimate) {
   // Generate static members for all nested types.
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
     // TODO(kenton):  Reuse MessageGenerator objects?
     ImmutableMessageLiteGenerator(descriptor_->nested_type(i), context_)
-      .GenerateStaticVariables(printer);
+        .GenerateStaticVariables(printer, bytecode_estimate);
   }
 }
 
@@ -197,6 +198,7 @@
   }
   printer->Indent();
 
+
   GenerateParsingConstructor(printer);
 
   // Nested types
@@ -259,12 +261,20 @@
       "cap_oneof_name",
       ToUpper(vars["oneof_name"]));
     printer->Print(vars,
-      "private int value = 0;\n"
+      "private final int value;\n"
       "private $oneof_capitalized_name$Case(int value) {\n"
       "  this.value = value;\n"
       "}\n");
     printer->Print(vars,
+      "/**\n"
+      " * @deprecated Use {@link #forNumber(int)} instead.\n"
+      " */\n"
+      "@java.lang.Deprecated\n"
       "public static $oneof_capitalized_name$Case valueOf(int value) {\n"
+      "  return forNumber(value);\n"
+      "}\n"
+      "\n"
+      "public static $oneof_capitalized_name$Case forNumber(int value) {\n"
       "  switch (value) {\n");
     for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
       const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
@@ -277,8 +287,7 @@
     }
     printer->Print(
       "    case 0: return $cap_oneof_name$_NOT_SET;\n"
-      "    default: throw new java.lang.IllegalArgumentException(\n"
-      "      \"Value is undefined for this oneof enum.\");\n"
+      "    default: return null;\n"
       "  }\n"
       "}\n"
       "public int getNumber() {\n"
@@ -291,7 +300,7 @@
     printer->Print(vars,
       "public $oneof_capitalized_name$Case\n"
       "get$oneof_capitalized_name$Case() {\n"
-      "  return $oneof_capitalized_name$Case.valueOf(\n"
+      "  return $oneof_capitalized_name$Case.forNumber(\n"
       "      $oneof_name$Case_);\n"
       "}\n"
       "\n"
@@ -317,7 +326,6 @@
     GenerateEqualsAndHashCode(printer);
   }
 
-
   GenerateParseFromMethods(printer);
   GenerateBuilder(printer);
 
@@ -446,7 +454,7 @@
   // because the DEFAULT_INSTANCE is used by the extension to lazily retrieve
   // the outer class's FileDescriptor.
   for (int i = 0; i < descriptor_->extension_count(); i++) {
-    ImmutableExtensionGenerator(descriptor_->extension(i), context_)
+    ImmutableExtensionLiteGenerator(descriptor_->extension(i), context_)
         .Generate(printer);
   }
 
@@ -557,9 +565,6 @@
     "  return size;\n"
     "}\n"
     "\n");
-
-  printer->Print(
-    "private static final long serialVersionUID = 0L;\n");
 }
 
 void ImmutableMessageLiteGenerator::
@@ -571,54 +576,62 @@
     "public static $classname$ parseFrom(\n"
     "    com.google.protobuf.ByteString data)\n"
     "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
-    "  return parser().parseFrom(data);\n"
+    "  return com.google.protobuf.GeneratedMessageLite.parseFrom(\n"
+    "      DEFAULT_INSTANCE, data);\n"
     "}\n"
     "public static $classname$ parseFrom(\n"
     "    com.google.protobuf.ByteString data,\n"
     "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
     "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
-    "  return parser().parseFrom(data, extensionRegistry);\n"
+    "  return com.google.protobuf.GeneratedMessageLite.parseFrom(\n"
+    "      DEFAULT_INSTANCE, data, extensionRegistry);\n"
     "}\n"
     "public static $classname$ parseFrom(byte[] data)\n"
     "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
-    "  return parser().parseFrom(data);\n"
+    "  return com.google.protobuf.GeneratedMessageLite.parseFrom(\n"
+    "      DEFAULT_INSTANCE, data);\n"
     "}\n"
     "public static $classname$ parseFrom(\n"
     "    byte[] data,\n"
     "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
     "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
-    "  return parser().parseFrom(data, extensionRegistry);\n"
+    "  return com.google.protobuf.GeneratedMessageLite.parseFrom(\n"
+    "      DEFAULT_INSTANCE, data, extensionRegistry);\n"
     "}\n"
     "public static $classname$ parseFrom(java.io.InputStream input)\n"
     "    throws java.io.IOException {\n"
-    "  return parser().parseFrom(input);\n"
+    "  return com.google.protobuf.GeneratedMessageLite.parseFrom(\n"
+    "      DEFAULT_INSTANCE, input);\n"
     "}\n"
     "public static $classname$ parseFrom(\n"
     "    java.io.InputStream input,\n"
     "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
     "    throws java.io.IOException {\n"
-    "  return parser().parseFrom(input, extensionRegistry);\n"
+    "  return com.google.protobuf.GeneratedMessageLite.parseFrom(\n"
+    "      DEFAULT_INSTANCE, input, extensionRegistry);\n"
     "}\n"
     "public static $classname$ parseDelimitedFrom(java.io.InputStream input)\n"
     "    throws java.io.IOException {\n"
-    "  return parser().parseDelimitedFrom(input);\n"
+    "  return parseDelimitedFrom(DEFAULT_INSTANCE, input);\n"
     "}\n"
     "public static $classname$ parseDelimitedFrom(\n"
     "    java.io.InputStream input,\n"
     "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
     "    throws java.io.IOException {\n"
-    "  return parser().parseDelimitedFrom(input, extensionRegistry);\n"
+    "  return parseDelimitedFrom(DEFAULT_INSTANCE, input, extensionRegistry);\n"
     "}\n"
     "public static $classname$ parseFrom(\n"
     "    com.google.protobuf.CodedInputStream input)\n"
     "    throws java.io.IOException {\n"
-    "  return parser().parseFrom(input);\n"
+    "  return com.google.protobuf.GeneratedMessageLite.parseFrom(\n"
+    "      DEFAULT_INSTANCE, input);\n"
     "}\n"
     "public static $classname$ parseFrom(\n"
     "    com.google.protobuf.CodedInputStream input,\n"
     "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
     "    throws java.io.IOException {\n"
-    "  return parser().parseFrom(input, extensionRegistry);\n"
+    "  return com.google.protobuf.GeneratedMessageLite.parseFrom(\n"
+    "      DEFAULT_INSTANCE, input, extensionRegistry);\n"
     "}\n"
     "\n",
     "classname", name_resolver_->GetImmutableClassName(descriptor_));
@@ -906,24 +919,61 @@
     "classname", name_resolver_->GetImmutableClassName(descriptor_));
 
   printer->Print("boolean result = true;\n");
+  // Compare non-oneofs.
   for (int i = 0; i < descriptor_->field_count(); i++) {
     const FieldDescriptor* field = descriptor_->field(i);
-    const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
-    bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field);
-    if (check_has_bits) {
-      printer->Print(
-        "result = result && (has$name$() == other.has$name$());\n"
-        "if (has$name$()) {\n",
-        "name", info->capitalized_name);
-      printer->Indent();
-    }
-    field_generators_.get(field).GenerateEqualsCode(printer);
-    if (check_has_bits) {
-      printer->Outdent();
-      printer->Print(
-        "}\n");
+    if (field->containing_oneof() == NULL) {
+      const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+      bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field);
+      if (check_has_bits) {
+        printer->Print(
+          "result = result && (has$name$() == other.has$name$());\n"
+          "if (has$name$()) {\n",
+          "name", info->capitalized_name);
+        printer->Indent();
+      }
+      field_generators_.get(field).GenerateEqualsCode(printer);
+      if (check_has_bits) {
+        printer->Outdent();
+        printer->Print(
+          "}\n");
+      }
     }
   }
+
+  // Compare oneofs.
+  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+    printer->Print(
+      "result = result && get$oneof_capitalized_name$Case().equals(\n"
+      "    other.get$oneof_capitalized_name$Case());\n",
+      "oneof_capitalized_name",
+      context_->GetOneofGeneratorInfo(
+          descriptor_->oneof_decl(i))->capitalized_name);
+    printer->Print(
+      "if (!result) return false;\n"
+      "switch ($oneof_name$Case_) {\n",
+      "oneof_name",
+      context_->GetOneofGeneratorInfo(
+          descriptor_->oneof_decl(i))->name);
+    printer->Indent();
+    for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
+      const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
+      printer->Print(
+        "case $field_number$:\n",
+        "field_number",
+        SimpleItoa(field->number()));
+      printer->Indent();
+      field_generators_.get(field).GenerateEqualsCode(printer);
+      printer->Print("break;\n");
+      printer->Outdent();
+    }
+    printer->Print(
+      "case 0:\n"
+      "default:\n");
+    printer->Outdent();
+    printer->Print("}\n");
+  }
+
   if (PreserveUnknownFields(descriptor_)) {
     // Always consider unknown fields for equality. This will sometimes return
     // false for non-canonical ordering when running in LITE_RUNTIME but it's
@@ -957,21 +1007,50 @@
   printer->Print("hash = (19 * hash) + $classname$.class.hashCode();\n",
     "classname", name_resolver_->GetImmutableClassName(descriptor_));
 
+  // hashCode non-oneofs.
   for (int i = 0; i < descriptor_->field_count(); i++) {
     const FieldDescriptor* field = descriptor_->field(i);
-    const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
-    bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field);
-    if (check_has_bits) {
+    if (field->containing_oneof() == NULL) {
+      const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+      bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field);
+      if (check_has_bits) {
+        printer->Print(
+          "if (has$name$()) {\n",
+          "name", info->capitalized_name);
+        printer->Indent();
+      }
+      field_generators_.get(field).GenerateHashCode(printer);
+      if (check_has_bits) {
+        printer->Outdent();
+        printer->Print("}\n");
+      }
+    }
+  }
+
+  // hashCode oneofs.
+  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+    printer->Print(
+      "switch ($oneof_name$Case_) {\n",
+      "oneof_name",
+      context_->GetOneofGeneratorInfo(
+          descriptor_->oneof_decl(i))->name);
+    printer->Indent();
+    for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
+      const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
       printer->Print(
-        "if (has$name$()) {\n",
-        "name", info->capitalized_name);
+        "case $field_number$:\n",
+        "field_number",
+        SimpleItoa(field->number()));
       printer->Indent();
-    }
-    field_generators_.get(field).GenerateHashCode(printer);
-    if (check_has_bits) {
+      field_generators_.get(field).GenerateHashCode(printer);
+      printer->Print("break;\n");
       printer->Outdent();
-      printer->Print("}\n");
     }
+    printer->Print(
+      "case 0:\n"
+      "default:\n");
+    printer->Outdent();
+    printer->Print("}\n");
   }
 
   printer->Print(
@@ -990,7 +1069,7 @@
 void ImmutableMessageLiteGenerator::
 GenerateExtensionRegistrationCode(io::Printer* printer) {
   for (int i = 0; i < descriptor_->extension_count(); i++) {
-    ImmutableExtensionGenerator(descriptor_->extension(i), context_)
+    ImmutableExtensionLiteGenerator(descriptor_->extension(i), context_)
       .GenerateRegistrationCode(printer);
   }
 
@@ -1167,7 +1246,6 @@
   }
 }
 
-
 }  // namespace java
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/java/java_message_lite.h b/src/google/protobuf/compiler/java/java_message_lite.h
index 2bd3cdd..c8ee99b 100644
--- a/src/google/protobuf/compiler/java/java_message_lite.h
+++ b/src/google/protobuf/compiler/java/java_message_lite.h
@@ -54,7 +54,8 @@
   virtual void Generate(io::Printer* printer);
   virtual void GenerateInterface(io::Printer* printer);
   virtual void GenerateExtensionRegistrationCode(io::Printer* printer);
-  virtual void GenerateStaticVariables(io::Printer* printer);
+  virtual void GenerateStaticVariables(
+      io::Printer* printer, int* bytecode_estimate);
   virtual int GenerateStaticVariableInitializers(io::Printer* printer);
 
  private:
diff --git a/src/google/protobuf/compiler/java/java_name_resolver.cc b/src/google/protobuf/compiler/java/java_name_resolver.cc
index 0c363f9..bffe4f1 100644
--- a/src/google/protobuf/compiler/java/java_name_resolver.cc
+++ b/src/google/protobuf/compiler/java/java_name_resolver.cc
@@ -259,6 +259,13 @@
       descriptor->file(), true);
 }
 
+string ClassNameResolver::GetJavaImmutableClassName(
+    const EnumDescriptor* descriptor) {
+  return GetJavaClassFullName(
+      ClassNameWithoutPackage(descriptor, true),
+      descriptor->file(), true);
+}
+
 
 }  // namespace java
 }  // namespace compiler
diff --git a/src/google/protobuf/compiler/java/java_name_resolver.h b/src/google/protobuf/compiler/java/java_name_resolver.h
index ab60b0a..570d8d8 100644
--- a/src/google/protobuf/compiler/java/java_name_resolver.h
+++ b/src/google/protobuf/compiler/java/java_name_resolver.h
@@ -98,6 +98,7 @@
   // For example:
   //   com.package.OuterClass$OuterMessage$InnerMessage
   string GetJavaImmutableClassName(const Descriptor* descriptor);
+  string GetJavaImmutableClassName(const EnumDescriptor* descriptor);
  private:
   // Get the full name of a Java class by prepending the Java package name
   // or outer class name.
diff --git a/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc
index 178bbe1..e42ec28 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field.cc
+++ b/src/google/protobuf/compiler/java/java_primitive_field.cc
@@ -75,12 +75,7 @@
       "" : ("= " + ImmutableDefaultValue(descriptor, name_resolver));
   (*variables)["capitalized_type"] =
       GetCapitalizedType(descriptor, /* immutable = */ true);
-  if (descriptor->is_packed()) {
-    (*variables)["tag"] = SimpleItoa(WireFormatLite::MakeTag(
-        descriptor->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED));
-  } else {
-    (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
-  }
+  (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
   (*variables)["tag_size"] = SimpleItoa(
       WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
   if (IsReferenceType(GetJavaType(descriptor))) {
@@ -99,8 +94,7 @@
   if (fixed_size != -1) {
     (*variables)["fixed_size"] = SimpleItoa(fixed_size);
   }
-  (*variables)["on_changed"] =
-      HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
+  (*variables)["on_changed"] = "onChanged();";
 
   if (SupportFieldPresence(descriptor->file())) {
     // For singular messages and builders, one bit is used for the hasField bit.
@@ -606,7 +600,7 @@
     "}\n");
 
   if (descriptor_->is_packed() &&
-      HasGeneratedMethods(descriptor_->containing_type())) {
+      context_->HasGeneratedMethods(descriptor_->containing_type())) {
     printer->Print(variables_,
       "private int $name$MemoizedSerializedSize = -1;\n");
   }
diff --git a/src/google/protobuf/compiler/java/java_primitive_field_lite.cc b/src/google/protobuf/compiler/java/java_primitive_field_lite.cc
index 5a7bf82..d277e4f 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_primitive_field_lite.cc
@@ -129,8 +129,6 @@
   if (fixed_size != -1) {
     (*variables)["fixed_size"] = SimpleItoa(fixed_size);
   }
-  (*variables)["on_changed"] =
-      HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
 
   if (SupportFieldPresence(descriptor->file())) {
     // For singular messages and builders, one bit is used for the hasField bit.
@@ -635,7 +633,7 @@
     "}\n");
 
   if (descriptor_->options().packed() &&
-      HasGeneratedMethods(descriptor_->containing_type())) {
+      context_->HasGeneratedMethods(descriptor_->containing_type())) {
     printer->Print(variables_,
       "private int $name$MemoizedSerializedSize = -1;\n");
   }
@@ -758,7 +756,6 @@
     "    ensure$capitalized_name$IsMutable();\n"
     "    $name$_.addAll(other.$name$_);\n"
     "  }\n"
-    "  $on_changed$\n"
     "}\n");
 }
 
diff --git a/src/google/protobuf/compiler/java/java_shared_code_generator.cc b/src/google/protobuf/compiler/java/java_shared_code_generator.cc
index 7017736..74253c3 100644
--- a/src/google/protobuf/compiler/java/java_shared_code_generator.cc
+++ b/src/google/protobuf/compiler/java/java_shared_code_generator.cc
@@ -52,8 +52,9 @@
 namespace java {
 
 SharedCodeGenerator::SharedCodeGenerator(const FileDescriptor* file)
-  : name_resolver_(new ClassNameResolver), file_(file) {
-}
+    : name_resolver_(new ClassNameResolver),
+      enforce_lite_(false),
+      file_(file) {}
 
 SharedCodeGenerator::~SharedCodeGenerator() {
 }
@@ -63,7 +64,7 @@
   string java_package = FileJavaPackage(file_);
   string package_dir = JavaPackageToDir(java_package);
 
-  if (HasDescriptorMethods(file_)) {
+  if (HasDescriptorMethods(file_, enforce_lite_)) {
     // Generate descriptors.
     string classname = name_resolver_->GetDescriptorClassName(file_);
     string filename = package_dir + classname + ".java";
diff --git a/src/google/protobuf/compiler/java/java_shared_code_generator.h b/src/google/protobuf/compiler/java/java_shared_code_generator.h
index 38a32fc..3b573c0 100644
--- a/src/google/protobuf/compiler/java/java_shared_code_generator.h
+++ b/src/google/protobuf/compiler/java/java_shared_code_generator.h
@@ -72,6 +72,10 @@
   void Generate(GeneratorContext* generator_context,
                 vector<string>* file_list);
 
+  void SetEnforceLite(bool value) {
+    enforce_lite_ = value;
+  }
+
   void GenerateDescriptors(io::Printer* printer);
 
  private:
@@ -81,6 +85,7 @@
   bool ShouldIncludeDependency(const FileDescriptor* descriptor);
 
   google::protobuf::scoped_ptr<ClassNameResolver> name_resolver_;
+  bool enforce_lite_;
   const FileDescriptor* file_;
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SharedCodeGenerator);
 };
diff --git a/src/google/protobuf/compiler/java/java_string_field.cc b/src/google/protobuf/compiler/java/java_string_field.cc
index 7f757e4..b67eeb5 100644
--- a/src/google/protobuf/compiler/java/java_string_field.cc
+++ b/src/google/protobuf/compiler/java/java_string_field.cc
@@ -87,8 +87,7 @@
   // by the proto compiler
   (*variables)["deprecation"] = descriptor->options().deprecated()
       ? "@java.lang.Deprecated " : "";
-  (*variables)["on_changed"] =
-      HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
+  (*variables)["on_changed"] = "onChanged();";
 
   if (SupportFieldPresence(descriptor->file())) {
     // For singular messages and builders, one bit is used for the hasField bit.
@@ -408,15 +407,6 @@
       "java.lang.String s = input.readStringRequireUtf8();\n"
       "$set_has_field_bit_message$\n"
       "$name$_ = s;\n");
-  } else if (!HasDescriptorMethods(descriptor_->file())) {
-    // Lite runtime should attempt to reduce allocations by attempting to
-    // construct the string directly from the input stream buffer. This avoids
-    // spurious intermediary ByteString allocations, cutting overall allocations
-    // in half.
-    printer->Print(variables_,
-      "java.lang.String s = input.readString();\n"
-      "$set_has_field_bit_message$\n"
-      "$name$_ = s;\n");
   } else {
     printer->Print(variables_,
       "com.google.protobuf.ByteString bs = input.readBytes();\n"
@@ -668,15 +658,6 @@
       "java.lang.String s = input.readStringRequireUtf8();\n"
       "$set_oneof_case_message$;\n"
       "$oneof_name$_ = s;\n");
-  } else if (!HasDescriptorMethods(descriptor_->file())) {
-    // Lite runtime should attempt to reduce allocations by attempting to
-    // construct the string directly from the input stream buffer. This avoids
-    // spurious intermediary ByteString allocations, cutting overall allocations
-    // in half.
-    printer->Print(variables_,
-      "java.lang.String s = input.readString();\n"
-      "$set_oneof_case_message$;\n"
-      "$oneof_name$_ = s;\n");
   } else {
     printer->Print(variables_,
       "com.google.protobuf.ByteString bs = input.readBytes();\n"
@@ -934,13 +915,6 @@
   if (CheckUtf8(descriptor_)) {
     printer->Print(variables_,
     "java.lang.String s = input.readStringRequireUtf8();\n");
-  } else if (!HasDescriptorMethods(descriptor_->file())) {
-    // Lite runtime should attempt to reduce allocations by attempting to
-    // construct the string directly from the input stream buffer. This avoids
-    // spurious intermediary ByteString allocations, cutting overall allocations
-    // in half.
-    printer->Print(variables_,
-    "java.lang.String s = input.readString();\n");
   } else {
     printer->Print(variables_,
     "com.google.protobuf.ByteString bs = input.readBytes();\n");
@@ -950,7 +924,7 @@
     "  $name$_ = new com.google.protobuf.LazyStringArrayList();\n"
     "  $set_mutable_bit_parser$;\n"
     "}\n");
-  if (CheckUtf8(descriptor_) || !HasDescriptorMethods(descriptor_->file())) {
+  if (CheckUtf8(descriptor_)) {
     printer->Print(variables_,
       "$name$_.add(s);\n");
   } else {
diff --git a/src/google/protobuf/compiler/java/java_string_field_lite.cc b/src/google/protobuf/compiler/java/java_string_field_lite.cc
index eb5964b..9012ab5 100644
--- a/src/google/protobuf/compiler/java/java_string_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_string_field_lite.cc
@@ -84,8 +84,6 @@
   // by the proto compiler
   (*variables)["deprecation"] = descriptor->options().deprecated()
       ? "@java.lang.Deprecated " : "";
-  (*variables)["on_changed"] =
-      HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
 
   if (SupportFieldPresence(descriptor->file())) {
     // For singular messages and builders, one bit is used for the hasField bit.
@@ -103,7 +101,7 @@
     (*variables)["clear_has_field_bit_message"] = "";
 
     (*variables)["is_field_present_message"] =
-        "!get" + (*variables)["capitalized_name"] + ".isEmpty()";
+        "!" + (*variables)["name"] + "_.isEmpty()";
   }
 
   // For repeated builders, the underlying list tracks mutability state.
@@ -309,13 +307,11 @@
       "if (other.has$capitalized_name$()) {\n"
       "  $set_has_field_bit_message$\n"
       "  $name$_ = other.$name$_;\n"
-      "  $on_changed$\n"
       "}\n");
   } else {
     printer->Print(variables_,
       "if (!other.get$capitalized_name$().isEmpty()) {\n"
       "  $name$_ = other.$name$_;\n"
-      "  $on_changed$\n"
       "}\n");
   }
 }
@@ -528,8 +524,7 @@
   // all string fields to Strings when copying fields from a Message.
   printer->Print(variables_,
     "$set_oneof_case_message$;\n"
-    "$oneof_name$_ = other.$oneof_name$_;\n"
-    "$on_changed$\n");
+    "$oneof_name$_ = other.$oneof_name$_;\n");
 }
 
 void ImmutableStringOneofFieldLiteGenerator::
@@ -792,7 +787,6 @@
     "    ensure$capitalized_name$IsMutable();\n"
     "    $name$_.addAll(other.$name$_);\n"
     "  }\n"
-    "  $on_changed$\n"
     "}\n");
 }
 
@@ -819,13 +813,8 @@
     "if (!$is_mutable$) {\n"
     "  $name$_ = com.google.protobuf.GeneratedMessageLite.newProtobufList();\n"
     "}\n");
-  if (CheckUtf8(descriptor_) || !HasDescriptorMethods(descriptor_->file())) {
-    printer->Print(variables_,
-      "$name$_.add(s);\n");
-  } else {
-    printer->Print(variables_,
-      "$name$_.add(bs);\n");
-  }
+  printer->Print(variables_,
+    "$name$_.add(s);\n");
 }
 
 void RepeatedImmutableStringFieldLiteGenerator::
diff --git a/src/google/protobuf/compiler/javanano/javanano_generator.cc b/src/google/protobuf/compiler/javanano/javanano_generator.cc
index a33eba1..a342e6b 100644
--- a/src/google/protobuf/compiler/javanano/javanano_generator.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_generator.cc
@@ -68,12 +68,7 @@
   }
   if (file->options().has_java_package()) {
     string result = file->options().java_package();
-    if (!file->options().javanano_use_deprecated_package()) {
-      if (!result.empty()) {
-        result += ".";
-      }
-      result += "nano";
-    }
+    result += "nano";
     params.set_java_package(
       file->name(), result);
   }
diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.cc b/src/google/protobuf/compiler/javanano/javanano_helpers.cc
index 5465655..02811a2 100644
--- a/src/google/protobuf/compiler/javanano/javanano_helpers.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_helpers.cc
@@ -201,12 +201,10 @@
       result += file->package();
     }
 
-    if (!file->options().javanano_use_deprecated_package()) {
-      if (!result.empty()) {
-        result += ".";
-      }
-      result += "nano";
+    if (!result.empty()) {
+      result += ".";
     }
+    result += "nano";
 
     return result;
   }
diff --git a/src/google/protobuf/compiler/js/js_generator.cc b/src/google/protobuf/compiler/js/js_generator.cc
index 0de7e2c..534a5b5 100755
--- a/src/google/protobuf/compiler/js/js_generator.cc
+++ b/src/google/protobuf/compiler/js/js_generator.cc
@@ -28,7 +28,7 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#include <google/protobuf/compiler/js/js_generator.h>
+#include "google/protobuf/compiler/js/js_generator.h"
 
 #include <assert.h>
 #include <algorithm>
@@ -123,6 +123,16 @@
 
 namespace {
 
+// The mode of operation for bytes fields. Historically JSPB always carried
+// bytes as JS {string}, containing base64 content by convention. With binary
+// and proto3 serialization the new convention is to represent it as binary
+// data in Uint8Array. See b/26173701 for background on the migration.
+enum BytesMode {
+  BYTES_DEFAULT,  // Default type for getBytesField to return.
+  BYTES_B64,      // Explicitly coerce to base64 string where needed.
+  BYTES_U8,       // Explicitly coerce to Uint8Array where needed.
+};
+
 bool IsReserved(const string& ident) {
   for (int i = 0; i < kNumKeyword; i++) {
     if (ident == kKeyword[i]) {
@@ -134,7 +144,7 @@
 
 // Returns a copy of |filename| with any trailing ".protodevel" or ".proto
 // suffix stripped.
-// TODO(robinson): Unify with copy in compiler/cpp/internal/helpers.cc.
+// TODO(haberman): Unify with copy in compiler/cpp/internal/helpers.cc.
 string StripProto(const string& filename) {
   const char* suffix = HasSuffixString(filename, ".protodevel")
       ? ".protodevel" : ".proto";
@@ -144,9 +154,7 @@
 // Given a filename like foo/bar/baz.proto, returns the correspoding JavaScript
 // file foo/bar/baz.js.
 string GetJSFilename(const string& filename) {
-  const char* suffix = HasSuffixString(filename, ".protodevel")
-      ? ".protodevel" : ".proto";
-  return StripSuffixString(filename, suffix) + "_pb.js";
+  return StripProto(filename) + "_pb.js";
 }
 
 // Given a filename like foo/bar/baz.proto, returns the root directory
@@ -385,15 +393,47 @@
   return result;
 }
 
+// When we're generating one output file per type name, this is the filename
+// that top-level extensions should go in.
+string GetExtensionFileName(const GeneratorOptions& options,
+                            const FileDescriptor* file) {
+  return options.output_dir + "/" + ToFileName(GetPath(options, file)) + ".js";
+}
+
+// When we're generating one output file per type name, this is the filename
+// that a top-level message should go in.
+string GetMessageFileName(const GeneratorOptions& options,
+                          const Descriptor* desc) {
+  return options.output_dir + "/" + ToFileName(desc->name()) + ".js";
+}
+
+// When we're generating one output file per type name, this is the filename
+// that a top-level message should go in.
+string GetEnumFileName(const GeneratorOptions& options,
+                       const EnumDescriptor* desc) {
+  return options.output_dir + "/" + ToFileName(desc->name()) + ".js";
+}
+
 // Returns the message/response ID, if set.
 string GetMessageId(const Descriptor* desc) {
   return string();
 }
 
+bool IgnoreExtensionField(const FieldDescriptor* field) {
+  // Exclude descriptor extensions from output "to avoid clutter" (from original
+  // codegen).
+  return field->is_extension() &&
+         field->containing_type()->file()->name() ==
+             "google/protobuf/descriptor.proto";
+}
+
 
 // Used inside Google only -- do not remove.
 bool IsResponse(const Descriptor* desc) { return false; }
-bool IgnoreField(const FieldDescriptor* field) { return false; }
+
+bool IgnoreField(const FieldDescriptor* field) {
+  return IgnoreExtensionField(field);
+}
 
 
 // Does JSPB ignore this entire oneof? True only if all fields are ignored.
@@ -438,12 +478,32 @@
   return name;
 }
 
+string JSByteGetterSuffix(BytesMode bytes_mode) {
+  switch (bytes_mode) {
+    case BYTES_DEFAULT:
+      return "";
+    case BYTES_B64:
+      return "B64";
+    case BYTES_U8:
+      return "U8";
+    default:
+      assert(false);
+  }
+}
+
 // Returns the field name as a capitalized portion of a getter/setter method
 // name, e.g. MyField for .getMyField().
-string JSGetterName(const FieldDescriptor* field) {
+string JSGetterName(const FieldDescriptor* field,
+                    BytesMode bytes_mode = BYTES_DEFAULT) {
   string name = JSIdent(field,
                         /* is_upper_camel = */ true,
                         /* is_map = */ false);
+  if (field->type() == FieldDescriptor::TYPE_BYTES) {
+    string suffix = JSByteGetterSuffix(bytes_mode);
+    if (!suffix.empty()) {
+      name += "_as" + suffix;
+    }
+  }
   if (name == "Extension" || name == "JsPbMessageId") {
     // Avoid conflicts with base-class names.
     name += "$";
@@ -504,8 +564,7 @@
   return SimpleItoa(index);
 }
 
-// Decodes a codepoint in \x0000 -- \xFFFF. Since JS strings are UTF-16, we only
-// need to handle the BMP (16-bit range) here.
+// Decodes a codepoint in \x0000 -- \xFFFF.
 uint16 DecodeUTF8Codepoint(uint8* bytes, size_t* length) {
   if (*length == 0) {
     return 0;
@@ -542,80 +601,56 @@
 }
 
 // Escapes the contents of a string to be included within double-quotes ("") in
-// JavaScript. |is_utf8| determines whether the input data (in a C++ string of
-// chars) is UTF-8 encoded (in which case codepoints become JavaScript string
-// characters, escaped with 16-bit hex escapes where necessary) or raw binary
-// (in which case bytes become JavaScript string characters 0 -- 255).
-string EscapeJSString(const string& in, bool is_utf8) {
-  string result;
+// JavaScript. The input data should be a UTF-8 encoded C++ string of chars.
+// Returns false if |out| was truncated because |in| contained invalid UTF-8 or
+// codepoints outside the BMP.
+// TODO(lukestebbing): Support codepoints outside the BMP.
+bool EscapeJSString(const string& in, string* out) {
   size_t decoded = 0;
   for (size_t i = 0; i < in.size(); i += decoded) {
     uint16 codepoint = 0;
-    if (is_utf8) {
-      // Decode the next UTF-8 codepoint.
-      size_t have_bytes = in.size() - i;
-      uint8 bytes[3] = {
+    // Decode the next UTF-8 codepoint.
+    size_t have_bytes = in.size() - i;
+    uint8 bytes[3] = {
         static_cast<uint8>(in[i]),
         static_cast<uint8>(((i + 1) < in.size()) ? in[i + 1] : 0),
         static_cast<uint8>(((i + 2) < in.size()) ? in[i + 2] : 0),
-      };
-      codepoint = DecodeUTF8Codepoint(bytes, &have_bytes);
-      if (have_bytes == 0) {
-        break;
-      }
-      decoded = have_bytes;
-    } else {
-      codepoint = static_cast<uint16>(static_cast<uint8>(in[i]));
-      decoded = 1;
+    };
+    codepoint = DecodeUTF8Codepoint(bytes, &have_bytes);
+    if (have_bytes == 0) {
+      return false;
     }
-
-    // Next byte -- used for minimal octal escapes below.
-    char next_byte = (i + decoded) < in.size() ?
-        in[i + decoded] : 0;
-    bool pad_octal = (next_byte >= '0' && next_byte <= '7');
+    decoded = have_bytes;
 
     switch (codepoint) {
-      case '\0': result += pad_octal ? "\\000" : "\\0";   break;
-      case '\b': result += "\\\b";  break;
-      case '\t': result += "\\\t";  break;
-      case '\n': result += "\\\n";  break;
-      case '\r': result += "\\\r";  break;
-      case '\f': result += "\\\f";  break;
-      case '\\': result += "\\\\";  break;
-      case '"':  result += pad_octal ? "\\042" : "\\42"; break;
-      case '&':  result += pad_octal ? "\\046" : "\\46"; break;
-      case '\'': result += pad_octal ? "\\047" : "\\47"; break;
-      case '<':  result += pad_octal ? "\\074" : "\\74"; break;
-      case '=':  result += pad_octal ? "\\075" : "\\75"; break;
-      case '>':  result += pad_octal ? "\\076" : "\\76"; break;
+      case '\'': *out += "\\x27"; break;
+      case '"': *out += "\\x22"; break;
+      case '<': *out += "\\x3c"; break;
+      case '=': *out += "\\x3d"; break;
+      case '>': *out += "\\x3e"; break;
+      case '&': *out += "\\x26"; break;
+      case '\b': *out += "\\b"; break;
+      case '\t': *out += "\\t"; break;
+      case '\n': *out += "\\n"; break;
+      case '\f': *out += "\\f"; break;
+      case '\r': *out += "\\r"; break;
+      case '\\': *out += "\\\\"; break;
       default:
-        // All other non-ASCII codepoints are escaped.
-        // Original codegen uses hex for >= 0x100 and octal for others.
+        // TODO(lukestebbing): Once we're supporting codepoints outside the BMP,
+        // use a single Unicode codepoint escape if the output language is
+        // ECMAScript 2015 or above. Otherwise, use a surrogate pair.
+        // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#String_literals
         if (codepoint >= 0x20 && codepoint <= 0x7e) {
-          result += static_cast<char>(codepoint);
+          *out += static_cast<char>(codepoint);
+        } else if (codepoint >= 0x100) {
+          *out += StringPrintf("\\u%04x", codepoint);
         } else {
-          if (codepoint >= 0x100) {
-            result += StringPrintf("\\u%04x", codepoint);
-          } else {
-            if (pad_octal || codepoint >= 0100) {
-              result += "\\";
-              result += ('0' + ((codepoint >> 6) & 07));
-              result += ('0' + ((codepoint >> 3) & 07));
-              result += ('0' + ((codepoint >> 0) & 07));
-            } else if (codepoint >= 010) {
-              result += "\\";
-              result += ('0' + ((codepoint >> 3) & 07));
-              result += ('0' + ((codepoint >> 0) & 07));
-            } else {
-              result += "\\";
-              result += ('0' + ((codepoint >> 0) & 07));
-            }
-          }
+          *out += StringPrintf("\\x%02x", codepoint);
         }
         break;
     }
   }
-  return result;
+  return true;
 }
 
 string EscapeBase64(const string& in) {
@@ -740,11 +775,17 @@
       return DoubleToString(field->default_value_double());
     case FieldDescriptor::CPPTYPE_STRING:
       if (field->type() == FieldDescriptor::TYPE_STRING) {
-        return "\"" + EscapeJSString(field->default_value_string(), true) +
-               "\"";
-      } else {
-        return "\"" + EscapeBase64(field->default_value_string()) +
-               "\"";
+        string out;
+        bool is_valid = EscapeJSString(field->default_value_string(), &out);
+        if (!is_valid) {
+          // TODO(lukestebbing): Decide whether this should be a hard error.
+          GOOGLE_LOG(WARNING) << "The default value for field " << field->full_name()
+                       << " was truncated since it contained invalid UTF-8 or"
+                          " codepoints outside the basic multilingual plane.";
+        }
+        return "\"" + out + "\"";
+      } else {  // Bytes
+        return "\"" + EscapeBase64(field->default_value_string()) + "\"";
       }
     case FieldDescriptor::CPPTYPE_MESSAGE:
       return "null";
@@ -801,8 +842,27 @@
   return "number";
 }
 
+string JSStringTypeName(const GeneratorOptions& options,
+                        const FieldDescriptor* field,
+                        BytesMode bytes_mode) {
+  if (field->type() == FieldDescriptor::TYPE_BYTES) {
+    switch (bytes_mode) {
+      case BYTES_DEFAULT:
+        return "(string|Uint8Array)";
+      case BYTES_B64:
+        return "string";
+      case BYTES_U8:
+        return "Uint8Array";
+      default:
+        assert(false);
+    }
+  }
+  return "string";
+}
+
 string JSTypeName(const GeneratorOptions& options,
-                  const FieldDescriptor* field) {
+                  const FieldDescriptor* field,
+                  BytesMode bytes_mode) {
   switch (field->cpp_type()) {
     case FieldDescriptor::CPPTYPE_BOOL:
       return "boolean";
@@ -819,7 +879,7 @@
     case FieldDescriptor::CPPTYPE_DOUBLE:
       return "number";
     case FieldDescriptor::CPPTYPE_STRING:
-      return "string";
+      return JSStringTypeName(options, field, bytes_mode);
     case FieldDescriptor::CPPTYPE_ENUM:
       return GetPath(options, field->enum_type());
     case FieldDescriptor::CPPTYPE_MESSAGE:
@@ -836,20 +896,26 @@
                              bool force_optional,
                              bool force_present,
                              bool singular_if_not_packed,
-                             bool always_singular) {
+                             BytesMode bytes_mode = BYTES_DEFAULT) {
   bool is_primitive =
       (field->cpp_type() != FieldDescriptor::CPPTYPE_ENUM &&
-       field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE);
+       field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE &&
+        (field->type() != FieldDescriptor::TYPE_BYTES ||
+            bytes_mode == BYTES_B64));
 
-  string jstype = JSTypeName(options, field);
+  string jstype = JSTypeName(options, field, bytes_mode);
 
   if (field->is_repeated() &&
-      !always_singular &&
       (field->is_packed() || !singular_if_not_packed)) {
-    if (!is_primitive) {
-      jstype = "!" + jstype;
+    if (field->type() == FieldDescriptor::TYPE_BYTES &&
+        bytes_mode == BYTES_DEFAULT) {
+      jstype = "(Array<!Uint8Array>|Array<string>)";
+    } else {
+      if (!is_primitive) {
+        jstype = "!" + jstype;
+      }
+      jstype = "Array.<" + jstype + ">";
     }
-    jstype = "Array.<" + jstype + ">";
     if (!force_optional) {
       jstype = "!" + jstype;
     }
@@ -884,10 +950,6 @@
 string JSBinaryReadWriteMethodName(const FieldDescriptor* field,
                                    bool is_writer) {
   string name = JSBinaryReaderMethodType(field);
-  if (is_writer && field->type() == FieldDescriptor::TYPE_BYTES) {
-    // Override for `bytes` fields: treat string as raw bytes, not base64.
-    name = "BytesRawString";
-  }
   if (field->is_packed()) {
     name = "Packed" + name;
   } else if (is_writer && field->is_repeated()) {
@@ -1044,7 +1106,7 @@
                       field->number());
 }
 
-string FieldComments(const FieldDescriptor* field) {
+string FieldComments(const FieldDescriptor* field, BytesMode bytes_mode) {
   string comments;
   if (field->cpp_type() == FieldDescriptor::CPPTYPE_BOOL) {
     comments +=
@@ -1060,6 +1122,11 @@
         " * replace the array itself, then you must call the setter to "
         "update it.\n";
   }
+  if (field->type() == FieldDescriptor::TYPE_BYTES && bytes_mode == BYTES_U8) {
+    comments +=
+        " * Note that Uint8Array is not supported on all browsers.\n"
+        " * @see http://caniuse.com/Uint8Array\n";
+  }
   return comments;
 }
 
@@ -1070,8 +1137,10 @@
 }
 
 bool HasExtensions(const Descriptor* desc) {
-  if (desc->extension_count() > 0) {
-    return true;
+  for (int i = 0; i < desc->extension_count(); i++) {
+    if (ShouldGenerateExtension(desc->extension(i))) {
+      return true;
+    }
   }
   for (int i = 0; i < desc->nested_type_count(); i++) {
     if (HasExtensions(desc->nested_type(i))) {
@@ -1123,7 +1192,7 @@
 }
 
 // Returns true for fields that represent "null" as distinct from the default
-// value. See https://go/proto3#heading=h.kozewqqcqhuz for more information.
+// value. See http://go/proto3#heading=h.kozewqqcqhuz for more information.
 bool HasFieldPresence(const FieldDescriptor* field) {
   return
       (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) ||
@@ -1132,7 +1201,7 @@
 }
 
 // For proto3 fields without presence, returns a string representing the default
-// value in JavaScript. See https://go/proto3#heading=h.kozewqqcqhuz for more
+// value in JavaScript. See http://go/proto3#heading=h.kozewqqcqhuz for more
 // information.
 string Proto3PrimitiveFieldDefault(const FieldDescriptor* field) {
   switch (field->cpp_type()) {
@@ -1151,16 +1220,153 @@
     case FieldDescriptor::CPPTYPE_BOOL:
       return "false";
 
-    case FieldDescriptor::CPPTYPE_STRING:
+    case FieldDescriptor::CPPTYPE_STRING:  // includes BYTES
       return "\"\"";
 
     default:
-      // BYTES and MESSAGE are handled separately.
+      // MESSAGE is handled separately.
       assert(false);
       return "";
   }
 }
 
+// We use this to implement the semantics that same file can be generated
+// multiple times, but the last one wins.  We never actually write the files,
+// but we keep a set of which descriptors were the final one for a given
+// filename.
+class FileDeduplicator {
+ public:
+  explicit FileDeduplicator(const GeneratorOptions& options)
+      : error_on_conflict_(options.error_on_name_conflict) {}
+
+  bool AddFile(const string& filename, const void* desc, string* error) {
+    if (descs_by_filename_.find(filename) != descs_by_filename_.end()) {
+      if (error_on_conflict_) {
+        *error = "Name conflict: file name " + filename +
+                 " would be generated by two descriptors";
+        return false;
+      }
+      allowed_descs_.erase(descs_by_filename_[filename]);
+    }
+
+    descs_by_filename_[filename] = desc;
+    allowed_descs_.insert(desc);
+    return true;
+  }
+
+  void GetAllowedSet(set<const void*>* allowed_set) {
+    *allowed_set = allowed_descs_;
+  }
+
+ private:
+  bool error_on_conflict_;
+  map<string, const void*> descs_by_filename_;
+  set<const void*> allowed_descs_;
+};
+
+void DepthFirstSearch(const FileDescriptor* file,
+                      vector<const FileDescriptor*>* list,
+                      set<const FileDescriptor*>* seen) {
+  if (!seen->insert(file).second) {
+    return;
+  }
+
+  // Add all dependencies.
+  for (int i = 0; i < file->dependency_count(); i++) {
+    DepthFirstSearch(file->dependency(i), list, seen);
+  }
+
+  // Add this file.
+  list->push_back(file);
+}
+
+// A functor for the predicate to remove_if() below.  Returns true if a given
+// FileDescriptor is not in the given set.
+class NotInSet {
+ public:
+  explicit NotInSet(const set<const FileDescriptor*>& file_set)
+      : file_set_(file_set) {}
+
+  bool operator()(const FileDescriptor* file) {
+    return file_set_.count(file) == 0;
+  }
+
+ private:
+  const set<const FileDescriptor*>& file_set_;
+};
+
+// This function generates an ordering of the input FileDescriptors that matches
+// the logic of the old code generator.  The order is significant because two
+// different input files can generate the same output file, and the last one
+// needs to win.
+void GenerateJspbFileOrder(const vector<const FileDescriptor*>& input,
+                           vector<const FileDescriptor*>* ordered) {
+  // First generate an ordering of all reachable files (including dependencies)
+  // with depth-first search.  This mimics the behavior of --include_imports,
+  // which is what the old codegen used.
+  ordered->clear();
+  set<const FileDescriptor*> seen;
+  set<const FileDescriptor*> input_set;
+  for (int i = 0; i < input.size(); i++) {
+    DepthFirstSearch(input[i], ordered, &seen);
+    input_set.insert(input[i]);
+  }
+
+  // Now remove the entries that are not actually in our input list.
+  ordered->erase(
+      std::remove_if(ordered->begin(), ordered->end(), NotInSet(input_set)),
+      ordered->end());
+}
+
+// If we're generating code in file-per-type mode, avoid overwriting files
+// by choosing the last descriptor that writes each filename and permitting
+// only those to generate code.
+
+bool GenerateJspbAllowedSet(const GeneratorOptions& options,
+                            const vector<const FileDescriptor*>& files,
+                            set<const void*>* allowed_set,
+                            string* error) {
+  vector<const FileDescriptor*> files_ordered;
+  GenerateJspbFileOrder(files, &files_ordered);
+
+  // Choose the last descriptor for each filename.
+  FileDeduplicator dedup(options);
+  for (int i = 0; i < files_ordered.size(); i++) {
+    for (int j = 0; j < files_ordered[i]->message_type_count(); j++) {
+      const Descriptor* desc = files_ordered[i]->message_type(j);
+      if (!dedup.AddFile(GetMessageFileName(options, desc), desc, error)) {
+        return false;
+      }
+    }
+    for (int j = 0; j < files_ordered[i]->enum_type_count(); j++) {
+      const EnumDescriptor* desc = files_ordered[i]->enum_type(j);
+      if (!dedup.AddFile(GetEnumFileName(options, desc), desc, error)) {
+        return false;
+      }
+    }
+
+    // Pull out all free-floating extensions and generate files for those too.
+    bool has_extension = false;
+
+    for (int j = 0; j < files_ordered[i]->extension_count(); j++) {
+      if (ShouldGenerateExtension(files_ordered[i]->extension(j))) {
+        has_extension = true;
+      }
+    }
+
+    if (has_extension) {
+      if (!dedup.AddFile(GetExtensionFileName(options, files_ordered[i]),
+                         files_ordered[i], error)) {
+        return false;
+      }
+    }
+  }
+
+  dedup.GetAllowedSet(allowed_set);
+
+  return true;
+}
+
 }  // anonymous namespace
 
 void Generator::GenerateHeader(const GeneratorOptions& options,
@@ -1251,10 +1457,10 @@
   }
 }
 
-void Generator::GenerateRequires(const GeneratorOptions& options,
-                                 io::Printer* printer,
-                                 const Descriptor* desc,
-                                 std::set<string>* provided) const {
+void Generator::GenerateRequiresForMessage(const GeneratorOptions& options,
+                                           io::Printer* printer,
+                                           const Descriptor* desc,
+                                           std::set<string>* provided) const {
   std::set<string> required;
   std::set<string> forwards;
   bool have_message = false;
@@ -1266,55 +1472,50 @@
                        /* require_extension = */ HasExtensions(desc));
 }
 
-void Generator::GenerateRequires(const GeneratorOptions& options,
-                                 io::Printer* printer,
-                                 const vector<const FileDescriptor*>& files,
-                                 std::set<string>* provided) const {
-  if (options.import_style == GeneratorOptions::IMPORT_BROWSER) {
-    return;
-  } else if (options.import_style == GeneratorOptions::IMPORT_CLOSURE) {
-    // For Closure imports we need to import every message type individually.
-    std::set<string> required;
-    std::set<string> forwards;
-    bool have_extensions = false;
-    bool have_message = false;
+void Generator::GenerateRequiresForLibrary(
+    const GeneratorOptions& options, io::Printer* printer,
+    const vector<const FileDescriptor*>& files,
+    std::set<string>* provided) const {
+  GOOGLE_CHECK_EQ(options.import_style, GeneratorOptions::IMPORT_CLOSURE);
+  // For Closure imports we need to import every message type individually.
+  std::set<string> required;
+  std::set<string> forwards;
+  bool have_extensions = false;
+  bool have_message = false;
 
-    for (int i = 0; i < files.size(); i++) {
-      for (int j = 0; j < files[i]->message_type_count(); j++) {
-        FindRequiresForMessage(options,
-                               files[i]->message_type(j),
-                               &required, &forwards, &have_message);
-      }
-      if (!have_extensions && HasExtensions(files[i])) {
-        have_extensions = true;
-      }
-
-      for (int j = 0; j < files[i]->extension_count(); j++) {
-        const FieldDescriptor* extension = files[i]->extension(j);
-        if (IgnoreField(extension)) {
-          continue;
-        }
-        if (extension->containing_type()->full_name() !=
-            "google.protobuf.bridge.MessageSet") {
-          required.insert(GetPath(options, extension->containing_type()));
-        }
-        FindRequiresForField(options, extension, &required, &forwards);
-        have_extensions = true;
-      }
+  for (int i = 0; i < files.size(); i++) {
+    for (int j = 0; j < files[i]->message_type_count(); j++) {
+      FindRequiresForMessage(options,
+                             files[i]->message_type(j),
+                             &required, &forwards, &have_message);
+    }
+    if (!have_extensions && HasExtensions(files[i])) {
+      have_extensions = true;
     }
 
-    GenerateRequiresImpl(options, printer, &required, &forwards, provided,
-                         /* require_jspb = */ have_message,
-                         /* require_extension = */ have_extensions);
-  } else if (options.import_style == GeneratorOptions::IMPORT_COMMONJS) {
-    // CommonJS imports are based on files
+    for (int j = 0; j < files[i]->extension_count(); j++) {
+      const FieldDescriptor* extension = files[i]->extension(j);
+      if (IgnoreField(extension)) {
+        continue;
+      }
+      if (extension->containing_type()->full_name() !=
+        "google.protobuf.bridge.MessageSet") {
+        required.insert(GetPath(options, extension->containing_type()));
+      }
+      FindRequiresForField(options, extension, &required, &forwards);
+      have_extensions = true;
+    }
   }
+
+  GenerateRequiresImpl(options, printer, &required, &forwards, provided,
+                       /* require_jspb = */ have_message,
+                       /* require_extension = */ have_extensions);
 }
 
-void Generator::GenerateRequires(const GeneratorOptions& options,
-                                 io::Printer* printer,
-                                 const vector<const FieldDescriptor*>& fields,
-                                 std::set<string>* provided) const {
+void Generator::GenerateRequiresForExtensions(
+    const GeneratorOptions& options, io::Printer* printer,
+    const vector<const FieldDescriptor*>& fields,
+    std::set<string>* provided) const {
   std::set<string> required;
   std::set<string> forwards;
   for (int i = 0; i < fields.size(); i++) {
@@ -1741,17 +1942,34 @@
     }
   } else {
     // Simple field (singular or repeated).
-    if (!HasFieldPresence(field) && !field->is_repeated()) {
+    if ((!HasFieldPresence(field) && !field->is_repeated()) ||
+        field->type() == FieldDescriptor::TYPE_BYTES) {
       // Delegate to the generated get<field>() method in order not to duplicate
-      // the proto3-field-default-value logic here.
+      // the proto3-field-default-value or byte-coercion logic here.
       printer->Print("msg.get$getter$()",
-                     "getter", JSGetterName(field));
+                     "getter", JSGetterName(field, BYTES_B64));
     } else {
       if (field->has_default_value()) {
-        printer->Print("jspb.Message.getField(msg, $index$) != null ? "
-                       "jspb.Message.getField(msg, $index$) : $defaultValue$",
+        printer->Print("jspb.Message.getField(msg, $index$) == null ? "
+                       "$defaultValue$ : ",
                        "index", JSFieldIndex(field),
                        "defaultValue", JSFieldDefault(field));
+      }
+      if (field->cpp_type() == FieldDescriptor::CPPTYPE_FLOAT ||
+          field->cpp_type() == FieldDescriptor::CPPTYPE_DOUBLE) {
+        if (field->is_repeated()) {
+          printer->Print("jspb.Message.getRepeatedFloatingPointField("
+                         "msg, $index$)",
+                         "index", JSFieldIndex(field));
+        } else if (field->is_optional() && !field->has_default_value()) {
+          printer->Print("jspb.Message.getOptionalFloatingPointField("
+                         "msg, $index$)",
+                         "index", JSFieldIndex(field));
+        } else {
+          // Convert "NaN" to NaN.
+          printer->Print("+jspb.Message.getField(msg, $index$)",
+                         "index", JSFieldIndex(field));
+        }
       } else {
         printer->Print("jspb.Message.getField(msg, $index$)",
                        "index", JSFieldIndex(field));
@@ -1860,6 +2078,40 @@
   }
 }
 
+void GenerateBytesWrapper(const GeneratorOptions& options,
+                          io::Printer* printer,
+                          const FieldDescriptor* field,
+                          BytesMode bytes_mode) {
+  string type =
+      JSFieldTypeAnnotation(options, field,
+                            /* force_optional = */ false,
+                            /* force_present = */ !HasFieldPresence(field),
+                            /* singular_if_not_packed = */ false,
+                            bytes_mode);
+  printer->Print(
+      "/**\n"
+      " * $fielddef$\n"
+      "$comment$"
+      " * This is a type-conversion wrapper around `get$defname$()`\n"
+      " * @return {$type$}\n"
+      " */\n"
+      "$class$.prototype.get$name$ = function() {\n"
+      "  return /** @type {$type$} */ (jspb.Message.bytes$list$As$suffix$(\n"
+      "      this.get$defname$()));\n"
+      "};\n"
+      "\n"
+      "\n",
+      "fielddef", FieldDefinition(options, field),
+      "comment", FieldComments(field, bytes_mode),
+      "type", type,
+      "class", GetPath(options, field->containing_type()),
+      "name", JSGetterName(field, bytes_mode),
+      "list", field->is_repeated() ? "List" : "",
+      "suffix", JSByteGetterSuffix(bytes_mode),
+      "defname", JSGetterName(field, BYTES_DEFAULT));
+}
+
+
 void Generator::GenerateClassField(const GeneratorOptions& options,
                                    io::Printer* printer,
                                    const FieldDescriptor* field) const {
@@ -1871,12 +2123,11 @@
         " * @return {$type$}\n"
         " */\n",
         "fielddef", FieldDefinition(options, field),
-        "comment", FieldComments(field),
+        "comment", FieldComments(field, BYTES_DEFAULT),
         "type", JSFieldTypeAnnotation(options, field,
                                       /* force_optional = */ false,
                                       /* force_present = */ false,
-                                      /* singular_if_not_packed = */ false,
-                                      /* always_singular = */ false));
+                                      /* singular_if_not_packed = */ false));
     printer->Print(
         "$class$.prototype.get$name$ = function() {\n"
         "  return /** @type{$type$} */ (\n"
@@ -1890,8 +2141,7 @@
         "type", JSFieldTypeAnnotation(options, field,
                                       /* force_optional = */ false,
                                       /* force_present = */ false,
-                                      /* singular_if_not_packed = */ false,
-                                      /* always_singular = */ false),
+                                      /* singular_if_not_packed = */ false),
         "rpt", (field->is_repeated() ? "Repeated" : ""),
         "index", JSFieldIndex(field),
         "wrapperclass", SubmessageTypeRef(options, field),
@@ -1905,8 +2155,7 @@
         JSFieldTypeAnnotation(options, field,
                               /* force_optional = */ true,
                               /* force_present = */ false,
-                              /* singular_if_not_packed = */ false,
-                              /* always_singular = */ false),
+                              /* singular_if_not_packed = */ false),
         "returndoc", JSReturnDoc(options, field),
         "class", GetPath(options, field->containing_type()),
         "name", JSGetterName(field),
@@ -1935,15 +2184,29 @@
         "returnvalue", JSReturnClause(field));
 
   } else {
-    string typed_annotation;
+    bool untyped =
+        false;
 
     // Simple (primitive) field, either singular or repeated.
-    {
-      typed_annotation = JSFieldTypeAnnotation(options, field,
+
+    // TODO(b/26173701): Always use BYTES_DEFAULT for the getter return type;
+    // at this point we "lie" to non-binary users and tell the the return
+    // type is always base64 string, pending a LSC to migrate to typed getters.
+    BytesMode bytes_mode =
+        field->type() == FieldDescriptor::TYPE_BYTES && !options.binary ?
+            BYTES_B64 : BYTES_DEFAULT;
+    string typed_annotation =
+        JSFieldTypeAnnotation(options, field,
                               /* force_optional = */ false,
                               /* force_present = */ !HasFieldPresence(field),
                               /* singular_if_not_packed = */ false,
-                              /* always_singular = */ false),
+                              /* bytes_mode = */ bytes_mode);
+    if (untyped) {
+      printer->Print(
+          "/**\n"
+          " * @return {?} Raw field, untyped.\n"
+          " */\n");
+    } else {
       printer->Print(
           "/**\n"
           " * $fielddef$\n"
@@ -1951,7 +2214,7 @@
           " * @return {$type$}\n"
           " */\n",
           "fielddef", FieldDefinition(options, field),
-          "comment", FieldComments(field),
+          "comment", FieldComments(field, bytes_mode),
           "type", typed_annotation);
     }
 
@@ -1960,7 +2223,10 @@
         "class", GetPath(options, field->containing_type()),
         "name", JSGetterName(field));
 
-    {
+    if (untyped) {
+      printer->Print(
+          "  return ");
+    } else {
       printer->Print(
           "  return /** @type {$type$} */ (",
           "type", typed_annotation);
@@ -1975,17 +2241,39 @@
                      "default", Proto3PrimitiveFieldDefault(field));
     } else {
       if (field->has_default_value()) {
-        printer->Print("jspb.Message.getField(this, $index$) != null ? "
-                       "jspb.Message.getField(this, $index$) : $defaultValue$",
+        printer->Print("jspb.Message.getField(this, $index$) == null ? "
+                       "$defaultValue$ : ",
                        "index", JSFieldIndex(field),
                        "defaultValue", JSFieldDefault(field));
+      }
+      if (field->cpp_type() == FieldDescriptor::CPPTYPE_FLOAT ||
+          field->cpp_type() == FieldDescriptor::CPPTYPE_DOUBLE) {
+        if (field->is_repeated()) {
+          printer->Print("jspb.Message.getRepeatedFloatingPointField("
+                         "this, $index$)",
+                         "index", JSFieldIndex(field));
+        } else if (field->is_optional() && !field->has_default_value()) {
+          printer->Print("jspb.Message.getOptionalFloatingPointField("
+                         "this, $index$)",
+                         "index", JSFieldIndex(field));
+        } else {
+          // Convert "NaN" to NaN.
+          printer->Print("+jspb.Message.getField(this, $index$)",
+                         "index", JSFieldIndex(field));
+        }
       } else {
         printer->Print("jspb.Message.getField(this, $index$)",
                        "index", JSFieldIndex(field));
       }
     }
 
-    {
+    if (untyped) {
+      printer->Print(
+          ";\n"
+          "};\n"
+          "\n"
+          "\n");
+    } else {
       printer->Print(
           ");\n"
           "};\n"
@@ -1993,18 +2281,27 @@
           "\n");
     }
 
-    {
+    if (field->type() == FieldDescriptor::TYPE_BYTES && !untyped) {
+      GenerateBytesWrapper(options, printer, field, BYTES_B64);
+      GenerateBytesWrapper(options, printer, field, BYTES_U8);
+    }
+
+    if (untyped) {
+      printer->Print(
+          "/**\n"
+          " * @param {*} value $returndoc$\n"
+          " */\n",
+          "returndoc", JSReturnDoc(options, field));
+    } else {
       printer->Print(
           "/** @param {$optionaltype$} value $returndoc$ */\n",
           "optionaltype",
           JSFieldTypeAnnotation(options, field,
                                 /* force_optional = */ true,
                                 /* force_present = */ !HasFieldPresence(field),
-                                /* singular_if_not_packed = */ false,
-                                /* always_singular = */ false),
+                                /* singular_if_not_packed = */ false),
           "returndoc", JSReturnDoc(options, field));
     }
-
     printer->Print(
         "$class$.prototype.set$name$ = function(value) {\n"
         "  jspb.Message.set$oneoftag$Field(this, $index$",
@@ -2017,14 +2314,22 @@
         "};\n"
         "\n"
         "\n",
-        "type", "",
-        "typeclose", "",
+        "type",
+        untyped ? "/** @type{string|number|boolean|Array|undefined} */(" : "",
+        "typeclose", untyped ? ")" : "",
         "oneofgroup",
         (field->containing_oneof() ? (", " + JSOneofArray(options, field))
                                    : ""),
         "returnvalue", JSReturnClause(field), "rptvalueinit",
         (field->is_repeated() ? " || []" : ""));
 
+    if (untyped) {
+      printer->Print(
+          "/**\n"
+          " * Clears the value. $returndoc$\n"
+          " */\n",
+          "returndoc", JSReturnDoc(options, field));
+    }
 
     if (HasFieldPresence(field)) {
       printer->Print(
@@ -2162,16 +2467,18 @@
         "      var value = /** @type {$fieldtype$} */ (reader.$reader$());\n",
         "fieldtype", JSFieldTypeAnnotation(options, field, false, true,
                                            /* singular_if_not_packed = */ true,
-                                           /* always_singular = */ false),
+                                           BYTES_U8),
         "reader", JSBinaryReaderMethodName(field));
   }
 
   if (field->is_repeated() && !field->is_packed()) {
     // Repeated fields receive a |value| one at at a time; append to array
-    // returned by get$name$().
-    printer->Print(
-        "      msg.get$name$().push(value);\n",
-        "name", JSGetterName(field));
+    // returned by get$name$(). Annoyingly, we have to call 'set' after
+    // changing the array.
+    printer->Print("      msg.get$name$().push(value);\n", "name",
+                   JSGetterName(field));
+    printer->Print("      msg.set$name$(msg.get$name$());\n", "name",
+                   JSGetterName(field));
   } else {
     // Singular fields, and packed repeated fields, receive a |value| either as
     // the field's value or as the array of all the field's values; set this as
@@ -2244,7 +2551,7 @@
     const FieldDescriptor* field) const {
   printer->Print(
       "  f = this.get$name$();\n",
-      "name", JSGetterName(field));
+      "name", JSGetterName(field, BYTES_U8));
 
   if (field->is_repeated()) {
     printer->Print(
@@ -2294,7 +2601,6 @@
       "      $index$,\n"
       "      f",
       "writer", JSBinaryWriterMethodName(field),
-      "name", JSGetterName(field),
       "index", SimpleItoa(field->number()));
 
   if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
@@ -2356,8 +2662,7 @@
           options, field,
           /* force_optional = */ false,
           /* force_present = */ true,
-          /* singular_if_not_packed = */ false,
-          /* always_singular = */ false));
+          /* singular_if_not_packed = */ false));
   printer->Print(
       "    $index$,\n"
       "    {$name$: 0},\n"
@@ -2528,7 +2833,7 @@
     printer->Print("var global = Function('return this')();\n\n");
 
     for (int i = 0; i < file->dependency_count(); i++) {
-      const std::string& name = file->dependency(i)->name();
+      const string& name = file->dependency(i)->name();
       printer->Print(
           "var $alias$ = require('$file$');\n",
           "alias", ModuleAlias(name),
@@ -2543,7 +2848,7 @@
   //
   //   // Later generated code expects foo.bar = {} to exist:
   //   foo.bar.Baz = function() { /* ... */ }
-  std::set<std::string> provided;
+  set<string> provided;
 
   // Cover the case where this file declares extensions but no messages.
   // This will ensure that the file-level object will be declared to hold
@@ -2615,7 +2920,7 @@
     FindProvidesForFields(options, &printer, extensions, &provided);
     GenerateProvides(options, &printer, &provided);
     GenerateTestOnly(options, &printer);
-    GenerateRequires(options, &printer, files, &provided);
+    GenerateRequiresForLibrary(options, &printer, files, &provided);
 
     GenerateFilesInDepOrder(options, &printer, files);
 
@@ -2629,66 +2934,20 @@
       return false;
     }
   } else if (options.import_style == GeneratorOptions::IMPORT_CLOSURE) {
-    // Collect all types, and print each type to a separate file. Pull out
-    // free-floating extensions while we make this pass.
-    map< string, vector<const FieldDescriptor*> > extensions_by_namespace;
-
-    // If we're generating code in file-per-type mode, avoid overwriting files
-    // by choosing the last descriptor that writes each filename and permitting
-    // only those to generate code.
-
-    // Current descriptor that will generate each filename, indexed by filename.
-    map<string, const void*> desc_by_filename;
-    // Set of descriptors allowed to generate files.
-    set<const void*> allowed_descs;
-
-    for (int i = 0; i < files.size(); i++) {
-      // Collect all (descriptor, filename) pairs.
-      map<const void*, string> descs_in_file;
-      for (int j = 0; j < files[i]->message_type_count(); j++) {
-        const Descriptor* desc = files[i]->message_type(j);
-        string filename =
-            options.output_dir + "/" + ToFileName(desc->name()) + ".js";
-        descs_in_file[desc] = filename;
-      }
-      for (int j = 0; j < files[i]->enum_type_count(); j++) {
-        const EnumDescriptor* desc = files[i]->enum_type(j);
-        string filename =
-            options.output_dir + "/" + ToFileName(desc->name()) + ".js";
-        descs_in_file[desc] = filename;
-      }
-
-      // For each (descriptor, filename) pair, update the
-      // descriptors-by-filename map, and if a previous descriptor was already
-      // writing the filename, remove it from the allowed-descriptors set.
-      map<const void*, string>::iterator it;
-      for (it = descs_in_file.begin(); it != descs_in_file.end(); ++it) {
-        const void* desc = it->first;
-        const string& filename = it->second;
-        if (desc_by_filename.find(filename) != desc_by_filename.end()) {
-          if (options.error_on_name_conflict) {
-            *error = "Name conflict: file name " + filename +
-                     " would be generated by two descriptors";
-            return false;
-          }
-          allowed_descs.erase(desc_by_filename[filename]);
-        }
-        desc_by_filename[filename] = desc;
-        allowed_descs.insert(desc);
-      }
+    set<const void*> allowed_set;
+    if (!GenerateJspbAllowedSet(options, files, &allowed_set, error)) {
+      return false;
     }
 
-    // Generate code.
     for (int i = 0; i < files.size(); i++) {
       const FileDescriptor* file = files[i];
       for (int j = 0; j < file->message_type_count(); j++) {
         const Descriptor* desc = file->message_type(j);
-        if (allowed_descs.find(desc) == allowed_descs.end()) {
+        if (allowed_set.count(desc) == 0) {
           continue;
         }
 
-        string filename = options.output_dir + "/" +
-            ToFileName(desc->name()) + ".js";
+        string filename = GetMessageFileName(options, desc);
         google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
             context->Open(filename));
         GOOGLE_CHECK(output.get());
@@ -2700,7 +2959,7 @@
         FindProvidesForMessage(options, &printer, desc, &provided);
         GenerateProvides(options, &printer, &provided);
         GenerateTestOnly(options, &printer);
-        GenerateRequires(options, &printer, desc, &provided);
+        GenerateRequiresForMessage(options, &printer, desc, &provided);
 
         GenerateClass(options, &printer, desc);
 
@@ -2710,13 +2969,11 @@
       }
       for (int j = 0; j < file->enum_type_count(); j++) {
         const EnumDescriptor* enumdesc = file->enum_type(j);
-        if (allowed_descs.find(enumdesc) == allowed_descs.end()) {
+        if (allowed_set.count(enumdesc) == 0) {
           continue;
         }
 
-        string filename = options.output_dir + "/" +
-            ToFileName(enumdesc->name()) + ".js";
-
+        string filename = GetEnumFileName(options, enumdesc);
         google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
             context->Open(filename));
         GOOGLE_CHECK(output.get());
@@ -2735,38 +2992,36 @@
           return false;
         }
       }
-      // Pull out all free-floating extensions and generate files for those too.
-      for (int j = 0; j < file->extension_count(); j++) {
-        const FieldDescriptor* extension = file->extension(j);
-        extensions_by_namespace[GetPath(options, files[i])]
-            .push_back(extension);
-      }
-    }
+      // File-level extensions (message-level extensions are generated under
+      // the enclosing message).
+      if (allowed_set.count(file) == 1) {
+        string filename = GetExtensionFileName(options, file);
 
-    // Generate extensions in separate files.
-    map< string, vector<const FieldDescriptor*> >::iterator it;
-    for (it = extensions_by_namespace.begin();
-         it != extensions_by_namespace.end();
-         ++it) {
-      string filename = options.output_dir + "/" +
-          ToFileName(it->first) + ".js";
+        google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
+            context->Open(filename));
+        GOOGLE_CHECK(output.get());
+        io::Printer printer(output.get(), '$');
 
-      google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
-          context->Open(filename));
-      GOOGLE_CHECK(output.get());
-      io::Printer printer(output.get(), '$');
+        GenerateHeader(options, &printer);
 
-      GenerateHeader(options, &printer);
+        std::set<string> provided;
+        vector<const FieldDescriptor*> fields;
 
-      std::set<string> provided;
-      FindProvidesForFields(options, &printer, it->second, &provided);
-      GenerateProvides(options, &printer, &provided);
-      GenerateTestOnly(options, &printer);
-      GenerateRequires(options, &printer, it->second, &provided);
+        for (int j = 0; j < files[i]->extension_count(); j++) {
+          if (ShouldGenerateExtension(files[i]->extension(j))) {
+            fields.push_back(files[i]->extension(j));
+          }
+        }
 
-      for (int j = 0; j < it->second.size(); j++) {
-        if (ShouldGenerateExtension(it->second[j])) {
-          GenerateExtension(options, &printer, it->second[j]);
+        FindProvidesForFields(options, &printer, fields, &provided);
+        GenerateProvides(options, &printer, &provided);
+        GenerateTestOnly(options, &printer);
+        GenerateRequiresForExtensions(options, &printer, fields, &provided);
+
+        for (int j = 0; j < files[i]->extension_count(); j++) {
+          if (ShouldGenerateExtension(files[i]->extension(j))) {
+            GenerateExtension(options, &printer, files[i]->extension(j));
+          }
         }
       }
     }
@@ -2777,7 +3032,7 @@
       const google::protobuf::FileDescriptor* file = files[i];
 
       string filename = options.output_dir + "/" + GetJSFilename(file->name());
-      google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
+      scoped_ptr<io::ZeroCopyOutputStream> output(
           context->Open(filename));
       GOOGLE_CHECK(output.get());
       io::Printer printer(output.get(), '$');
diff --git a/src/google/protobuf/compiler/js/js_generator.h b/src/google/protobuf/compiler/js/js_generator.h
index db9178d..6fd7ca5 100755
--- a/src/google/protobuf/compiler/js/js_generator.h
+++ b/src/google/protobuf/compiler/js/js_generator.h
@@ -146,19 +146,19 @@
                         io::Printer* printer) const;
 
   // Generate goog.requires() calls.
-  void GenerateRequires(const GeneratorOptions& options,
-                        io::Printer* printer,
-                        const vector<const FileDescriptor*>& file,
-                        std::set<string>* provided) const;
-  void GenerateRequires(const GeneratorOptions& options,
+  void GenerateRequiresForLibrary(const GeneratorOptions& options,
+                                  io::Printer* printer,
+                                  const vector<const FileDescriptor*>& files,
+                                  std::set<string>* provided) const;
+  void GenerateRequiresForMessage(const GeneratorOptions& options,
                         io::Printer* printer,
                         const Descriptor* desc,
                         std::set<string>* provided) const;
   // For extension fields at file scope.
-  void GenerateRequires(const GeneratorOptions& options,
-                        io::Printer* printer,
-                        const vector<const FieldDescriptor*>& fields,
-                        std::set<string>* provided) const;
+  void GenerateRequiresForExtensions(
+      const GeneratorOptions& options, io::Printer* printer,
+      const vector<const FieldDescriptor*>& fields,
+      std::set<string>* provided) const;
   void GenerateRequiresImpl(const GeneratorOptions& options,
                             io::Printer* printer,
                             std::set<string>* required,
diff --git a/src/google/protobuf/compiler/mock_code_generator.cc b/src/google/protobuf/compiler/mock_code_generator.cc
index 121d917..82bb342 100644
--- a/src/google/protobuf/compiler/mock_code_generator.cc
+++ b/src/google/protobuf/compiler/mock_code_generator.cc
@@ -32,20 +32,26 @@
 
 #include <google/protobuf/compiler/mock_code_generator.h>
 
+#include <stdlib.h>
+#include <iostream>
 #include <memory>
 #ifndef _SHARED_PTR_H
 #include <google/protobuf/stubs/shared_ptr.h>
 #endif
+#include <vector>
 
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
 #include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/descriptor.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/io/printer.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/substitute.h>
 #include <gtest/gtest.h>
-#include <google/protobuf/stubs/stl_util.h>
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/mock_code_generator.h b/src/google/protobuf/compiler/mock_code_generator.h
index 8c8348d..e1665f8 100644
--- a/src/google/protobuf/compiler/mock_code_generator.h
+++ b/src/google/protobuf/compiler/mock_code_generator.h
@@ -34,10 +34,15 @@
 #define GOOGLE_PROTOBUF_COMPILER_MOCK_CODE_GENERATOR_H__
 
 #include <string>
+
 #include <google/protobuf/compiler/code_generator.h>
 
 namespace google {
 namespace protobuf {
+class FileDescriptor;
+}  // namespace protobuf
+
+namespace protobuf {
 namespace compiler {
 
 // A mock CodeGenerator, used by command_line_interface_unittest.  This is in
diff --git a/src/google/protobuf/compiler/plugin.cc b/src/google/protobuf/compiler/plugin.cc
index 2bebf1f..2ff50f6 100644
--- a/src/google/protobuf/compiler/plugin.cc
+++ b/src/google/protobuf/compiler/plugin.cc
@@ -93,6 +93,65 @@
   const vector<const FileDescriptor*>& parsed_files_;
 };
 
+bool GenerateCode(const CodeGeneratorRequest& request,
+    const CodeGenerator& generator, CodeGeneratorResponse* response,
+    string* error_msg) {
+  DescriptorPool pool;
+  for (int i = 0; i < request.proto_file_size(); i++) {
+    const FileDescriptor* file = pool.BuildFile(request.proto_file(i));
+    if (file == NULL) {
+      // BuildFile() already wrote an error message.
+      return false;
+    }
+  }
+
+  vector<const FileDescriptor*> parsed_files;
+  for (int i = 0; i < request.file_to_generate_size(); i++) {
+    parsed_files.push_back(pool.FindFileByName(request.file_to_generate(i)));
+    if (parsed_files.back() == NULL) {
+      *error_msg = "protoc asked plugin to generate a file but "
+                   "did not provide a descriptor for the file: " +
+                   request.file_to_generate(i);
+      return false;
+    }
+  }
+
+  GeneratorResponseContext context(response, parsed_files);
+
+  if (generator.HasGenerateAll()) {
+    string error;
+    bool succeeded = generator.GenerateAll(
+        parsed_files, request.parameter(), &context, &error);
+
+    if (!succeeded && error.empty()) {
+      error = "Code generator returned false but provided no error "
+              "description.";
+    }
+    if (!error.empty()) {
+      response->set_error(error);
+    }
+  } else {
+    for (int i = 0; i < parsed_files.size(); i++) {
+      const FileDescriptor* file = parsed_files[i];
+
+      string error;
+      bool succeeded = generator.Generate(
+          file, request.parameter(), &context, &error);
+
+      if (!succeeded && error.empty()) {
+        error = "Code generator returned false but provided no error "
+                "description.";
+      }
+      if (!error.empty()) {
+        response->set_error(file->name() + ": " + error);
+        break;
+      }
+    }
+  }
+
+  return true;
+}
+
 int PluginMain(int argc, char* argv[], const CodeGenerator* generator) {
 
   if (argc > 1) {
@@ -112,62 +171,18 @@
     return 1;
   }
 
-  DescriptorPool pool;
-  for (int i = 0; i < request.proto_file_size(); i++) {
-    const FileDescriptor* file = pool.BuildFile(request.proto_file(i));
-    if (file == NULL) {
-      // BuildFile() already wrote an error message.
-      return 1;
-    }
-  }
-
-  vector<const FileDescriptor*> parsed_files;
-  for (int i = 0; i < request.file_to_generate_size(); i++) {
-    parsed_files.push_back(pool.FindFileByName(request.file_to_generate(i)));
-    if (parsed_files.back() == NULL) {
-      std::cerr << argv[0] << ": protoc asked plugin to generate a file but "
-                              "did not provide a descriptor for the file: "
-                << request.file_to_generate(i) << std::endl;
-      return 1;
-    }
-  }
-
+  string error_msg;
   CodeGeneratorResponse response;
-  GeneratorResponseContext context(&response, parsed_files);
 
-  if (generator->HasGenerateAll()) {
-    string error;
-    bool succeeded = generator->GenerateAll(
-        parsed_files, request.parameter(), &context, &error);
-
-    if (!succeeded && error.empty()) {
-      error = "Code generator returned false but provided no error "
-              "description.";
-    }
-    if (!error.empty()) {
-      response.set_error(error);
+  if (GenerateCode(request, *generator, &response, &error_msg)) {
+    if (!response.SerializeToFileDescriptor(STDOUT_FILENO)) {
+      std::cerr << argv[0] << ": Error writing to stdout." << std::endl;
+      return 1;
     }
   } else {
-    for (int i = 0; i < parsed_files.size(); i++) {
-      const FileDescriptor* file = parsed_files[i];
-
-      string error;
-      bool succeeded = generator->Generate(
-          file, request.parameter(), &context, &error);
-
-      if (!succeeded && error.empty()) {
-        error = "Code generator returned false but provided no error "
-                "description.";
-      }
-      if (!error.empty()) {
-        response.set_error(file->name() + ": " + error);
-        break;
-      }
+    if (!error_msg.empty()) {
+      std::cerr << argv[0] << ": " << error_msg << std::endl;
     }
-  }
-
-  if (!response.SerializeToFileDescriptor(STDOUT_FILENO)) {
-    std::cerr << argv[0] << ": Error writing to stdout." << std::endl;
     return 1;
   }
 
diff --git a/src/google/protobuf/compiler/plugin.h b/src/google/protobuf/compiler/plugin.h
index 679f9bd..d2793a9 100644
--- a/src/google/protobuf/compiler/plugin.h
+++ b/src/google/protobuf/compiler/plugin.h
@@ -40,6 +40,13 @@
 //   }
 // You must link your plugin against libprotobuf and libprotoc.
 //
+// The core part of PluginMain is to invoke the given CodeGenerator on a
+// CodeGeneratorRequest to generate a CodeGeneratorResponse. This part is
+// abstracted out and made into function GenerateCode so that it can be reused,
+// for example, to implement a variant of PluginMain that does some
+// preprocessing on the input CodeGeneratorRequest before feeding the request
+// to the given code generator.
+//
 // To get protoc to use the plugin, do one of the following:
 // * Place the plugin binary somewhere in the PATH and give it the name
 //   "protoc-gen-NAME" (replacing "NAME" with the name of your plugin).  If you
@@ -55,16 +62,27 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_PLUGIN_H__
 #define GOOGLE_PROTOBUF_COMPILER_PLUGIN_H__
 
+#include <string>
+
 #include <google/protobuf/stubs/common.h>
 namespace google {
 namespace protobuf {
 namespace compiler {
 
 class CodeGenerator;    // code_generator.h
+class CodeGeneratorRequest;
+class CodeGeneratorResponse;
 
 // Implements main() for a protoc plugin exposing the given code generator.
 LIBPROTOC_EXPORT int PluginMain(int argc, char* argv[], const CodeGenerator* generator);
 
+// Generates code using the given code generator. Returns true if the code
+// generation is successful. If the code geneartion fails, error_msg may be
+// populated to describe the failure cause.
+bool GenerateCode(const CodeGeneratorRequest& request,
+    const CodeGenerator& generator, CodeGeneratorResponse* response,
+    string* error_msg);
+
 }  // namespace compiler
 }  // namespace protobuf
 
diff --git a/src/google/protobuf/compiler/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc
index 4d500f9..0553dd0 100644
--- a/src/google/protobuf/compiler/python/python_generator.cc
+++ b/src/google/protobuf/compiler/python/python_generator.cc
@@ -235,7 +235,7 @@
         // infinity * 0 = nan
         return "(1e10000 * 0)";
       } else {
-        return SimpleDtoa(value);
+        return "float(" + SimpleDtoa(value) + ")";
       }
     }
     case FieldDescriptor::CPPTYPE_FLOAT: {
@@ -251,7 +251,7 @@
         // infinity - infinity = nan
         return "(1e10000 * 0)";
       } else {
-        return SimpleFtoa(value);
+        return "float(" + SimpleFtoa(value) + ")";
       }
     }
     case FieldDescriptor::CPPTYPE_BOOL:
diff --git a/src/google/protobuf/compiler/subprocess.cc b/src/google/protobuf/compiler/subprocess.cc
index a30ac30..6e25866 100644
--- a/src/google/protobuf/compiler/subprocess.cc
+++ b/src/google/protobuf/compiler/subprocess.cc
@@ -361,7 +361,7 @@
   string output_data;
 
   int input_pos = 0;
-  int max_fd = max(child_stdin_, child_stdout_);
+  int max_fd = std::max(child_stdin_, child_stdout_);
 
   while (child_stdout_ != -1) {
     fd_set read_fds;
diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h
index 7e3a749..3ecc0a9 100644
--- a/src/google/protobuf/descriptor.h
+++ b/src/google/protobuf/descriptor.h
@@ -127,6 +127,11 @@
 class DescriptorTest;
 }  // namespace descriptor_unittest
 
+// Defined in printer.h
+namespace io {
+class Printer;
+}  // namespace io
+
 // NB, all indices are zero-based.
 struct SourceLocation {
   int start_line;
@@ -359,6 +364,9 @@
   // Allows tests to test CopyTo(proto, true).
   friend class ::google::protobuf::descriptor_unittest::DescriptorTest;
 
+  // Allows access to GetLocationPath for annotations.
+  friend class ::google::protobuf::io::Printer;
+
   // Fill the json_name field of FieldDescriptorProto.
   void CopyJsonNameTo(DescriptorProto* proto) const;
 
@@ -644,6 +652,9 @@
  private:
   typedef FieldOptions OptionsType;
 
+  // Allows access to GetLocationPath for annotations.
+  friend class ::google::protobuf::io::Printer;
+
   // Fill the json_name field of FieldDescriptorProto.
   void CopyJsonNameTo(FieldDescriptorProto* proto) const;
 
@@ -756,6 +767,9 @@
   bool GetSourceLocation(SourceLocation* out_location) const;
 
  private:
+  // Allows access to GetLocationPath for annotations.
+  friend class ::google::protobuf::io::Printer;
+
   // See Descriptor::DebugString().
   void DebugString(int depth, string* contents,
                    const DebugStringOptions& options) const;
@@ -846,6 +860,9 @@
  private:
   typedef EnumOptions OptionsType;
 
+  // Allows access to GetLocationPath for annotations.
+  friend class ::google::protobuf::io::Printer;
+
   // Looks up a value by number.  If the value does not exist, dynamically
   // creates a new EnumValueDescriptor for that value, assuming that it was
   // unknown. If a new descriptor is created, this is done in a thread-safe way,
@@ -942,6 +959,9 @@
  private:
   typedef EnumValueOptions OptionsType;
 
+  // Allows access to GetLocationPath for annotations.
+  friend class ::google::protobuf::io::Printer;
+
   // See Descriptor::DebugString().
   void DebugString(int depth, string *contents,
                    const DebugStringOptions& options) const;
@@ -1018,6 +1038,9 @@
  private:
   typedef ServiceOptions OptionsType;
 
+  // Allows access to GetLocationPath for annotations.
+  friend class ::google::protobuf::io::Printer;
+
   // See Descriptor::DebugString().
   void DebugString(string *contents, const DebugStringOptions& options) const;
 
@@ -1096,6 +1119,9 @@
  private:
   typedef MethodOptions OptionsType;
 
+  // Allows access to GetLocationPath for annotations.
+  friend class ::google::protobuf::io::Printer;
+
   // See Descriptor::DebugString().
   void DebugString(int depth, string *contents,
                    const DebugStringOptions& options) const;
diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc
index ff0cfcf..1338537 100644
--- a/src/google/protobuf/descriptor.pb.cc
+++ b/src/google/protobuf/descriptor.pb.cc
@@ -319,7 +319,7 @@
       GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, _internal_metadata_),
       -1);
   FileOptions_descriptor_ = file->message_type(9);
-  static const int FileOptions_offsets_[16] = {
+  static const int FileOptions_offsets_[15] = {
     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_),
@@ -334,7 +334,6 @@
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, cc_enable_arenas_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, objc_class_prefix_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, csharp_namespace_),
-    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, javanano_use_deprecated_package_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, uninterpreted_option_),
   };
   FileOptions_reflection_ =
@@ -746,7 +745,7 @@
     "_type\030\003 \001(\t\022/\n\007options\030\004 \001(\0132\036.google.pr"
     "otobuf.MethodOptions\022\037\n\020client_streaming"
     "\030\005 \001(\010:\005false\022\037\n\020server_streaming\030\006 \001(\010:"
-    "\005false\"\256\005\n\013FileOptions\022\024\n\014java_package\030\001"
+    "\005false\"\207\005\n\013FileOptions\022\024\n\014java_package\030\001"
     " \001(\t\022\034\n\024java_outer_classname\030\010 \001(\t\022\"\n\023ja"
     "va_multiple_files\030\n \001(\010:\005false\022,\n\035java_g"
     "enerate_equals_and_hash\030\024 \001(\010:\005false\022%\n\026"
@@ -758,60 +757,59 @@
     "e\022\"\n\023py_generic_services\030\022 \001(\010:\005false\022\031\n"
     "\ndeprecated\030\027 \001(\010:\005false\022\037\n\020cc_enable_ar"
     "enas\030\037 \001(\010:\005false\022\031\n\021objc_class_prefix\030$"
-    " \001(\t\022\030\n\020csharp_namespace\030% \001(\t\022+\n\037javana"
-    "no_use_deprecated_package\030& \001(\010B\002\030\001\022C\n\024u"
-    "ninterpreted_option\030\347\007 \003(\0132$.google.prot"
-    "obuf.UninterpretedOption\":\n\014OptimizeMode"
-    "\022\t\n\005SPEED\020\001\022\r\n\tCODE_SIZE\020\002\022\020\n\014LITE_RUNTI"
-    "ME\020\003*\t\010\350\007\020\200\200\200\200\002\"\346\001\n\016MessageOptions\022&\n\027me"
-    "ssage_set_wire_format\030\001 \001(\010:\005false\022.\n\037no"
-    "_standard_descriptor_accessor\030\002 \001(\010:\005fal"
-    "se\022\031\n\ndeprecated\030\003 \001(\010:\005false\022\021\n\tmap_ent"
-    "ry\030\007 \001(\010\022C\n\024uninterpreted_option\030\347\007 \003(\0132"
-    "$.google.protobuf.UninterpretedOption*\t\010"
-    "\350\007\020\200\200\200\200\002\"\230\003\n\014FieldOptions\022:\n\005ctype\030\001 \001(\016"
-    "2#.google.protobuf.FieldOptions.CType:\006S"
-    "TRING\022\016\n\006packed\030\002 \001(\010\022\?\n\006jstype\030\006 \001(\0162$."
-    "google.protobuf.FieldOptions.JSType:\tJS_"
-    "NORMAL\022\023\n\004lazy\030\005 \001(\010:\005false\022\031\n\ndeprecate"
-    "d\030\003 \001(\010:\005false\022\023\n\004weak\030\n \001(\010:\005false\022C\n\024u"
-    "ninterpreted_option\030\347\007 \003(\0132$.google.prot"
-    "obuf.UninterpretedOption\"/\n\005CType\022\n\n\006STR"
-    "ING\020\000\022\010\n\004CORD\020\001\022\020\n\014STRING_PIECE\020\002\"5\n\006JST"
-    "ype\022\r\n\tJS_NORMAL\020\000\022\r\n\tJS_STRING\020\001\022\r\n\tJS_"
-    "NUMBER\020\002*\t\010\350\007\020\200\200\200\200\002\"\215\001\n\013EnumOptions\022\023\n\013a"
-    "llow_alias\030\002 \001(\010\022\031\n\ndeprecated\030\003 \001(\010:\005fa"
-    "lse\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.goo"
-    "gle.protobuf.UninterpretedOption*\t\010\350\007\020\200\200"
-    "\200\200\002\"}\n\020EnumValueOptions\022\031\n\ndeprecated\030\001 "
-    "\001(\010:\005false\022C\n\024uninterpreted_option\030\347\007 \003("
-    "\0132$.google.protobuf.UninterpretedOption*"
-    "\t\010\350\007\020\200\200\200\200\002\"{\n\016ServiceOptions\022\031\n\ndeprecat"
-    "ed\030! \001(\010:\005false\022C\n\024uninterpreted_option\030"
-    "\347\007 \003(\0132$.google.protobuf.UninterpretedOp"
-    "tion*\t\010\350\007\020\200\200\200\200\002\"z\n\rMethodOptions\022\031\n\ndepr"
-    "ecated\030! \001(\010:\005false\022C\n\024uninterpreted_opt"
-    "ion\030\347\007 \003(\0132$.google.protobuf.Uninterpret"
-    "edOption*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023UninterpretedOpt"
-    "ion\022;\n\004name\030\002 \003(\0132-.google.protobuf.Unin"
-    "terpretedOption.NamePart\022\030\n\020identifier_v"
-    "alue\030\003 \001(\t\022\032\n\022positive_int_value\030\004 \001(\004\022\032"
-    "\n\022negative_int_value\030\005 \001(\003\022\024\n\014double_val"
-    "ue\030\006 \001(\001\022\024\n\014string_value\030\007 \001(\014\022\027\n\017aggreg"
-    "ate_value\030\010 \001(\t\0323\n\010NamePart\022\021\n\tname_part"
-    "\030\001 \002(\t\022\024\n\014is_extension\030\002 \002(\010\"\325\001\n\016SourceC"
-    "odeInfo\022:\n\010location\030\001 \003(\0132(.google.proto"
-    "buf.SourceCodeInfo.Location\032\206\001\n\010Location"
-    "\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n\004span\030\002 \003(\005B\002\020\001\022\030\n\020"
-    "leading_comments\030\003 \001(\t\022\031\n\021trailing_comme"
-    "nts\030\004 \001(\t\022!\n\031leading_detached_comments\030\006"
-    " \003(\t\"\247\001\n\021GeneratedCodeInfo\022A\n\nannotation"
-    "\030\001 \003(\0132-.google.protobuf.GeneratedCodeIn"
-    "fo.Annotation\032O\n\nAnnotation\022\020\n\004path\030\001 \003("
-    "\005B\002\020\001\022\023\n\013source_file\030\002 \001(\t\022\r\n\005begin\030\003 \001("
-    "\005\022\013\n\003end\030\004 \001(\005BX\n\023com.google.protobufB\020D"
-    "escriptorProtosH\001Z\ndescriptor\242\002\003GPB\252\002\032Go"
-    "ogle.Protobuf.Reflection", 5184);
+    " \001(\t\022\030\n\020csharp_namespace\030% \001(\t\022C\n\024uninte"
+    "rpreted_option\030\347\007 \003(\0132$.google.protobuf."
+    "UninterpretedOption\":\n\014OptimizeMode\022\t\n\005S"
+    "PEED\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\002J\004\010&\020\'\"\346\001\n\016MessageOptions\022&\n\027m"
+    "essage_set_wire_format\030\001 \001(\010:\005false\022.\n\037n"
+    "o_standard_descriptor_accessor\030\002 \001(\010:\005fa"
+    "lse\022\031\n\ndeprecated\030\003 \001(\010:\005false\022\021\n\tmap_en"
+    "try\030\007 \001(\010\022C\n\024uninterpreted_option\030\347\007 \003(\013"
+    "2$.google.protobuf.UninterpretedOption*\t"
+    "\010\350\007\020\200\200\200\200\002\"\230\003\n\014FieldOptions\022:\n\005ctype\030\001 \001("
+    "\0162#.google.protobuf.FieldOptions.CType:\006"
+    "STRING\022\016\n\006packed\030\002 \001(\010\022\?\n\006jstype\030\006 \001(\0162$"
+    ".google.protobuf.FieldOptions.JSType:\tJS"
+    "_NORMAL\022\023\n\004lazy\030\005 \001(\010:\005false\022\031\n\ndeprecat"
+    "ed\030\003 \001(\010:\005false\022\023\n\004weak\030\n \001(\010:\005false\022C\n\024"
+    "uninterpreted_option\030\347\007 \003(\0132$.google.pro"
+    "tobuf.UninterpretedOption\"/\n\005CType\022\n\n\006ST"
+    "RING\020\000\022\010\n\004CORD\020\001\022\020\n\014STRING_PIECE\020\002\"5\n\006JS"
+    "Type\022\r\n\tJS_NORMAL\020\000\022\r\n\tJS_STRING\020\001\022\r\n\tJS"
+    "_NUMBER\020\002*\t\010\350\007\020\200\200\200\200\002\"\215\001\n\013EnumOptions\022\023\n\013"
+    "allow_alias\030\002 \001(\010\022\031\n\ndeprecated\030\003 \001(\010:\005f"
+    "alse\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.go"
+    "ogle.protobuf.UninterpretedOption*\t\010\350\007\020\200"
+    "\200\200\200\002\"}\n\020EnumValueOptions\022\031\n\ndeprecated\030\001"
+    " \001(\010:\005false\022C\n\024uninterpreted_option\030\347\007 \003"
+    "(\0132$.google.protobuf.UninterpretedOption"
+    "*\t\010\350\007\020\200\200\200\200\002\"{\n\016ServiceOptions\022\031\n\ndepreca"
+    "ted\030! \001(\010:\005false\022C\n\024uninterpreted_option"
+    "\030\347\007 \003(\0132$.google.protobuf.UninterpretedO"
+    "ption*\t\010\350\007\020\200\200\200\200\002\"z\n\rMethodOptions\022\031\n\ndep"
+    "recated\030! \001(\010:\005false\022C\n\024uninterpreted_op"
+    "tion\030\347\007 \003(\0132$.google.protobuf.Uninterpre"
+    "tedOption*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023UninterpretedOp"
+    "tion\022;\n\004name\030\002 \003(\0132-.google.protobuf.Uni"
+    "nterpretedOption.NamePart\022\030\n\020identifier_"
+    "value\030\003 \001(\t\022\032\n\022positive_int_value\030\004 \001(\004\022"
+    "\032\n\022negative_int_value\030\005 \001(\003\022\024\n\014double_va"
+    "lue\030\006 \001(\001\022\024\n\014string_value\030\007 \001(\014\022\027\n\017aggre"
+    "gate_value\030\010 \001(\t\0323\n\010NamePart\022\021\n\tname_par"
+    "t\030\001 \002(\t\022\024\n\014is_extension\030\002 \002(\010\"\325\001\n\016Source"
+    "CodeInfo\022:\n\010location\030\001 \003(\0132(.google.prot"
+    "obuf.SourceCodeInfo.Location\032\206\001\n\010Locatio"
+    "n\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n\004span\030\002 \003(\005B\002\020\001\022\030\n"
+    "\020leading_comments\030\003 \001(\t\022\031\n\021trailing_comm"
+    "ents\030\004 \001(\t\022!\n\031leading_detached_comments\030"
+    "\006 \003(\t\"\247\001\n\021GeneratedCodeInfo\022A\n\nannotatio"
+    "n\030\001 \003(\0132-.google.protobuf.GeneratedCodeI"
+    "nfo.Annotation\032O\n\nAnnotation\022\020\n\004path\030\001 \003"
+    "(\005B\002\020\001\022\023\n\013source_file\030\002 \001(\t\022\r\n\005begin\030\003 \001"
+    "(\005\022\013\n\003end\030\004 \001(\005BX\n\023com.google.protobufB\020"
+    "DescriptorProtosH\001Z\ndescriptor\242\002\003GPB\252\002\032G"
+    "oogle.Protobuf.Reflection", 5145);
   ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
     "google/protobuf/descriptor.proto", &protobuf_RegisterTypes);
   FileDescriptorSet::default_instance_ = new FileDescriptorSet();
@@ -7770,7 +7768,6 @@
 const int FileOptions::kCcEnableArenasFieldNumber;
 const int FileOptions::kObjcClassPrefixFieldNumber;
 const int FileOptions::kCsharpNamespaceFieldNumber;
-const int FileOptions::kJavananoUseDeprecatedPackageFieldNumber;
 const int FileOptions::kUninterpretedOptionFieldNumber;
 #endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
 
@@ -7808,7 +7805,6 @@
   cc_enable_arenas_ = false;
   objc_class_prefix_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   csharp_namespace_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  javanano_use_deprecated_package_ = false;
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
 }
 
@@ -7875,8 +7871,8 @@
       go_package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
     }
   }
-  if (_has_bits_[8 / 32] & 32512u) {
-    ZR_(java_generic_services_, javanano_use_deprecated_package_);
+  if (_has_bits_[8 / 32] & 16128u) {
+    ZR_(java_generic_services_, cc_enable_arenas_);
     if (has_objc_class_prefix()) {
       objc_class_prefix_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
     }
@@ -8125,21 +8121,6 @@
         } else {
           goto handle_unusual;
         }
-        if (input->ExpectTag(304)) goto parse_javanano_use_deprecated_package;
-        break;
-      }
-
-      // optional bool javanano_use_deprecated_package = 38 [deprecated = true];
-      case 38: {
-        if (tag == 304) {
-         parse_javanano_use_deprecated_package:
-          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
-                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
-                 input, &javanano_use_deprecated_package_)));
-          set_has_javanano_use_deprecated_package();
-        } else {
-          goto handle_unusual;
-        }
         if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
         break;
       }
@@ -8287,11 +8268,6 @@
       37, this->csharp_namespace(), output);
   }
 
-  // optional bool javanano_use_deprecated_package = 38 [deprecated = true];
-  if (has_javanano_use_deprecated_package()) {
-    ::google::protobuf::internal::WireFormatLite::WriteBool(38, this->javanano_use_deprecated_package(), output);
-  }
-
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
@@ -8413,11 +8389,6 @@
         37, this->csharp_namespace(), target);
   }
 
-  // optional bool javanano_use_deprecated_package = 38 [deprecated = true];
-  if (has_javanano_use_deprecated_package()) {
-    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(38, this->javanano_use_deprecated_package(), target);
-  }
-
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
@@ -8489,7 +8460,7 @@
     }
 
   }
-  if (_has_bits_[8 / 32] & 32512u) {
+  if (_has_bits_[8 / 32] & 16128u) {
     // optional bool java_generic_services = 17 [default = false];
     if (has_java_generic_services()) {
       total_size += 2 + 1;
@@ -8524,11 +8495,6 @@
           this->csharp_namespace());
     }
 
-    // optional bool javanano_use_deprecated_package = 38 [deprecated = true];
-    if (has_javanano_use_deprecated_package()) {
-      total_size += 2 + 1;
-    }
-
   }
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   total_size += 2 * this->uninterpreted_option_size();
@@ -8616,9 +8582,6 @@
       set_has_csharp_namespace();
       csharp_namespace_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.csharp_namespace_);
     }
-    if (from.has_javanano_use_deprecated_package()) {
-      set_javanano_use_deprecated_package(from.javanano_use_deprecated_package());
-    }
   }
   _extensions_.MergeFrom(from._extensions_);
   if (from._internal_metadata_.have_unknown_fields()) {
@@ -8664,7 +8627,6 @@
   std::swap(cc_enable_arenas_, other->cc_enable_arenas_);
   objc_class_prefix_.Swap(&other->objc_class_prefix_);
   csharp_namespace_.Swap(&other->csharp_namespace_);
-  std::swap(javanano_use_deprecated_package_, other->javanano_use_deprecated_package_);
   uninterpreted_option_.UnsafeArenaSwap(&other->uninterpreted_option_);
   std::swap(_has_bits_[0], other->_has_bits_[0]);
   _internal_metadata_.Swap(&other->_internal_metadata_);
@@ -9165,30 +9127,6 @@
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.csharp_namespace)
 }
 
-// optional bool javanano_use_deprecated_package = 38 [deprecated = true];
-bool FileOptions::has_javanano_use_deprecated_package() const {
-  return (_has_bits_[0] & 0x00004000u) != 0;
-}
-void FileOptions::set_has_javanano_use_deprecated_package() {
-  _has_bits_[0] |= 0x00004000u;
-}
-void FileOptions::clear_has_javanano_use_deprecated_package() {
-  _has_bits_[0] &= ~0x00004000u;
-}
-void FileOptions::clear_javanano_use_deprecated_package() {
-  javanano_use_deprecated_package_ = false;
-  clear_has_javanano_use_deprecated_package();
-}
- bool FileOptions::javanano_use_deprecated_package() const {
-  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.javanano_use_deprecated_package)
-  return javanano_use_deprecated_package_;
-}
- void FileOptions::set_javanano_use_deprecated_package(bool value) {
-  set_has_javanano_use_deprecated_package();
-  javanano_use_deprecated_package_ = value;
-  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.javanano_use_deprecated_package)
-}
-
 // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
 int FileOptions::uninterpreted_option_size() const {
   return uninterpreted_option_.size();
diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h
index 3fe07bf..9f15bf2 100644
--- a/src/google/protobuf/descriptor.pb.h
+++ b/src/google/protobuf/descriptor.pb.h
@@ -2017,13 +2017,6 @@
   ::std::string* release_csharp_namespace();
   void set_allocated_csharp_namespace(::std::string* csharp_namespace);
 
-  // optional bool javanano_use_deprecated_package = 38 [deprecated = true];
-  bool has_javanano_use_deprecated_package() const PROTOBUF_DEPRECATED;
-  void clear_javanano_use_deprecated_package() PROTOBUF_DEPRECATED;
-  static const int kJavananoUseDeprecatedPackageFieldNumber = 38;
-  bool javanano_use_deprecated_package() const PROTOBUF_DEPRECATED;
-  void set_javanano_use_deprecated_package(bool value) PROTOBUF_DEPRECATED;
-
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   int uninterpreted_option_size() const;
   void clear_uninterpreted_option();
@@ -2067,8 +2060,6 @@
   inline void clear_has_objc_class_prefix();
   inline void set_has_csharp_namespace();
   inline void clear_has_csharp_namespace();
-  inline void set_has_javanano_use_deprecated_package();
-  inline void clear_has_javanano_use_deprecated_package();
 
   ::google::protobuf::internal::ExtensionSet _extensions_;
 
@@ -2083,14 +2074,13 @@
   bool cc_generic_services_;
   int optimize_for_;
   ::google::protobuf::internal::ArenaStringPtr go_package_;
+  ::google::protobuf::internal::ArenaStringPtr objc_class_prefix_;
+  ::google::protobuf::internal::ArenaStringPtr csharp_namespace_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
   bool java_generic_services_;
   bool py_generic_services_;
   bool deprecated_;
   bool cc_enable_arenas_;
-  bool javanano_use_deprecated_package_;
-  ::google::protobuf::internal::ArenaStringPtr objc_class_prefix_;
-  ::google::protobuf::internal::ArenaStringPtr csharp_namespace_;
-  ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
   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();
@@ -6194,30 +6184,6 @@
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.csharp_namespace)
 }
 
-// optional bool javanano_use_deprecated_package = 38 [deprecated = true];
-inline bool FileOptions::has_javanano_use_deprecated_package() const {
-  return (_has_bits_[0] & 0x00004000u) != 0;
-}
-inline void FileOptions::set_has_javanano_use_deprecated_package() {
-  _has_bits_[0] |= 0x00004000u;
-}
-inline void FileOptions::clear_has_javanano_use_deprecated_package() {
-  _has_bits_[0] &= ~0x00004000u;
-}
-inline void FileOptions::clear_javanano_use_deprecated_package() {
-  javanano_use_deprecated_package_ = false;
-  clear_has_javanano_use_deprecated_package();
-}
-inline bool FileOptions::javanano_use_deprecated_package() const {
-  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.javanano_use_deprecated_package)
-  return javanano_use_deprecated_package_;
-}
-inline void FileOptions::set_javanano_use_deprecated_package(bool value) {
-  set_has_javanano_use_deprecated_package();
-  javanano_use_deprecated_package_ = value;
-  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.javanano_use_deprecated_package)
-}
-
 // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
 inline int FileOptions::uninterpreted_option_size() const {
   return uninterpreted_option_.size();
diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto
index 3e664d5..08b1555 100644
--- a/src/google/protobuf/descriptor.proto
+++ b/src/google/protobuf/descriptor.proto
@@ -377,15 +377,13 @@
   // Namespace for generated classes; defaults to the package.
   optional string csharp_namespace = 37;
 
-  // Whether the nano proto compiler should generate in the deprecated non-nano
-  // suffixed package.
-  optional bool javanano_use_deprecated_package = 38 [deprecated = true];
-
   // The parser stores options it doesn't recognize here. See above.
   repeated UninterpretedOption uninterpreted_option = 999;
 
   // Clients can define custom options in extensions of this message. See above.
   extensions 1000 to max;
+
+  reserved 38;
 }
 
 message MessageOptions {
diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc
index be8e0b7..e4720a7 100644
--- a/src/google/protobuf/descriptor_unittest.cc
+++ b/src/google/protobuf/descriptor_unittest.cc
@@ -54,6 +54,7 @@
 
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/scoped_ptr.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
diff --git a/src/google/protobuf/duration.pb.cc b/src/google/protobuf/duration.pb.cc
index b325944..c71ce66 100644
--- a/src/google/protobuf/duration.pb.cc
+++ b/src/google/protobuf/duration.pb.cc
@@ -83,9 +83,10 @@
   ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
     "\n\036google/protobuf/duration.proto\022\017google"
     ".protobuf\"*\n\010Duration\022\017\n\007seconds\030\001 \001(\003\022\r"
-    "\n\005nanos\030\002 \001(\005BP\n\023com.google.protobufB\rDu"
-    "rationProtoP\001\240\001\001\242\002\003GPB\252\002\036Google.Protobuf"
-    ".WellKnownTypesb\006proto3", 183);
+    "\n\005nanos\030\002 \001(\005B|\n\023com.google.protobufB\rDu"
+    "rationProtoP\001Z*github.com/golang/protobu"
+    "f/ptypes/duration\240\001\001\242\002\003GPB\252\002\036Google.Prot"
+    "obuf.WellKnownTypesb\006proto3", 227);
   ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
     "google/protobuf/duration.proto", &protobuf_RegisterTypes);
   Duration::default_instance_ = new Duration();
diff --git a/src/google/protobuf/duration.proto b/src/google/protobuf/duration.proto
index 78bcc74..96c1796 100644
--- a/src/google/protobuf/duration.proto
+++ b/src/google/protobuf/duration.proto
@@ -33,6 +33,7 @@
 package google.protobuf;
 
 option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option go_package = "github.com/golang/protobuf/ptypes/duration";
 option java_package = "com.google.protobuf";
 option java_outer_classname = "DurationProto";
 option java_multiple_files = true;
@@ -80,6 +81,7 @@
 //       end.nanos -= 1000000000;
 //     }
 //
+//
 message Duration {
 
   // Signed seconds of the span of time. Must be from -315,576,000,000
diff --git a/src/google/protobuf/dynamic_message.cc b/src/google/protobuf/dynamic_message.cc
index 8d689ac..9e83bd2 100644
--- a/src/google/protobuf/dynamic_message.cc
+++ b/src/google/protobuf/dynamic_message.cc
@@ -267,6 +267,16 @@
 
   Metadata GetMetadata() const;
 
+  // We actually allocate more memory than sizeof(*this) when this
+  // class's memory is allocated via the global operator new. Thus, we need to
+  // manually call the global operator delete. Calling the destructor is taken
+  // care of for us. This makes DynamicMessage compatible with -fsized-delete.
+  // It doesn't work for MSVC though.
+#ifndef _MSC_VER
+  static void operator delete(void* ptr) {
+    ::operator delete(ptr);
+  }
+#endif  // !_MSC_VER
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage);
@@ -442,8 +452,10 @@
             case FieldOptions::STRING: {
               const ::std::string* default_value =
                   &(reinterpret_cast<const ArenaStringPtr*>(
-                      type_info_->prototype->OffsetToPointer(
-                          type_info_->offsets[i]))->Get(NULL));
+                      reinterpret_cast<uint8*>(
+                          type_info_->default_oneof_instance)
+                      + type_info_->offsets[i])
+                    ->Get(NULL));
               reinterpret_cast<ArenaStringPtr*>(field_ptr)->Destroy(
                   default_value, NULL);
               break;
@@ -704,7 +716,7 @@
     // Oneof fields do not use any space.
     if (!type->field(i)->containing_oneof()) {
       int field_size = FieldSpaceUsed(type->field(i));
-      size = AlignTo(size, min(kSafeAlignment, field_size));
+      size = AlignTo(size, std::min(kSafeAlignment, field_size));
       offsets[i] = size;
       size += field_size;
     }
@@ -748,7 +760,7 @@
       for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) {
         const FieldDescriptor* field = type->oneof_decl(i)->field(j);
         int field_size = OneofFieldSpaceUsed(field);
-        oneof_size = AlignTo(oneof_size, min(kSafeAlignment, field_size));
+        oneof_size = AlignTo(oneof_size, std::min(kSafeAlignment, field_size));
         offsets[field->index()] = oneof_size;
         oneof_size += field_size;
       }
diff --git a/src/google/protobuf/empty.pb.cc b/src/google/protobuf/empty.pb.cc
index f2eec78..4550921 100644
--- a/src/google/protobuf/empty.pb.cc
+++ b/src/google/protobuf/empty.pb.cc
@@ -80,9 +80,10 @@
 
   ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
     "\n\033google/protobuf/empty.proto\022\017google.pr"
-    "otobuf\"\007\n\005EmptyBP\n\023com.google.protobufB\n"
-    "EmptyProtoP\001\240\001\001\370\001\001\242\002\003GPB\252\002\036Google.Protob"
-    "uf.WellKnownTypesb\006proto3", 145);
+    "otobuf\"\007\n\005EmptyBy\n\023com.google.protobufB\n"
+    "EmptyProtoP\001Z\'github.com/golang/protobuf"
+    "/ptypes/empty\240\001\001\370\001\001\242\002\003GPB\252\002\036Google.Proto"
+    "buf.WellKnownTypesb\006proto3", 186);
   ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
     "google/protobuf/empty.proto", &protobuf_RegisterTypes);
   Empty::default_instance_ = new Empty();
diff --git a/src/google/protobuf/empty.proto b/src/google/protobuf/empty.proto
index b96daf2..37f4cd1 100644
--- a/src/google/protobuf/empty.proto
+++ b/src/google/protobuf/empty.proto
@@ -33,6 +33,7 @@
 package google.protobuf;
 
 option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option go_package = "github.com/golang/protobuf/ptypes/empty";
 option java_package = "com.google.protobuf";
 option java_outer_classname = "EmptyProto";
 option java_multiple_files = true;
diff --git a/src/google/protobuf/field_mask.proto b/src/google/protobuf/field_mask.proto
index 908c8a8..b1657f5 100644
--- a/src/google/protobuf/field_mask.proto
+++ b/src/google/protobuf/field_mask.proto
@@ -162,6 +162,32 @@
 //       mask: "user.displayName,photo"
 //     }
 //
+// # Field Masks and Oneof Fields
+//
+// Field masks treat fields in oneofs just as regular fields. Consider the
+// following message:
+//
+//     message SampleMessage {
+//       oneof test_oneof {
+//         string name = 4;
+//         SubMessage sub_message = 9;
+//       }
+//     }
+//
+// The field mask can be:
+//
+//     mask {
+//       paths: "name"
+//     }
+//
+// Or:
+//
+//     mask {
+//       paths: "sub_message"
+//     }
+//
+// Note that oneof type names ("test_oneof" in this case) cannot be used in
+// paths.
 message FieldMask {
   // The set of field mask paths.
   repeated string paths = 1;
diff --git a/src/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc
index e3a34d0..d8354c1 100644
--- a/src/google/protobuf/io/coded_stream.cc
+++ b/src/google/protobuf/io/coded_stream.cc
@@ -105,7 +105,7 @@
 
 inline void CodedInputStream::RecomputeBufferLimits() {
   buffer_end_ += buffer_size_after_limit_;
-  int closest_limit = min(current_limit_, total_bytes_limit_);
+  int closest_limit = std::min(current_limit_, total_bytes_limit_);
   if (closest_limit < total_bytes_read_) {
     // The limit position is in the current buffer.  We must adjust
     // the buffer size accordingly.
@@ -135,7 +135,7 @@
   // We need to enforce all limits, not just the new one, so if the previous
   // limit was before the new requested limit, we continue to enforce the
   // previous limit.
-  current_limit_ = min(current_limit_, old_limit);
+  current_limit_ = std::min(current_limit_, old_limit);
 
   RecomputeBufferLimits();
   return old_limit;
@@ -188,7 +188,7 @@
   // Make sure the limit isn't already past, since this could confuse other
   // code.
   int current_position = CurrentPosition();
-  total_bytes_limit_ = max(current_position, total_bytes_limit);
+  total_bytes_limit_ = std::max(current_position, total_bytes_limit);
   if (warning_threshold >= 0) {
     total_bytes_warning_threshold_ = warning_threshold;
   } else {
@@ -233,7 +233,7 @@
   buffer_end_ = buffer_;
 
   // Make sure this skip doesn't try to skip past the current limit.
-  int closest_limit = min(current_limit_, total_bytes_limit_);
+  int closest_limit = std::min(current_limit_, total_bytes_limit_);
   int bytes_until_limit = closest_limit - total_bytes_read_;
   if (bytes_until_limit < count) {
     // We hit the limit.  Skip up to it then fail.
@@ -270,7 +270,7 @@
     buffer->clear();
   }
 
-  int closest_limit = min(current_limit_, total_bytes_limit_);
+  int closest_limit = std::min(current_limit_, total_bytes_limit_);
   if (closest_limit != INT_MAX) {
     int bytes_to_limit = closest_limit - CurrentPosition();
     if (bytes_to_limit > 0 && size > 0 && size <= bytes_to_limit) {
diff --git a/src/google/protobuf/io/coded_stream_unittest.cc b/src/google/protobuf/io/coded_stream_unittest.cc
index d1782e3..f10d467 100644
--- a/src/google/protobuf/io/coded_stream_unittest.cc
+++ b/src/google/protobuf/io/coded_stream_unittest.cc
@@ -46,6 +46,7 @@
 
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/scoped_ptr.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
diff --git a/src/google/protobuf/io/gzip_stream.h b/src/google/protobuf/io/gzip_stream.h
index 8244500..15b02fe 100644
--- a/src/google/protobuf/io/gzip_stream.h
+++ b/src/google/protobuf/io/gzip_stream.h
@@ -43,10 +43,9 @@
 #ifndef GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__
 #define GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__
 
-#include <zlib.h>
-
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/io/zero_copy_stream.h>
+#include <zlib.h>
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/io/printer.cc b/src/google/protobuf/io/printer.cc
index 7d88650..7532b09 100644
--- a/src/google/protobuf/io/printer.cc
+++ b/src/google/protobuf/io/printer.cc
@@ -42,13 +42,25 @@
 namespace io {
 
 Printer::Printer(ZeroCopyOutputStream* output, char variable_delimiter)
-  : variable_delimiter_(variable_delimiter),
-    output_(output),
-    buffer_(NULL),
-    buffer_size_(0),
-    at_start_of_line_(true),
-    failed_(false) {
-}
+    : variable_delimiter_(variable_delimiter),
+      output_(output),
+      buffer_(NULL),
+      buffer_size_(0),
+      offset_(0),
+      at_start_of_line_(true),
+      failed_(false),
+      annotation_collector_(NULL) {}
+
+Printer::Printer(ZeroCopyOutputStream* output, char variable_delimiter,
+                 AnnotationCollector* annotation_collector)
+    : variable_delimiter_(variable_delimiter),
+      output_(output),
+      buffer_(NULL),
+      buffer_size_(0),
+      offset_(0),
+      at_start_of_line_(true),
+      failed_(false),
+      annotation_collector_(annotation_collector) {}
 
 Printer::~Printer() {
   // Only BackUp() if we have called Next() at least once and never failed.
@@ -57,9 +69,47 @@
   }
 }
 
+bool Printer::GetSubstitutionRange(const char* varname,
+                                   pair<size_t, size_t>* range) {
+  map<string, pair<size_t, size_t> >::const_iterator iter =
+      substitutions_.find(varname);
+  if (iter == substitutions_.end()) {
+    GOOGLE_LOG(DFATAL) << " Undefined variable in annotation: " << varname;
+    return false;
+  }
+  if (iter->second.first > iter->second.second) {
+    GOOGLE_LOG(DFATAL) << " Variable used for annotation used multiple times: "
+                << varname;
+    return false;
+  }
+  *range = iter->second;
+  return true;
+}
+
+void Printer::Annotate(const char* begin_varname, const char* end_varname,
+                       const string& file_path, const vector<int>& path) {
+  if (annotation_collector_ == NULL) {
+    // Can't generate signatures with this Printer.
+    return;
+  }
+  pair<size_t, size_t> begin, end;
+  if (!GetSubstitutionRange(begin_varname, &begin) ||
+      !GetSubstitutionRange(end_varname, &end)) {
+    return;
+  }
+  if (begin.first > end.second) {
+    GOOGLE_LOG(DFATAL) << "  Annotation has negative length from " << begin_varname
+                << " to " << end_varname;
+  } else {
+    annotation_collector_->AddAnnotation(begin.first, end.second, file_path,
+                                         path);
+  }
+}
+
 void Printer::Print(const map<string, string>& variables, const char* text) {
   int size = strlen(text);
   int pos = 0;  // The number of bytes we've written so far.
+  substitutions_.clear();
 
   for (int i = 0; i < size; i++) {
     if (text[i] == '\n') {
@@ -97,7 +147,17 @@
         if (iter == variables.end()) {
           GOOGLE_LOG(DFATAL) << " Undefined variable: " << varname;
         } else {
+          size_t begin = offset_;
           WriteRaw(iter->second.data(), iter->second.size());
+          pair<map<string, pair<size_t, size_t> >::iterator, bool> inserted =
+              substitutions_.insert(
+                  std::make_pair(varname, std::make_pair(begin, offset_)));
+          if (!inserted.second) {
+            // This variable was used multiple times.  Make its span have
+            // negative length so we can detect it if it gets used in an
+            // annotation.
+            inserted.first->second = std::make_pair(1, 0);
+          }
         }
       }
 
@@ -265,6 +325,7 @@
     // Data exceeds space in the buffer.  Copy what we can and request a
     // new buffer.
     memcpy(buffer_, data, buffer_size_);
+    offset_ += buffer_size_;
     data += buffer_size_;
     size -= buffer_size_;
     void* void_buffer;
@@ -277,6 +338,7 @@
   memcpy(buffer_, data, size);
   buffer_ += size;
   buffer_size_ -= size;
+  offset_ += size;
 }
 
 }  // namespace io
diff --git a/src/google/protobuf/io/printer.h b/src/google/protobuf/io/printer.h
index f1490bb..2ba8455 100644
--- a/src/google/protobuf/io/printer.h
+++ b/src/google/protobuf/io/printer.h
@@ -39,6 +39,7 @@
 
 #include <string>
 #include <map>
+#include <vector>
 #include <google/protobuf/stubs/common.h>
 
 namespace google {
@@ -47,6 +48,47 @@
 
 class ZeroCopyOutputStream;     // zero_copy_stream.h
 
+// Records annotations about a Printer's output.
+class LIBPROTOBUF_EXPORT AnnotationCollector {
+ public:
+  // Records that the bytes in file_path beginning with begin_offset and ending
+  // before end_offset are associated with the SourceCodeInfo-style path.
+  virtual void AddAnnotation(size_t begin_offset, size_t end_offset,
+                             const string& file_path,
+                             const vector<int>& path) = 0;
+
+  virtual ~AnnotationCollector() {}
+};
+
+// Records annotations about a Printer's output to the given protocol buffer,
+// assuming that the buffer has an ::Annotation message exposing path,
+// source_file, begin and end fields.
+template <typename AnnotationProto>
+class AnnotationProtoCollector : public AnnotationCollector {
+ public:
+  // annotation_proto is the protocol buffer to which new Annotations should be
+  // added. It is not owned by the AnnotationProtoCollector.
+  explicit AnnotationProtoCollector(AnnotationProto* annotation_proto)
+      : annotation_proto_(annotation_proto) {}
+
+  // Override for AnnotationCollector::AddAnnotation.
+  virtual void AddAnnotation(size_t begin_offset, size_t end_offset,
+                             const string& file_path, const vector<int>& path) {
+    typename AnnotationProto::Annotation* annotation =
+        annotation_proto_->add_annotation();
+    for (int i = 0; i < path.size(); ++i) {
+      annotation->add_path(path[i]);
+    }
+    annotation->set_source_file(file_path);
+    annotation->set_begin(begin_offset);
+    annotation->set_end(end_offset);
+  }
+
+ private:
+  // The protocol buffer to which new annotations should be added.
+  AnnotationProto* const annotation_proto_;
+};
+
 // This simple utility class assists in code generation.  It basically
 // allows the caller to define a set of variables and then output some
 // text with variable substitutions.  Example usage:
@@ -61,13 +103,103 @@
 // Printer aggressively enforces correct usage, crashing (with assert failures)
 // in the case of undefined variables in debug builds. This helps greatly in
 // debugging code which uses it.
+//
+// If a Printer is constructed with an AnnotationCollector, it will provide it
+// with annotations that connect the Printer's output to paths that can identify
+// various descriptors.  In the above example, if person_ is a descriptor that
+// identifies Bob, we can associate the output string "My name is Bob." with
+// a source path pointing to that descriptor with:
+//
+//   printer.Annotate("name", person_);
+//
+// The AnnotationCollector will be sent an annotation linking the output range
+// covering "Bob" to the logical path provided by person_.  Tools may use
+// this association to (for example) link "Bob" in the output back to the
+// source file that defined the person_ descriptor identifying Bob.
+//
+// Annotate can only examine variables substituted during the last call to
+// Print.  It is invalid to refer to a variable that was used multiple times
+// in a single Print call.
+//
+// In full generality, one may specify a range of output text using a beginning
+// substitution variable and an ending variable.  The resulting annotation will
+// span from the first character of the substituted value for the beginning
+// variable to the last character of the substituted value for the ending
+// variable.  For example, the Annotate call above is equivalent to this one:
+//
+//   printer.Annotate("name", "name", person_);
+//
+// This is useful if multiple variables combine to form a single span of output
+// that should be annotated with the same source path.  For example:
+//
+//   Printer printer(output, '$');
+//   map<string, string> vars;
+//   vars["first"] = "Alice";
+//   vars["last"] = "Smith";
+//   printer.Print(vars, "My name is $first$ $last$.");
+//   printer.Annotate("first", "last", person_);
+//
+// This code would associate the span covering "Alice Smith" in the output with
+// the person_ descriptor.
+//
+// Note that the beginning variable must come before (or overlap with, in the
+// case of zero-sized substitution values) the ending variable.
+//
+// It is also sometimes useful to use variables with zero-sized values as
+// markers.  This avoids issues with multiple references to the same variable
+// and also allows annotation ranges to span literal text from the Print
+// templates:
+//
+//   Printer printer(output, '$');
+//   map<string, string> vars;
+//   vars["foo"] = "bar";
+//   vars["function"] = "call";
+//   vars["mark"] = "";
+//   printer.Print(vars, "$function$($foo$,$foo$)$mark$");
+//   printer.Annotate("function", "rmark", call_);
+//
+// This code associates the span covering "call(bar,bar)" in the output with the
+// call_ descriptor.
+
 class LIBPROTOBUF_EXPORT Printer {
  public:
   // Create a printer that writes text to the given output stream.  Use the
   // given character as the delimiter for variables.
   Printer(ZeroCopyOutputStream* output, char variable_delimiter);
+
+  // Create a printer that writes text to the given output stream.  Use the
+  // given character as the delimiter for variables.  If annotation_collector
+  // is not null, Printer will provide it with annotations about code written
+  // to the stream.  annotation_collector is not owned by Printer.
+  Printer(ZeroCopyOutputStream* output, char variable_delimiter,
+          AnnotationCollector* annotation_collector);
+
   ~Printer();
 
+  // Link a subsitution variable emitted by the last call to Print to the object
+  // described by descriptor.
+  template <typename SomeDescriptor>
+  void Annotate(const char* varname, const SomeDescriptor* descriptor) {
+    Annotate(varname, varname, descriptor);
+  }
+
+  // Link the output range defined by the substitution variables as emitted by
+  // the last call to Print to the object described by descriptor. The range
+  // begins at begin_varname's value and ends after the last character of the
+  // value substituted for end_varname.
+  template <typename SomeDescriptor>
+  void Annotate(const char* begin_varname, const char* end_varname,
+                const SomeDescriptor* descriptor) {
+    if (annotation_collector_ == NULL) {
+      // Annotations aren't turned on for this Printer, so don't pay the cost
+      // of building the location path.
+      return;
+    }
+    vector<int> path;
+    descriptor->GetLocationPath(&path);
+    Annotate(begin_varname, end_varname, descriptor->file()->name(), path);
+  }
+
   // Print some text after applying variable substitutions.  If a particular
   // variable in the text is not defined, this will crash.  Variables to be
   // substituted are identified by their names surrounded by delimiter
@@ -149,16 +281,48 @@
   bool failed() const { return failed_; }
 
  private:
+  // Link the output range defined by the substitution variables as emitted by
+  // the last call to Print to the object found at the SourceCodeInfo-style path
+  // in a file with path file_path. The range begins at the start of
+  // begin_varname's value and ends after the last character of the value
+  // substituted for end_varname. Note that begin_varname and end_varname
+  // may refer to the same variable.
+  void Annotate(const char* begin_varname, const char* end_varname,
+                const string& file_path, const vector<int>& path);
+
   const char variable_delimiter_;
 
   ZeroCopyOutputStream* const output_;
   char* buffer_;
   int buffer_size_;
+  // The current position, in bytes, in the output stream.  This is equivalent
+  // to the total number of bytes that have been written so far.  This value is
+  // used to calculate annotation ranges in the substitutions_ map below.
+  size_t offset_;
 
   string indent_;
   bool at_start_of_line_;
   bool failed_;
 
+  // A map from variable name to [start, end) offsets in the output buffer.
+  // These refer to the offsets used for a variable after the last call to
+  // Print.  If a variable was used more than once, the entry used in
+  // this map is set to a negative-length span.  For singly-used variables, the
+  // start offset is the beginning of the substitution; the end offset is the
+  // last byte of the substitution plus one (such that (end - start) is the
+  // length of the substituted string).
+  map<string, pair<size_t, size_t> > substitutions_;
+
+  // Returns true and sets range to the substitution range in the output for
+  // varname if varname was used once in the last call to Print. If varname
+  // was not used, or if it was used multiple times, returns false (and
+  // fails a debug assertion).
+  bool GetSubstitutionRange(const char* varname, pair<size_t, size_t>* range);
+
+  // If non-null, annotation_collector_ is used to store annotations about
+  // generated code.
+  AnnotationCollector* const annotation_collector_;
+
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Printer);
 };
 
diff --git a/src/google/protobuf/io/printer_unittest.cc b/src/google/protobuf/io/printer_unittest.cc
index 258dd98..95f3afa 100644
--- a/src/google/protobuf/io/printer_unittest.cc
+++ b/src/google/protobuf/io/printer_unittest.cc
@@ -36,6 +36,7 @@
 
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/descriptor.pb.h>
 
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
@@ -169,6 +170,196 @@
                buffer);
 }
 
+// MockDescriptorFile defines only those members that Printer uses to write out
+// annotations.
+class MockDescriptorFile {
+ public:
+  explicit MockDescriptorFile(const string& file) : file_(file) {}
+
+  // The mock filename for this file.
+  const string& name() const { return file_; }
+
+ private:
+  string file_;
+};
+
+// MockDescriptor defines only those members that Printer uses to write out
+// annotations.
+class MockDescriptor {
+ public:
+  MockDescriptor(const string& file, const vector<int>& path)
+      : file_(file), path_(path) {}
+
+  // The mock file in which this descriptor was defined.
+  const MockDescriptorFile* file() const { return &file_; }
+
+ private:
+  // Allows access to GetLocationPath.
+  friend class ::google::protobuf::io::Printer;
+
+  // Copies the pre-stored path to output.
+  void GetLocationPath(std::vector<int>* output) const { *output = path_; }
+
+  MockDescriptorFile file_;
+  vector<int> path_;
+};
+
+TEST(Printer, AnnotateMap) {
+  char buffer[8192];
+  ArrayOutputStream output(buffer, sizeof(buffer));
+  GeneratedCodeInfo info;
+  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
+  {
+    Printer printer(&output, '$', &info_collector);
+    map<string, string> vars;
+    vars["foo"] = "3";
+    vars["bar"] = "5";
+    printer.Print(vars, "012$foo$4$bar$\n");
+    vector<int> path_1;
+    path_1.push_back(33);
+    vector<int> path_2;
+    path_2.push_back(11);
+    path_2.push_back(22);
+    MockDescriptor descriptor_1("path_1", path_1);
+    MockDescriptor descriptor_2("path_2", path_2);
+    printer.Annotate("foo", "foo", &descriptor_1);
+    printer.Annotate("bar", "bar", &descriptor_2);
+  }
+  buffer[output.ByteCount()] = '\0';
+  EXPECT_STREQ("012345\n", buffer);
+  ASSERT_EQ(2, info.annotation_size());
+  const GeneratedCodeInfo::Annotation* foo = info.annotation(0).path_size() == 1
+                                                 ? &info.annotation(0)
+                                                 : &info.annotation(1);
+  const GeneratedCodeInfo::Annotation* bar = info.annotation(0).path_size() == 1
+                                                 ? &info.annotation(1)
+                                                 : &info.annotation(0);
+  ASSERT_EQ(1, foo->path_size());
+  ASSERT_EQ(2, bar->path_size());
+  EXPECT_EQ(33, foo->path(0));
+  EXPECT_EQ(11, bar->path(0));
+  EXPECT_EQ(22, bar->path(1));
+  EXPECT_EQ("path_1", foo->source_file());
+  EXPECT_EQ("path_2", bar->source_file());
+  EXPECT_EQ(3, foo->begin());
+  EXPECT_EQ(4, foo->end());
+  EXPECT_EQ(5, bar->begin());
+  EXPECT_EQ(6, bar->end());
+}
+
+TEST(Printer, AnnotateInline) {
+  char buffer[8192];
+  ArrayOutputStream output(buffer, sizeof(buffer));
+  GeneratedCodeInfo info;
+  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
+  {
+    Printer printer(&output, '$', &info_collector);
+    printer.Print("012$foo$4$bar$\n", "foo", "3", "bar", "5");
+    vector<int> path_1;
+    path_1.push_back(33);
+    vector<int> path_2;
+    path_2.push_back(11);
+    path_2.push_back(22);
+    MockDescriptor descriptor_1("path_1", path_1);
+    MockDescriptor descriptor_2("path_2", path_2);
+    printer.Annotate("foo", "foo", &descriptor_1);
+    printer.Annotate("bar", "bar", &descriptor_2);
+  }
+  buffer[output.ByteCount()] = '\0';
+  EXPECT_STREQ("012345\n", buffer);
+  ASSERT_EQ(2, info.annotation_size());
+  const GeneratedCodeInfo::Annotation* foo = info.annotation(0).path_size() == 1
+                                                 ? &info.annotation(0)
+                                                 : &info.annotation(1);
+  const GeneratedCodeInfo::Annotation* bar = info.annotation(0).path_size() == 1
+                                                 ? &info.annotation(1)
+                                                 : &info.annotation(0);
+  ASSERT_EQ(1, foo->path_size());
+  ASSERT_EQ(2, bar->path_size());
+  EXPECT_EQ(33, foo->path(0));
+  EXPECT_EQ(11, bar->path(0));
+  EXPECT_EQ(22, bar->path(1));
+  EXPECT_EQ("path_1", foo->source_file());
+  EXPECT_EQ("path_2", bar->source_file());
+  EXPECT_EQ(3, foo->begin());
+  EXPECT_EQ(4, foo->end());
+  EXPECT_EQ(5, bar->begin());
+  EXPECT_EQ(6, bar->end());
+}
+
+TEST(Printer, AnnotateRange) {
+  char buffer[8192];
+  ArrayOutputStream output(buffer, sizeof(buffer));
+  GeneratedCodeInfo info;
+  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
+  {
+    Printer printer(&output, '$', &info_collector);
+    printer.Print("012$foo$4$bar$\n", "foo", "3", "bar", "5");
+    vector<int> path;
+    path.push_back(33);
+    MockDescriptor descriptor("path", path);
+    printer.Annotate("foo", "bar", &descriptor);
+  }
+  buffer[output.ByteCount()] = '\0';
+  EXPECT_STREQ("012345\n", buffer);
+  ASSERT_EQ(1, info.annotation_size());
+  const GeneratedCodeInfo::Annotation* foobar = &info.annotation(0);
+  ASSERT_EQ(1, foobar->path_size());
+  EXPECT_EQ(33, foobar->path(0));
+  EXPECT_EQ("path", foobar->source_file());
+  EXPECT_EQ(3, foobar->begin());
+  EXPECT_EQ(6, foobar->end());
+}
+
+TEST(Printer, AnnotateEmptyRange) {
+  char buffer[8192];
+  ArrayOutputStream output(buffer, sizeof(buffer));
+  GeneratedCodeInfo info;
+  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
+  {
+    Printer printer(&output, '$', &info_collector);
+    printer.Print("012$foo$4$baz$$bam$$bar$\n", "foo", "3", "bar", "5", "baz",
+                  "", "bam", "");
+    vector<int> path;
+    path.push_back(33);
+    MockDescriptor descriptor("path", path);
+    printer.Annotate("baz", "bam", &descriptor);
+  }
+  buffer[output.ByteCount()] = '\0';
+  EXPECT_STREQ("012345\n", buffer);
+  ASSERT_EQ(1, info.annotation_size());
+  const GeneratedCodeInfo::Annotation* bazbam = &info.annotation(0);
+  ASSERT_EQ(1, bazbam->path_size());
+  EXPECT_EQ(33, bazbam->path(0));
+  EXPECT_EQ("path", bazbam->source_file());
+  EXPECT_EQ(5, bazbam->begin());
+  EXPECT_EQ(5, bazbam->end());
+}
+
+TEST(Printer, AnnotateDespiteUnrelatedMultipleUses) {
+  char buffer[8192];
+  ArrayOutputStream output(buffer, sizeof(buffer));
+  GeneratedCodeInfo info;
+  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
+  {
+    Printer printer(&output, '$', &info_collector);
+    printer.Print("012$foo$4$foo$$bar$\n", "foo", "3", "bar", "5");
+    vector<int> path;
+    path.push_back(33);
+    MockDescriptor descriptor("path", path);
+    printer.Annotate("bar", "bar", &descriptor);
+  }
+  buffer[output.ByteCount()] = '\0';
+  EXPECT_STREQ("0123435\n", buffer);
+  ASSERT_EQ(1, info.annotation_size());
+  const GeneratedCodeInfo::Annotation* bar = &info.annotation(0);
+  ASSERT_EQ(1, bar->path_size());
+  EXPECT_EQ(33, bar->path(0));
+  EXPECT_EQ("path", bar->source_file());
+  EXPECT_EQ(6, bar->begin());
+  EXPECT_EQ(7, bar->end());
+}
+
 TEST(Printer, Indenting) {
   char buffer[8192];
 
@@ -232,6 +423,52 @@
   EXPECT_DEBUG_DEATH(printer.Print("$unclosed"), "Unclosed variable name");
   EXPECT_DEBUG_DEATH(printer.Outdent(), "without matching Indent");
 }
+
+TEST(Printer, AnnotateMultipleUsesDeath) {
+  char buffer[8192];
+  ArrayOutputStream output(buffer, sizeof(buffer));
+  GeneratedCodeInfo info;
+  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
+  {
+    Printer printer(&output, '$', &info_collector);
+    printer.Print("012$foo$4$foo$\n", "foo", "3");
+    vector<int> path;
+    path.push_back(33);
+    MockDescriptor descriptor("path", path);
+    EXPECT_DEBUG_DEATH(printer.Annotate("foo", "foo", &descriptor), "multiple");
+  }
+}
+
+TEST(Printer, AnnotateNegativeLengthDeath) {
+  char buffer[8192];
+  ArrayOutputStream output(buffer, sizeof(buffer));
+  GeneratedCodeInfo info;
+  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
+  {
+    Printer printer(&output, '$', &info_collector);
+    printer.Print("012$foo$4$bar$\n", "foo", "3", "bar", "5");
+    vector<int> path;
+    path.push_back(33);
+    MockDescriptor descriptor("path", path);
+    EXPECT_DEBUG_DEATH(printer.Annotate("bar", "foo", &descriptor), "negative");
+  }
+}
+
+TEST(Printer, AnnotateUndefinedDeath) {
+  char buffer[8192];
+  ArrayOutputStream output(buffer, sizeof(buffer));
+  GeneratedCodeInfo info;
+  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
+  {
+    Printer printer(&output, '$', &info_collector);
+    printer.Print("012$foo$4$foo$\n", "foo", "3");
+    vector<int> path;
+    path.push_back(33);
+    MockDescriptor descriptor("path", path);
+    EXPECT_DEBUG_DEATH(printer.Annotate("bar", "bar", &descriptor),
+                       "Undefined");
+  }
+}
 #endif  // PROTOBUF_HAS_DEATH_TEST
 
 TEST(Printer, WriteFailurePartial) {
diff --git a/src/google/protobuf/io/tokenizer.cc b/src/google/protobuf/io/tokenizer.cc
index 3d57707..b3550df 100644
--- a/src/google/protobuf/io/tokenizer.cc
+++ b/src/google/protobuf/io/tokenizer.cc
@@ -881,9 +881,11 @@
   uint64 result = 0;
   for (; *ptr != '\0'; ptr++) {
     int digit = DigitValue(*ptr);
-    GOOGLE_LOG_IF(DFATAL, digit < 0 || digit >= base)
-      << " Tokenizer::ParseInteger() passed text that could not have been"
-         " tokenized as an integer: " << CEscape(text);
+    if (digit < 0 || digit >= base) {
+      // The token provided by Tokenizer is invalid. i.e., 099 is an invalid
+      // token, but Tokenizer still think it's integer.
+      return false;
+    }
     if (digit > max_value || result > (max_value - digit) / base) {
       // Overflow.
       return false;
diff --git a/src/google/protobuf/io/tokenizer.h b/src/google/protobuf/io/tokenizer.h
index 49885ed..64ee7d8 100644
--- a/src/google/protobuf/io/tokenizer.h
+++ b/src/google/protobuf/io/tokenizer.h
@@ -52,6 +52,12 @@
 class ErrorCollector;
 class Tokenizer;
 
+// By "column number", the proto compiler refers to a count of the number
+// of bytes before a given byte, except that a tab character advances to
+// the next multiple of 8 bytes.  Note in particular that column numbers
+// are zero-based, while many user interfaces use one-based column numbers.
+typedef int ColumnNumber;
+
 // Abstract interface for an object which collects the errors that occur
 // during parsing.  A typical implementation might simply print the errors
 // to stdout.
@@ -63,13 +69,14 @@
   // Indicates that there was an error in the input at the given line and
   // column numbers.  The numbers are zero-based, so you may want to add
   // 1 to each before printing them.
-  virtual void AddError(int line, int column, const string& message) = 0;
+  virtual void AddError(int line, ColumnNumber column,
+                        const string& message) = 0;
 
   // Indicates that there was a warning in the input at the given line and
   // column numbers.  The numbers are zero-based, so you may want to add
   // 1 to each before printing them.
-  virtual void AddWarning(int /* line */, int /* column */,
-                          const string& /* message */) { }
+  virtual void AddWarning(int line, ColumnNumber column,
+                          const string& message) { }
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ErrorCollector);
@@ -124,8 +131,8 @@
     // "line" and "column" specify the position of the first character of
     // the token within the input stream.  They are zero-based.
     int line;
-    int column;
-    int end_column;
+    ColumnNumber column;
+    ColumnNumber end_column;
   };
 
   // Get the current token.  This is updated when Next() is called.  Before
@@ -263,7 +270,7 @@
 
   // Line and column number of current_char_ within the whole input stream.
   int line_;
-  int column_;
+  ColumnNumber column_;
 
   // String to which text should be appended as we advance through it.
   // Call RecordTo(&str) to start recording and StopRecording() to stop.
@@ -280,6 +287,7 @@
 
   // Since we count columns we need to interpret tabs somehow.  We'll take
   // the standard 8-character definition for lack of any way to do better.
+  // This must match the documentation of ColumnNumber.
   static const int kTabWidth = 8;
 
   // -----------------------------------------------------------------
diff --git a/src/google/protobuf/io/tokenizer_unittest.cc b/src/google/protobuf/io/tokenizer_unittest.cc
index 20d50a2..ae0811f 100644
--- a/src/google/protobuf/io/tokenizer_unittest.cc
+++ b/src/google/protobuf/io/tokenizer_unittest.cc
@@ -736,19 +736,13 @@
   EXPECT_EQ(0, ParseInteger("0x"));
 
   uint64 i;
-#ifdef PROTOBUF_HAS_DEATH_TEST  // death tests do not work on Windows yet
+
   // Test invalid integers that will never be tokenized as integers.
-  EXPECT_DEBUG_DEATH(Tokenizer::ParseInteger("zxy", kuint64max, &i),
-    "passed text that could not have been tokenized as an integer");
-  EXPECT_DEBUG_DEATH(Tokenizer::ParseInteger("1.2", kuint64max, &i),
-    "passed text that could not have been tokenized as an integer");
-  EXPECT_DEBUG_DEATH(Tokenizer::ParseInteger("08", kuint64max, &i),
-    "passed text that could not have been tokenized as an integer");
-  EXPECT_DEBUG_DEATH(Tokenizer::ParseInteger("0xg", kuint64max, &i),
-    "passed text that could not have been tokenized as an integer");
-  EXPECT_DEBUG_DEATH(Tokenizer::ParseInteger("-1", kuint64max, &i),
-    "passed text that could not have been tokenized as an integer");
-#endif  // PROTOBUF_HAS_DEATH_TEST
+  EXPECT_FALSE(Tokenizer::ParseInteger("zxy", kuint64max, &i));
+  EXPECT_FALSE(Tokenizer::ParseInteger("1.2", kuint64max, &i));
+  EXPECT_FALSE(Tokenizer::ParseInteger("08", kuint64max, &i));
+  EXPECT_FALSE(Tokenizer::ParseInteger("0xg", kuint64max, &i));
+  EXPECT_FALSE(Tokenizer::ParseInteger("-1", kuint64max, &i));
 
   // Test overflows.
   EXPECT_TRUE (Tokenizer::ParseInteger("0", 0, &i));
diff --git a/src/google/protobuf/io/zero_copy_stream_impl_lite.cc b/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
index 083beca..e6ca88c 100644
--- a/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
+++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
@@ -69,7 +69,7 @@
 
 bool ArrayInputStream::Next(const void** data, int* size) {
   if (position_ < size_) {
-    last_returned_size_ = min(block_size_, size_ - position_);
+    last_returned_size_ = std::min(block_size_, size_ - position_);
     *data = data_ + position_;
     *size = last_returned_size_;
     position_ += last_returned_size_;
@@ -122,7 +122,7 @@
 
 bool ArrayOutputStream::Next(void** data, int* size) {
   if (position_ < size_) {
-    last_returned_size_ = min(block_size_, size_ - position_);
+    last_returned_size_ = std::min(block_size_, size_ - position_);
     *data = data_ + position_;
     *size = last_returned_size_;
     position_ += last_returned_size_;
@@ -157,7 +157,7 @@
 }
 
 bool StringOutputStream::Next(void** data, int* size) {
-  GOOGLE_CHECK_NE(NULL, target_);
+  GOOGLE_CHECK(target_ != NULL);
   int old_size = target_->size();
 
   // Grow the string.
@@ -177,9 +177,9 @@
     // Double the size, also make sure that the new size is at least
     // kMinimumSize.
     STLStringResizeUninitialized(
-      target_,
-      max(old_size * 2,
-          kMinimumSize + 0));  // "+ 0" works around GCC4 weirdness.
+        target_,
+        std::max(old_size * 2,
+                 kMinimumSize + 0));  // "+ 0" works around GCC4 weirdness.
   }
 
   *data = mutable_string_data(target_) + old_size;
@@ -189,13 +189,13 @@
 
 void StringOutputStream::BackUp(int count) {
   GOOGLE_CHECK_GE(count, 0);
-  GOOGLE_CHECK_NE(NULL, target_);
+  GOOGLE_CHECK(target_ != NULL);
   GOOGLE_CHECK_LE(count, target_->size());
   target_->resize(target_->size() - count);
 }
 
 int64 StringOutputStream::ByteCount() const {
-  GOOGLE_CHECK_NE(NULL, target_);
+  GOOGLE_CHECK(target_ != NULL);
   return target_->size();
 }
 
@@ -235,8 +235,8 @@
   char junk[4096];
   int skipped = 0;
   while (skipped < count) {
-    int bytes = Read(junk, min(count - skipped,
-                               implicit_cast<int>(sizeof(junk))));
+    int bytes =
+        Read(junk, std::min(count - skipped, implicit_cast<int>(sizeof(junk))));
     if (bytes <= 0) {
       // EOF or read error.
       return skipped;
diff --git a/src/google/protobuf/io/zero_copy_stream_impl_lite.h b/src/google/protobuf/io/zero_copy_stream_impl_lite.h
index 1c397de..cc7430e 100644
--- a/src/google/protobuf/io/zero_copy_stream_impl_lite.h
+++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.h
@@ -51,6 +51,7 @@
 #include <string>
 #include <iosfwd>
 #include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/callback.h>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/scoped_ptr.h>
 #include <google/protobuf/stubs/stl_util.h>
diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h
index dfc6242..a182abe 100644
--- a/src/google/protobuf/map.h
+++ b/src/google/protobuf/map.h
@@ -31,9 +31,11 @@
 #ifndef GOOGLE_PROTOBUF_MAP_H__
 #define GOOGLE_PROTOBUF_MAP_H__
 
-#include <iterator>
 #include <google/protobuf/stubs/hash.h>
+#include <iterator>
 #include <limits>  // To support Visual Studio 2008
+#include <set>
+#include <utility>
 
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/arena.h>
@@ -41,17 +43,23 @@
 #include <google/protobuf/map_type_handler.h>
 #include <google/protobuf/message.h>
 #include <google/protobuf/descriptor.h>
+#if __cpp_exceptions && LANG_CXX11
+#include <random>
+#endif
 
 namespace google {
 namespace protobuf {
 
+// The Map and MapIterator types are provided by this header file.
+// Please avoid using other types defined here, unless they are public
+// types within Map or MapIterator, such as Map::value_type.
 template <typename Key, typename T>
 class Map;
 
-template <typename Enum> struct is_proto_enum;
-
 class MapIterator;
 
+template <typename Enum> struct is_proto_enum;
+
 namespace internal {
 template <typename Key, typename T,
           WireFormatLite::FieldType key_wire_type,
@@ -73,15 +81,15 @@
 class GeneratedMessageReflection;
 }  // namespace internal
 
-#define TYPE_CHECK(EXPECTEDTYPE, METHOD)                                \
-  if (type() != EXPECTEDTYPE) {                                         \
-    GOOGLE_LOG(FATAL)                                                          \
-        << "Protocol Buffer map usage error:\n"                         \
-        << METHOD << " type does not match\n"                           \
-        << "  Expected : "                                              \
-        << FieldDescriptor::CppTypeName(EXPECTEDTYPE) << "\n"           \
-        << "  Actual   : "                                              \
-        << FieldDescriptor::CppTypeName(type());                        \
+#define TYPE_CHECK(EXPECTEDTYPE, METHOD)                        \
+  if (type() != EXPECTEDTYPE) {                                 \
+    GOOGLE_LOG(FATAL)                                                  \
+        << "Protocol Buffer map usage error:\n"                 \
+        << METHOD << " type does not match\n"                   \
+        << "  Expected : "                                      \
+        << FieldDescriptor::CppTypeName(EXPECTEDTYPE) << "\n"   \
+        << "  Actual   : "                                      \
+        << FieldDescriptor::CppTypeName(type());                \
   }
 
 // MapKey is an union type for representing any possible
@@ -166,11 +174,47 @@
     return *val_.string_value_;
   }
 
-  bool operator==(const MapKey& other) const {
+  bool operator<(const MapKey& other) const {
     if (type_ != other.type_) {
-      return false;
+      // We could define a total order that handles this case, but
+      // there currently no need.  So, for now, fail.
+      GOOGLE_LOG(FATAL) << "Unsupported: type mismatch";
     }
     switch (type()) {
+      case FieldDescriptor::CPPTYPE_DOUBLE:
+      case FieldDescriptor::CPPTYPE_FLOAT:
+      case FieldDescriptor::CPPTYPE_ENUM:
+      case FieldDescriptor::CPPTYPE_MESSAGE:
+        GOOGLE_LOG(FATAL) << "Unsupported";
+        return false;
+      case FieldDescriptor::CPPTYPE_STRING:
+        return *val_.string_value_ < *other.val_.string_value_;
+      case FieldDescriptor::CPPTYPE_INT64:
+        return val_.int64_value_ < other.val_.int64_value_;
+      case FieldDescriptor::CPPTYPE_INT32:
+        return val_.int32_value_ < other.val_.int32_value_;
+      case FieldDescriptor::CPPTYPE_UINT64:
+        return val_.uint64_value_ < other.val_.uint64_value_;
+      case FieldDescriptor::CPPTYPE_UINT32:
+        return val_.uint32_value_ < other.val_.uint32_value_;
+      case FieldDescriptor::CPPTYPE_BOOL:
+        return val_.bool_value_ < other.val_.bool_value_;
+    }
+    return false;
+  }
+
+  bool operator==(const MapKey& other) const {
+    if (type_ != other.type_) {
+      // To be consistent with operator<, we don't allow this either.
+      GOOGLE_LOG(FATAL) << "Unsupported: type mismatch";
+    }
+    switch (type()) {
+      case FieldDescriptor::CPPTYPE_DOUBLE:
+      case FieldDescriptor::CPPTYPE_FLOAT:
+      case FieldDescriptor::CPPTYPE_ENUM:
+      case FieldDescriptor::CPPTYPE_MESSAGE:
+        GOOGLE_LOG(FATAL) << "Unsupported";
+        break;
       case FieldDescriptor::CPPTYPE_STRING:
         return *val_.string_value_ == *other.val_.string_value_;
       case FieldDescriptor::CPPTYPE_INT64:
@@ -183,11 +227,6 @@
         return val_.uint32_value_ == other.val_.uint32_value_;
       case FieldDescriptor::CPPTYPE_BOOL:
         return val_.bool_value_ == other.val_.bool_value_;
-      case FieldDescriptor::CPPTYPE_DOUBLE:
-      case FieldDescriptor::CPPTYPE_FLOAT:
-      case FieldDescriptor::CPPTYPE_ENUM:
-      case FieldDescriptor::CPPTYPE_MESSAGE:
-        GOOGLE_LOG(FATAL) << "Can't get here.";
     }
     GOOGLE_LOG(FATAL) << "Can't get here.";
     return false;
@@ -196,6 +235,12 @@
   void CopyFrom(const MapKey& other) {
     SetType(other.type());
     switch (type_) {
+      case FieldDescriptor::CPPTYPE_DOUBLE:
+      case FieldDescriptor::CPPTYPE_FLOAT:
+      case FieldDescriptor::CPPTYPE_ENUM:
+      case FieldDescriptor::CPPTYPE_MESSAGE:
+        GOOGLE_LOG(FATAL) << "Unsupported";
+        break;
       case FieldDescriptor::CPPTYPE_STRING:
         *val_.string_value_ = *other.val_.string_value_;
         break;
@@ -214,12 +259,6 @@
       case FieldDescriptor::CPPTYPE_BOOL:
         val_.bool_value_ = other.val_.bool_value_;
         break;
-      case FieldDescriptor::CPPTYPE_DOUBLE:
-      case FieldDescriptor::CPPTYPE_FLOAT:
-      case FieldDescriptor::CPPTYPE_ENUM:
-      case FieldDescriptor::CPPTYPE_MESSAGE:
-        GOOGLE_LOG(FATAL) << "Can't get here.";
-        break;
     }
   }
 
@@ -457,8 +496,17 @@
 };
 
 // google::protobuf::Map is an associative container type used to store protobuf map
-// fields. Its interface is similar to std::unordered_map. Users should use this
-// interface directly to visit or change map fields.
+// fields.  Each Map instance may or may not use a different hash function, a
+// different iteration order, and so on.  E.g., please don't examine
+// implementation details to decide if the following would work:
+//  Map<int, int> m0, m1;
+//  m0[0] = m1[0] = m0[1] = m1[1] = 0;
+//  assert(m0.begin()->first == m1.begin()->first);  // Bug!
+//
+// Map's interface is similar to std::unordered_map, except that Map is not
+// designed to play well with exceptions.  Mutations to a Map do not invalidate
+// a Map's iterators, pointers to elements, or references to elements.  Except
+// for erase(iterator), any non-const method can reorder iterators.
 template <typename Key, typename T>
 class Map {
  public:
@@ -473,40 +521,56 @@
 
   typedef size_t size_type;
   typedef hash<Key> hasher;
-  typedef equal_to<Key> key_equal;
 
-  Map()
+  Map(bool old_style = true)
       : arena_(NULL),
-        allocator_(arena_),
-        elements_(0, hasher(), key_equal(), allocator_),
-        default_enum_value_(0) {}
-  explicit Map(Arena* arena)
-      : arena_(arena),
-        allocator_(arena_),
-        elements_(0, hasher(), key_equal(), allocator_),
-        default_enum_value_(0) {
-    arena_->OwnDestructor(&elements_);
+        default_enum_value_(0),
+        old_style_(old_style) {
+    Init();
   }
-
+  explicit Map(Arena* arena, bool old_style = true)
+      : arena_(arena),
+        default_enum_value_(0),
+        old_style_(old_style) {
+    Init();
+  }
   Map(const Map& other)
       : arena_(NULL),
-        allocator_(arena_),
-        elements_(0, hasher(), key_equal(), allocator_),
-        default_enum_value_(other.default_enum_value_) {
+        default_enum_value_(other.default_enum_value_),
+        old_style_(other.old_style_) {
+    Init();
     insert(other.begin(), other.end());
   }
   template <class InputIt>
-  Map(const InputIt& first, const InputIt& last)
+  Map(const InputIt& first, const InputIt& last, bool old_style = true)
       : arena_(NULL),
-        allocator_(arena_),
-        elements_(0, hasher(), key_equal(), allocator_),
-        default_enum_value_(0) {
+        default_enum_value_(0),
+        old_style_(old_style) {
+    Init();
     insert(first, last);
   }
 
-  ~Map() { clear(); }
+  ~Map() {
+    clear();
+    if (arena_ == NULL) {
+      if (old_style_)
+        delete deprecated_elements_;
+      else
+        delete elements_;
+    }
+  }
 
  private:
+  void Init() {
+    if (old_style_)
+      deprecated_elements_ = Arena::Create<DeprecatedInnerMap>(
+          arena_, 0, hasher(), equal_to<Key>(),
+          MapAllocator<std::pair<const Key, MapPair<Key, T>*> >(arena_));
+    else
+      elements_ =
+          Arena::Create<InnerMap>(arena_, 0, hasher(), Allocator(arena_));
+  }
+
   // re-implement std::allocator to use arena allocator for memory allocation.
   // Used for google::protobuf::Map implementation. Users should not use this class
   // directly.
@@ -544,8 +608,8 @@
       }
     }
 
-#if __cplusplus >= 201103L && !defined(GOOGLE_PROTOBUF_OS_APPLE) && \
-    !defined(GOOGLE_PROTOBUF_OS_NACL) && !defined(GOOGLE_PROTOBUF_OS_ANDROID)
+#if __cplusplus >= 201103L && !defined(GOOGLE_PROTOBUF_OS_APPLE) &&     \
+  !defined(GOOGLE_PROTOBUF_OS_NACL) && !defined(GOOGLE_PROTOBUF_OS_ANDROID)
     template<class NodeType, class... Args>
     void construct(NodeType* p, Args&&... args) {
       new (static_cast<void*>(p)) NodeType(std::forward<Args>(args)...);
@@ -589,86 +653,837 @@
     friend class MapAllocator;
   };
 
-  typedef MapAllocator<std::pair<const Key, MapPair<Key, T>*> > Allocator;
-  typedef hash_map<Key, value_type*, hash<Key>, equal_to<Key>, Allocator>
-      InnerMap;
+  // InnerMap's key type is Key and its value type is value_type*.  We use a
+  // custom class here and for Node, below, to ensure that k_ is at offset 0,
+  // allowing safe conversion from pointer to Node to pointer to Key, and vice
+  // versa when appropriate.
+  class LIBPROTOBUF_EXPORT KeyValuePair {
+   public:
+    KeyValuePair(const Key& k, value_type* v) : k_(k), v_(v) {}
+
+    const Key& key() const { return k_; }
+    Key& key() { return k_; }
+    value_type* const value() const { return v_; }
+    value_type*& value() { return v_; }
+
+   private:
+    Key k_;
+    value_type* v_;
+  };
+
+  typedef MapAllocator<KeyValuePair> Allocator;
+
+  // InnerMap is a generic hash-based map.  It doesn't contain any
+  // protocol-buffer-specific logic.  It is a chaining hash map with the
+  // additional feature that some buckets can be converted to use an ordered
+  // container.  This ensures O(lg n) bounds on find, insert, and erase, while
+  // avoiding the overheads of ordered containers most of the time.
+  //
+  // The implementation doesn't need the full generality of unordered_map,
+  // and it doesn't have it.  More bells and whistles can be added as needed.
+  // Some implementation details:
+  // 1. The hash function has type hasher and the equality function
+  //    equal_to<Key>.  We inherit from hasher to save space
+  //    (empty-base-class optimization).
+  // 2. The number of buckets is a power of two.
+  // 3. Buckets are converted to trees in pairs: if we convert bucket b then
+  //    buckets b and b^1 will share a tree.  Invariant: buckets b and b^1 have
+  //    the same non-NULL value iff they are sharing a tree.  (An alternative
+  //    implementation strategy would be to have a tag bit per bucket.)
+  // 4. As is typical for hash_map and such, the Keys and Values are always
+  //    stored in linked list nodes.  Pointers to elements are never invalidated
+  //    until the element is deleted.
+  // 5. The trees' payload type is pointer to linked-list node.  Tree-converting
+  //    a bucket doesn't copy Key-Value pairs.
+  // 6. Once we've tree-converted a bucket, it is never converted back. However,
+  //    the items a tree contains may wind up assigned to trees or lists upon a
+  //    rehash.
+  // 7. The code requires no C++ features from C++11 or later.
+  // 8. Mutations to a map do not invalidate the map's iterators, pointers to
+  //    elements, or references to elements.
+  // 9. Except for erase(iterator), any non-const method can reorder iterators.
+  class LIBPROTOBUF_EXPORT InnerMap : private hasher {
+   public:
+    typedef value_type* Value;
+
+    InnerMap(size_type n, hasher h, Allocator alloc)
+        : hasher(h),
+          num_elements_(0),
+          seed_(Seed()),
+          table_(NULL),
+          alloc_(alloc) {
+      n = TableSize(n);
+      table_ = CreateEmptyTable(n);
+      num_buckets_ = index_of_first_non_null_ = n;
+    }
+
+    ~InnerMap() {
+      if (table_ != NULL) {
+        clear();
+        Dealloc<void*>(table_, num_buckets_);
+      }
+    }
+
+   private:
+    enum { kMinTableSize = 8 };
+
+    // Linked-list nodes, as one would expect for a chaining hash table.
+    struct Node {
+      KeyValuePair kv;
+      Node* next;
+    };
+
+    // This is safe only if the given pointer is known to point to a Key that is
+    // part of a Node.
+    static Node* NodePtrFromKeyPtr(Key* k) {
+      return reinterpret_cast<Node*>(k);
+    }
+
+    static Key* KeyPtrFromNodePtr(Node* node) { return &node->kv.key(); }
+
+    // Trees.  The payload type is pointer to Key, so that we can query the tree
+    // with Keys that are not in any particular data structure.  When we insert,
+    // though, the pointer is always pointing to a Key that is inside a Node.
+    struct KeyCompare {
+      bool operator()(const Key* n0, const Key* n1) const { return *n0 < *n1; }
+    };
+    typedef typename Allocator::template rebind<Key*>::other KeyPtrAllocator;
+    typedef std::set<Key*, KeyCompare, KeyPtrAllocator> Tree;
+
+    // iterator and const_iterator are instantiations of iterator_base.
+    template <typename KeyValueType>
+    class iterator_base {
+     public:
+      typedef KeyValueType& reference;
+      typedef KeyValueType* pointer;
+      typedef typename Tree::iterator TreeIterator;
+
+      // Invariants:
+      // node_ is always correct. This is handy because the most common
+      // operations are operator* and operator-> and they only use node_.
+      // When node_ is set to a non-NULL value, all the other non-const fields
+      // are updated to be correct also, but those fields can become stale
+      // if the underlying map is modified.  When those fields are needed they
+      // are rechecked, and updated if necessary.
+      iterator_base() : node_(NULL) {}
+
+      explicit iterator_base(const InnerMap* m) : m_(m) {
+        SearchFrom(m->index_of_first_non_null_);
+      }
+
+      // Any iterator_base can convert to any other.  This is overkill, and we
+      // rely on the enclosing class to use it wisely.  The standard "iterator
+      // can convert to const_iterator" is OK but the reverse direction is not.
+      template <typename U>
+      explicit iterator_base(const iterator_base<U>& it)
+          : node_(it.node_),
+            m_(it.m_),
+            bucket_index_(it.bucket_index_),
+            tree_it_(it.tree_it_) {}
+
+      iterator_base(Node* n, const InnerMap* m, size_type index)
+          : node_(n),
+            m_(m),
+            bucket_index_(index) {}
+
+      iterator_base(TreeIterator tree_it, const InnerMap* m, size_type index)
+          : node_(NodePtrFromKeyPtr(*tree_it)),
+            m_(m),
+            bucket_index_(index),
+            tree_it_(tree_it) {
+        // Invariant: iterators that use tree_it_ have an even bucket_index_.
+        GOOGLE_DCHECK_EQ(bucket_index_ % 2, 0);
+      }
+
+      // Advance through buckets, looking for the first that isn't empty.
+      // If nothing non-empty is found then leave node_ == NULL.
+      void SearchFrom(size_type start_bucket) {
+        node_ = NULL;
+        for (bucket_index_ = start_bucket; bucket_index_ < m_->num_buckets_;
+             bucket_index_++) {
+          if (m_->TableEntryIsNonEmptyList(bucket_index_)) {
+            node_ = static_cast<Node*>(m_->table_[bucket_index_]);
+            break;
+          } else if (m_->TableEntryIsTree(bucket_index_)) {
+            Tree* tree = static_cast<Tree*>(m_->table_[bucket_index_]);
+            GOOGLE_DCHECK(!tree->empty());
+            tree_it_ = tree->begin();
+            node_ = NodePtrFromKeyPtr(*tree_it_);
+            break;
+          }
+        }
+      }
+
+      reference operator*() const { return node_->kv; }
+      pointer operator->() const { return &(operator*()); }
+
+      friend bool operator==(const iterator_base& a, const iterator_base& b) {
+        return a.node_ == b.node_;
+      }
+      friend bool operator!=(const iterator_base& a, const iterator_base& b) {
+        return a.node_ != b.node_;
+      }
+
+      iterator_base& operator++() {
+        if (node_->next == NULL) {
+          const bool is_list = revalidate_if_necessary();
+          if (is_list) {
+            SearchFrom(bucket_index_ + 1);
+          } else {
+            GOOGLE_DCHECK_EQ(bucket_index_ & 1, 0);
+            Tree* tree = static_cast<Tree*>(m_->table_[bucket_index_]);
+            if (++tree_it_ == tree->end()) {
+              SearchFrom(bucket_index_ + 2);
+            } else {
+              node_ = NodePtrFromKeyPtr(*tree_it_);
+            }
+          }
+        } else {
+          node_ = node_->next;
+        }
+        return *this;
+      }
+
+      iterator_base operator++(int /* unused */) {
+        iterator_base tmp = *this;
+        ++*this;
+        return tmp;
+      }
+
+      // Assumes node_ and m_ are correct and non-NULL, but other fields may be
+      // stale.  Fix them as needed.  Then return true iff node_ points to a
+      // Node in a list.
+      bool revalidate_if_necessary() {
+        GOOGLE_DCHECK(node_ != NULL && m_ != NULL);
+        // Force bucket_index_ to be in range.
+        bucket_index_ &= (m_->num_buckets_ - 1);
+        // Common case: the bucket we think is relevant points to node_.
+        if (m_->table_[bucket_index_] == static_cast<void*>(node_))
+          return true;
+        // Less common: the bucket is a linked list with node_ somewhere in it,
+        // but not at the head.
+        if (m_->TableEntryIsNonEmptyList(bucket_index_)) {
+          Node* l = static_cast<Node*>(m_->table_[bucket_index_]);
+          while ((l = l->next) != NULL) {
+            if (l == node_) {
+              return true;
+            }
+          }
+        }
+        // Well, bucket_index_ still might be correct, but probably
+        // not.  Revalidate just to be sure.  This case is rare enough that we
+        // don't worry about potential optimizations, such as having a custom
+        // find-like method that compares Node* instead of const Key&.
+        iterator_base i(m_->find(*KeyPtrFromNodePtr(node_)));
+        bucket_index_ = i.bucket_index_;
+        tree_it_ = i.tree_it_;
+        return m_->TableEntryIsList(bucket_index_);
+      }
+
+      Node* node_;
+      const InnerMap* m_;
+      size_type bucket_index_;
+      TreeIterator tree_it_;
+    };
+
+   public:
+    typedef iterator_base<KeyValuePair> iterator;
+    typedef iterator_base<const KeyValuePair> const_iterator;
+
+    iterator begin() { return iterator(this); }
+    iterator end() { return iterator(); }
+    const_iterator begin() const { return const_iterator(this); }
+    const_iterator end() const { return const_iterator(); }
+
+    void clear() {
+      for (size_type b = 0; b < num_buckets_; b++) {
+        if (TableEntryIsNonEmptyList(b)) {
+          Node* node = static_cast<Node*>(table_[b]);
+          table_[b] = NULL;
+          do {
+            Node* next = node->next;
+            DestroyNode(node);
+            node = next;
+          } while (node != NULL);
+        } else if (TableEntryIsTree(b)) {
+          Tree* tree = static_cast<Tree*>(table_[b]);
+          GOOGLE_DCHECK(table_[b] == table_[b + 1] && (b & 1) == 0);
+          table_[b] = table_[b + 1] = NULL;
+          typename Tree::iterator tree_it = tree->begin();
+          do {
+            Node* node = NodePtrFromKeyPtr(*tree_it);
+            typename Tree::iterator next = tree_it;
+            ++next;
+            tree->erase(tree_it);
+            DestroyNode(node);
+            tree_it = next;
+          } while (tree_it != tree->end());
+          DestroyTree(tree);
+          b++;
+        }
+      }
+      num_elements_ = 0;
+      index_of_first_non_null_ = num_buckets_;
+    }
+
+    const hasher& hash_function() const { return *this; }
+
+    static size_type max_size() {
+      return static_cast<size_type>(1) << (sizeof(table_) >= 8 ? 60 : 28);
+    }
+    size_type size() const { return num_elements_; }
+    bool empty() const { return size() == 0; }
+
+    iterator find(const Key& k) { return iterator(FindHelper(k).first); }
+    const_iterator find(const Key& k) const { return FindHelper(k).first; }
+
+    // In traditional C++ style, this performs "insert if not present."
+    std::pair<iterator, bool> insert(const KeyValuePair& kv) {
+      std::pair<const_iterator, size_type> p = FindHelper(kv.key());
+      // Case 1: key was already present.
+      if (p.first.node_ != NULL)
+        return std::make_pair(iterator(p.first), false);
+      // Case 2: insert.
+      if (ResizeIfLoadIsOutOfRange(num_elements_ + 1)) {
+        p = FindHelper(kv.key());
+      }
+      const size_type b = p.second;  // bucket number
+      Node* node = Alloc<Node>(1);
+      alloc_.construct(&node->kv, kv);
+      iterator result = InsertUnique(b, node);
+      ++num_elements_;
+      return std::make_pair(result, true);
+    }
+
+    // The same, but if an insertion is necessary then the value portion of the
+    // inserted key-value pair is left uninitialized.
+    std::pair<iterator, bool> insert(const Key& k) {
+      std::pair<const_iterator, size_type> p = FindHelper(k);
+      // Case 1: key was already present.
+      if (p.first.node_ != NULL)
+        return std::make_pair(iterator(p.first), false);
+      // Case 2: insert.
+      if (ResizeIfLoadIsOutOfRange(num_elements_ + 1)) {
+        p = FindHelper(k);
+      }
+      const size_type b = p.second;  // bucket number
+      Node* node = Alloc<Node>(1);
+      typedef typename Allocator::template rebind<Key>::other KeyAllocator;
+      KeyAllocator(alloc_).construct(&node->kv.key(), k);
+      iterator result = InsertUnique(b, node);
+      ++num_elements_;
+      return std::make_pair(result, true);
+    }
+
+    Value& operator[](const Key& k) {
+      KeyValuePair kv(k, Value());
+      return insert(kv).first->value();
+    }
+
+    void erase(iterator it) {
+      GOOGLE_DCHECK_EQ(it.m_, this);
+      const bool is_list = it.revalidate_if_necessary();
+      const size_type b = it.bucket_index_;
+      Node* const item = it.node_;
+      if (is_list) {
+        GOOGLE_DCHECK(TableEntryIsNonEmptyList(b));
+        Node* head = static_cast<Node*>(table_[b]);
+        head = EraseFromLinkedList(item, head);
+        table_[b] = static_cast<void*>(head);
+      } else {
+        GOOGLE_DCHECK(TableEntryIsTree(b));
+        Tree* tree = static_cast<Tree*>(table_[b]);
+        tree->erase(it.tree_it_);
+        if (tree->empty()) {
+          DestroyTree(tree);
+          table_[b] = table_[b ^ 1] = NULL;
+        }
+      }
+      DestroyNode(item);
+      --num_elements_;
+      if (GOOGLE_PREDICT_FALSE(b == index_of_first_non_null_)) {
+        while (index_of_first_non_null_ < num_buckets_ &&
+               table_[index_of_first_non_null_] == 0) {
+          ++index_of_first_non_null_;
+        }
+      }
+    }
+
+   private:
+    std::pair<const_iterator, size_type> FindHelper(const Key& k) const {
+      size_type b = BucketNumber(k);
+      if (TableEntryIsNonEmptyList(b)) {
+        Node* node = static_cast<Node*>(table_[b]);
+        do {
+          if (IsMatch(*KeyPtrFromNodePtr(node), k)) {
+            return std::make_pair(const_iterator(node, this, b), b);
+          } else {
+            node = node->next;
+          }
+        } while (node != NULL);
+      } else if (TableEntryIsTree(b)) {
+        GOOGLE_DCHECK_EQ(table_[b], table_[b ^ 1]);
+        b &= ~static_cast<size_t>(1);
+        Tree* tree = static_cast<Tree*>(table_[b]);
+        Key* key = const_cast<Key*>(&k);
+        typename Tree::iterator tree_it = tree->find(key);
+        if (tree_it != tree->end()) {
+          return std::make_pair(const_iterator(tree_it, this, b), b);
+        }
+      }
+      return std::make_pair(end(), b);
+    }
+
+    // Insert the given Node in bucket b.  If that would make bucket b too big,
+    // and bucket b is not a tree, create a tree for buckets b and b^1 to share.
+    // Requires count(*KeyPtrFromNodePtr(node)) == 0 and that b is the correct
+    // bucket.  num_elements_ is not modified.
+    iterator InsertUnique(size_type b, Node* node) {
+      // In practice, the code that led to this point may have already
+      // determined whether we are inserting into an empty list, a short list,
+      // or whatever.  But it's probably cheap enough to recompute that here;
+      // it's likely that we're inserting into an empty or short list.
+      iterator result;
+      GOOGLE_DCHECK(find(*KeyPtrFromNodePtr(node)) == end());
+      if (TableEntryIsEmpty(b)) {
+        result = InsertUniqueInList(b, node);
+      } else if (TableEntryIsNonEmptyList(b)) {
+        if (GOOGLE_PREDICT_FALSE(TableEntryIsTooLong(b))) {
+          TreeConvert(b);
+          result = InsertUniqueInTree(b, node);
+        } else {
+          result = InsertUniqueInList(b, node);
+        }
+      } else {
+        result = InsertUniqueInTree(b, node);
+      }
+      index_of_first_non_null_ =
+          std::min(index_of_first_non_null_, result.bucket_index_);
+      return result;
+    }
+
+    // Helper for InsertUnique.  Handles the case where bucket b is a
+    // not-too-long linked list.
+    iterator InsertUniqueInList(size_type b, Node* node) {
+      node->next = static_cast<Node*>(table_[b]);
+      table_[b] = static_cast<void*>(node);
+      return iterator(node, this, b);
+    }
+
+    // Helper for InsertUnique.  Handles the case where bucket b points to a
+    // Tree.
+    iterator InsertUniqueInTree(size_type b, Node* node) {
+      GOOGLE_DCHECK_EQ(table_[b], table_[b ^ 1]);
+      // Maintain the invariant that node->next is NULL for all Nodes in Trees.
+      node->next = NULL;
+      return iterator(static_cast<Tree*>(table_[b])
+                      ->insert(KeyPtrFromNodePtr(node))
+                      .first,
+                      this, b & ~static_cast<size_t>(1));
+    }
+
+    // Returns whether it did resize.  Currently this is only used when
+    // num_elements_ increases, though it could be used in other situations.
+    // It checks for load too low as well as load too high: because any number
+    // of erases can occur between inserts, the load could be as low as 0 here.
+    // Resizing to a lower size is not always helpful, but failing to do so can
+    // destroy the expected big-O bounds for some operations. By having the
+    // policy that sometimes we resize down as well as up, clients can easily
+    // keep O(size()) = O(number of buckets) if they want that.
+    bool ResizeIfLoadIsOutOfRange(size_type new_size) {
+      const size_type kMaxMapLoadTimes16 = 12;  // controls RAM vs CPU tradeoff
+      const size_type hi_cutoff = num_buckets_ * kMaxMapLoadTimes16 / 16;
+      const size_type lo_cutoff = hi_cutoff / 4;
+      // We don't care how many elements are in trees.  If a lot are,
+      // we may resize even though there are many empty buckets.  In
+      // practice, this seems fine.
+      if (GOOGLE_PREDICT_FALSE(new_size >= hi_cutoff)) {
+        if (num_buckets_ <= max_size() / 2) {
+          Resize(num_buckets_ * 2);
+          return true;
+        }
+      } else if (GOOGLE_PREDICT_FALSE(new_size <= lo_cutoff &&
+                               num_buckets_ > kMinTableSize)) {
+        size_type lg2_of_size_reduction_factor = 1;
+        // It's possible we want to shrink a lot here... size() could even be 0.
+        // So, estimate how much to shrink by making sure we don't shrink so
+        // much that we would need to grow the table after a few inserts.
+        const size_type hypothetical_size = new_size * 5 / 4 + 1;
+        while ((hypothetical_size << lg2_of_size_reduction_factor) <
+               hi_cutoff) {
+          ++lg2_of_size_reduction_factor;
+        }
+        size_type new_num_buckets = std::max<size_type>(
+            kMinTableSize, num_buckets_ >> lg2_of_size_reduction_factor);
+        if (new_num_buckets != num_buckets_) {
+          Resize(new_num_buckets);
+          return true;
+        }
+      }
+      return false;
+    }
+
+    // Resize to the given number of buckets.
+    void Resize(size_t new_num_buckets) {
+      GOOGLE_DCHECK_GE(new_num_buckets, kMinTableSize);
+      void** const old_table = table_;
+      const size_type old_table_size = num_buckets_;
+      num_buckets_ = new_num_buckets;
+      table_ = CreateEmptyTable(num_buckets_);
+      const size_type start = index_of_first_non_null_;
+      index_of_first_non_null_ = 0;
+      for (size_type i = start; i < old_table_size; i++) {
+        if (TableEntryIsNonEmptyList(old_table, i)) {
+          TransferList(old_table, i);
+        } else if (TableEntryIsTree(old_table, i)) {
+          TransferTree(old_table, i++);
+        }
+      }
+      Dealloc<void*>(old_table, old_table_size);
+    }
+
+    void TransferList(void* const* table, size_type index) {
+      Node* node = static_cast<Node*>(table[index]);
+      do {
+        Node* next = node->next;
+        InsertUnique(BucketNumber(*KeyPtrFromNodePtr(node)), node);
+        node = next;
+      } while (node != NULL);
+    }
+
+    void TransferTree(void* const* table, size_type index) {
+      Tree* tree = static_cast<Tree*>(table[index]);
+      typename Tree::iterator tree_it = tree->begin();
+      do {
+        Node* node = NodePtrFromKeyPtr(*tree_it);
+        InsertUnique(BucketNumber(**tree_it), node);
+      } while (++tree_it != tree->end());
+      DestroyTree(tree);
+    }
+
+    Node* EraseFromLinkedList(Node* item, Node* head) {
+      if (head == item) {
+        return head->next;
+      } else {
+        head->next = EraseFromLinkedList(item, head->next);
+        return head;
+      }
+    }
+
+    bool TableEntryIsEmpty(size_type b) const {
+      return TableEntryIsEmpty(table_, b);
+    }
+    bool TableEntryIsNonEmptyList(size_type b) const {
+      return TableEntryIsNonEmptyList(table_, b);
+    }
+    bool TableEntryIsTree(size_type b) const {
+      return TableEntryIsTree(table_, b);
+    }
+    bool TableEntryIsList(size_type b) const {
+      return TableEntryIsList(table_, b);
+    }
+    static bool TableEntryIsEmpty(void* const* table, size_type b) {
+      return table[b] == 0;
+    }
+    static bool TableEntryIsNonEmptyList(void* const* table, size_type b) {
+      return table[b] != 0 && table[b] != table[b ^ 1];
+    }
+    static bool TableEntryIsTree(void* const* table, size_type b) {
+      return !TableEntryIsEmpty(table, b) &&
+          !TableEntryIsNonEmptyList(table, b);
+    }
+    static bool TableEntryIsList(void* const* table, size_type b) {
+      return !TableEntryIsTree(table, b);
+    }
+
+    void TreeConvert(size_type b) {
+      GOOGLE_DCHECK(!TableEntryIsTree(b) && !TableEntryIsTree(b ^ 1));
+      typename Allocator::template rebind<Tree>::other tree_allocator(alloc_);
+      Tree* tree = tree_allocator.allocate(1);
+      // We want to use the three-arg form of construct, if it exists, but we
+      // create a temporary and use the two-arg construct that's known to exist.
+      // It's clunky, but the compiler should be able to generate more-or-less
+      // the same code.
+      tree_allocator.construct(tree,
+                               Tree(KeyCompare(), KeyPtrAllocator(alloc_)));
+      // Now the tree is ready to use.
+      size_type count = CopyListToTree(b, tree) + CopyListToTree(b ^ 1, tree);
+      GOOGLE_DCHECK_EQ(count, tree->size());
+      table_[b] = table_[b ^ 1] = static_cast<void*>(tree);
+    }
+
+    // Copy a linked list in the given bucket to a tree.
+    // Returns the number of things it copied.
+    size_type CopyListToTree(size_type b, Tree* tree) {
+      size_type count = 0;
+      Node* node = static_cast<Node*>(table_[b]);
+      while (node != NULL) {
+        tree->insert(KeyPtrFromNodePtr(node));
+        ++count;
+        Node* next = node->next;
+        node->next = NULL;
+        node = next;
+      }
+      return count;
+    }
+
+    // Return whether table_[b] is a linked list that seems awfully long.
+    // Requires table_[b] to point to a non-empty linked list.
+    bool TableEntryIsTooLong(size_type b) {
+      const int kMaxLength = 8;
+      size_type count = 0;
+      Node* node = static_cast<Node*>(table_[b]);
+      do {
+        ++count;
+        node = node->next;
+      } while (node != NULL);
+      // Invariant: no linked list ever is more than kMaxLength in length.
+      GOOGLE_DCHECK_LE(count, kMaxLength);
+      return count >= kMaxLength;
+    }
+
+    size_type BucketNumber(const Key& k) const {
+      // We inherit from hasher, so one-arg operator() provides a hash function.
+      size_type h = (*this)(k);
+      // To help prevent people from making assumptions about the hash function,
+      // we use the seed differently depending on NDEBUG.  The default hash
+      // function, the seeding, etc., are all likely to change in the future.
+#ifndef NDEBUG
+      return (h * (seed_ | 1)) & (num_buckets_ - 1);
+#else
+      return (h + seed_) & (num_buckets_ - 1);
+#endif
+    }
+
+    bool IsMatch(const Key& k0, const Key& k1) const {
+      return std::equal_to<Key>()(k0, k1);
+    }
+
+    // Return a power of two no less than max(kMinTableSize, n).
+    // Assumes either n < kMinTableSize or n is a power of two.
+    size_type TableSize(size_type n) {
+      return n < kMinTableSize ? kMinTableSize : n;
+    }
+
+    // Use alloc_ to allocate an array of n objects of type U.
+    template <typename U>
+    U* Alloc(size_type n) {
+      typedef typename Allocator::template rebind<U>::other alloc_type;
+      return alloc_type(alloc_).allocate(n);
+    }
+
+    // Use alloc_ to deallocate an array of n objects of type U.
+    template <typename U>
+    void Dealloc(U* t, size_type n) {
+      typedef typename Allocator::template rebind<U>::other alloc_type;
+      alloc_type(alloc_).deallocate(t, n);
+    }
+
+    void DestroyNode(Node* node) {
+      alloc_.destroy(&node->kv);
+      Dealloc<Node>(node, 1);
+    }
+
+    void DestroyTree(Tree* tree) {
+      typename Allocator::template rebind<Tree>::other tree_allocator(alloc_);
+      tree_allocator.destroy(tree);
+      tree_allocator.deallocate(tree, 1);
+    }
+
+    void** CreateEmptyTable(size_type n) {
+      GOOGLE_DCHECK(n >= kMinTableSize);
+      GOOGLE_DCHECK_EQ(n & (n - 1), 0);
+      void** result = Alloc<void*>(n);
+      memset(result, 0, n * sizeof(result[0]));
+      return result;
+    }
+
+    // Return a randomish value.
+    size_type Seed() const {
+      // random_device can throw, so avoid it unless we are compiling with
+      // exceptions enabled.
+#if __cpp_exceptions && LANG_CXX11
+      try {
+        std::random_device rd;
+        std::knuth_b knuth(rd());
+        std::uniform_int_distribution<size_type> u;
+        return u(knuth);
+      } catch (...) { }
+#endif
+      size_type s = static_cast<size_type>(reinterpret_cast<uintptr_t>(this));
+#if defined(__x86_64__) && defined(__GNUC__)
+      uint32 hi, lo;
+      asm("rdtsc" : "=a" (lo), "=d" (hi));
+      s += ((static_cast<uint64>(hi) << 32) | lo);
+#endif
+      return s;
+    }
+
+    size_type num_elements_;
+    size_type num_buckets_;
+    size_type seed_;
+    size_type index_of_first_non_null_;
+    void** table_;  // an array with num_buckets_ entries
+    Allocator alloc_;
+    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(InnerMap);
+  };  // end of class InnerMap
+
+  typedef hash_map<Key, value_type*, hash<Key>, equal_to<Key>,
+                   MapAllocator<std::pair<const Key, MapPair<Key, T>*> > >
+      DeprecatedInnerMap;
 
  public:
   // Iterators
+  class LIBPROTOBUF_EXPORT iterator_base {
+   public:
+    // We support "old style" and "new style" iterators for now. This is
+    // temporary.  Also, for "iterator()" we have an unknown category.
+    // TODO(gpike): get rid of this.
+    enum IteratorStyle { kUnknown, kOld, kNew };
+    explicit iterator_base(IteratorStyle style) : iterator_style_(style) {}
+
+    bool OldStyle() const {
+      GOOGLE_DCHECK_NE(iterator_style_, kUnknown);
+      return iterator_style_ == kOld;
+    }
+    bool UnknownStyle() const {
+      return iterator_style_ == kUnknown;
+    }
+    bool SameStyle(const iterator_base& other) const {
+      return iterator_style_ == other.iterator_style_;
+    }
+
+   private:
+    IteratorStyle iterator_style_;
+  };
+
   class const_iterator
-      : public std::iterator<std::forward_iterator_tag, value_type, ptrdiff_t,
+      : private iterator_base,
+        public std::iterator<std::forward_iterator_tag, value_type, ptrdiff_t,
                              const value_type*, const value_type&> {
     typedef typename InnerMap::const_iterator InnerIt;
+    typedef typename DeprecatedInnerMap::const_iterator DeprecatedInnerIt;
 
    public:
-    const_iterator() {}
-    explicit const_iterator(const InnerIt& it) : it_(it) {}
+    const_iterator() : iterator_base(iterator_base::kUnknown) {}
+    explicit const_iterator(const DeprecatedInnerIt& dit)
+        : iterator_base(iterator_base::kOld), dit_(dit) {}
+    explicit const_iterator(const InnerIt& it)
+        : iterator_base(iterator_base::kNew), it_(it) {}
 
-    const_reference operator*() const { return *it_->second; }
-    const_pointer operator->() const { return it_->second; }
+    const_iterator(const const_iterator& other)
+        : iterator_base(other), it_(other.it_), dit_(other.dit_) {}
+
+    const_reference operator*() const {
+      return this->OldStyle() ? *dit_->second : *it_->value();
+    }
+    const_pointer operator->() const { return &(operator*()); }
 
     const_iterator& operator++() {
-      ++it_;
+      if (this->OldStyle())
+        ++dit_;
+      else
+        ++it_;
       return *this;
     }
-    const_iterator operator++(int) { return const_iterator(it_++); }
+    const_iterator operator++(int) {
+      return this->OldStyle() ? const_iterator(dit_++) : const_iterator(it_++);
+    }
 
     friend bool operator==(const const_iterator& a, const const_iterator& b) {
-      return a.it_ == b.it_;
+      if (!a.SameStyle(b)) return false;
+      if (a.UnknownStyle()) return true;
+      return a.OldStyle() ? (a.dit_ == b.dit_) : (a.it_ == b.it_);
     }
     friend bool operator!=(const const_iterator& a, const const_iterator& b) {
-      return a.it_ != b.it_;
+      return !(a == b);
     }
 
    private:
     InnerIt it_;
+    DeprecatedInnerIt dit_;
   };
 
-  class iterator : public std::iterator<std::forward_iterator_tag, value_type> {
+  class iterator : private iterator_base,
+                   public std::iterator<std::forward_iterator_tag, value_type> {
     typedef typename InnerMap::iterator InnerIt;
+    typedef typename DeprecatedInnerMap::iterator DeprecatedInnerIt;
 
    public:
-    iterator() {}
-    explicit iterator(const InnerIt& it) : it_(it) {}
+    iterator() : iterator_base(iterator_base::kUnknown) {}
+    explicit iterator(const DeprecatedInnerIt& dit)
+        : iterator_base(iterator_base::kOld), dit_(dit) {}
+    explicit iterator(const InnerIt& it)
+        : iterator_base(iterator_base::kNew), it_(it) {}
 
-    reference operator*() const { return *it_->second; }
-    pointer operator->() const { return it_->second; }
+    reference operator*() const {
+      return this->OldStyle() ? *dit_->second : *it_->value();
+    }
+    pointer operator->() const { return &(operator*()); }
 
     iterator& operator++() {
-      ++it_;
+      if (this->OldStyle())
+        ++dit_;
+      else
+        ++it_;
       return *this;
     }
-    iterator operator++(int) { return iterator(it_++); }
+    iterator operator++(int) {
+      return this->OldStyle() ? iterator(dit_++) : iterator(it_++);
+    }
 
-    // Implicitly convertible to const_iterator.
-    operator const_iterator() const { return const_iterator(it_); }
+    // Allow implicit conversion to const_iterator.
+    operator const_iterator() const {
+      return this->OldStyle() ?
+          const_iterator(typename DeprecatedInnerMap::const_iterator(dit_)) :
+          const_iterator(typename InnerMap::const_iterator(it_));
+    }
 
     friend bool operator==(const iterator& a, const iterator& b) {
-      return a.it_ == b.it_;
+      if (!a.SameStyle(b)) return false;
+      if (a.UnknownStyle()) return true;
+      return a.OldStyle() ? a.dit_ == b.dit_ : a.it_ == b.it_;
     }
     friend bool operator!=(const iterator& a, const iterator& b) {
-      return a.it_ != b.it_;
+      return !(a == b);
     }
 
    private:
     friend class Map;
+
     InnerIt it_;
+    DeprecatedInnerIt dit_;
   };
 
-  iterator begin() { return iterator(elements_.begin()); }
-  iterator end() { return iterator(elements_.end()); }
-  const_iterator begin() const { return const_iterator(elements_.begin()); }
-  const_iterator end() const { return const_iterator(elements_.end()); }
+  iterator begin() {
+    return old_style_ ? iterator(deprecated_elements_->begin())
+                      : iterator(elements_->begin());
+  }
+  iterator end() {
+    return old_style_ ? iterator(deprecated_elements_->end())
+                      : iterator(elements_->end());
+  }
+  const_iterator begin() const {
+    return old_style_ ? const_iterator(deprecated_elements_->begin())
+                      : const_iterator(iterator(elements_->begin()));
+  }
+  const_iterator end() const {
+    return old_style_ ? const_iterator(deprecated_elements_->end())
+                      : const_iterator(iterator(elements_->end()));
+  }
   const_iterator cbegin() const { return begin(); }
   const_iterator cend() const { return end(); }
 
   // Capacity
-  size_type size() const { return elements_.size(); }
-  bool empty() const { return elements_.empty(); }
+  size_type size() const {
+    return old_style_ ? deprecated_elements_->size() : elements_->size();
+  }
+  bool empty() const { return size() == 0; }
 
   // Element access
   T& operator[](const key_type& key) {
-    value_type** value = &elements_[key];
+    value_type** value =
+        old_style_ ? &(*deprecated_elements_)[key] : &(*elements_)[key];
     if (*value == NULL) {
       *value = CreateValueTypeInternal(key);
       internal::MapValueInitializer<google::protobuf::is_proto_enum<T>::value,
@@ -690,13 +1505,16 @@
 
   // Lookup
   size_type count(const key_type& key) const {
-    return elements_.count(key);
+    if (find(key) != end()) assert(key == find(key)->first);
+    return find(key) == end() ? 0 : 1;
   }
   const_iterator find(const key_type& key) const {
-    return const_iterator(elements_.find(key));
+    return old_style_ ? const_iterator(deprecated_elements_->find(key))
+        : const_iterator(iterator(elements_->find(key)));
   }
   iterator find(const key_type& key) {
-    return iterator(elements_.find(key));
+    return old_style_ ? iterator(deprecated_elements_->find(key))
+                      : iterator(elements_->find(key));
   }
   std::pair<const_iterator, const_iterator> equal_range(
       const key_type& key) const {
@@ -720,13 +1538,22 @@
 
   // insert
   std::pair<iterator, bool> insert(const value_type& value) {
-    iterator it = find(value.first);
-    if (it != end()) {
-      return std::pair<iterator, bool>(it, false);
+    if (old_style_) {
+      iterator it = find(value.first);
+      if (it != end()) {
+        return std::pair<iterator, bool>(it, false);
+      } else {
+        return std::pair<iterator, bool>(
+            iterator(deprecated_elements_->insert(std::pair<Key, value_type*>(
+                value.first, CreateValueTypeInternal(value))).first), true);
+      }
     } else {
-      return std::pair<iterator, bool>(
-          iterator(elements_.insert(std::pair<Key, value_type*>(
-              value.first, CreateValueTypeInternal(value))).first), true);
+      std::pair<typename InnerMap::iterator, bool> p =
+          elements_->insert(value.first);
+      if (p.second) {
+        p.first->value() = CreateValueTypeInternal(value);
+      }
+      return std::pair<iterator, bool>(iterator(p.first), p.second);
     }
   }
   template <class InputIt>
@@ -739,33 +1566,31 @@
     }
   }
 
-  // Erase
+  // Erase and clear
   size_type erase(const key_type& key) {
-    typename InnerMap::iterator it = elements_.find(key);
-    if (it == elements_.end()) {
+    iterator it = find(key);
+    if (it == end()) {
       return 0;
     } else {
-      if (arena_ == NULL) delete it->second;
-      elements_.erase(it);
+      erase(it);
       return 1;
     }
   }
-  void erase(iterator pos) {
-    if (arena_ == NULL) delete pos.it_->second;
-    elements_.erase(pos.it_);
+  iterator erase(iterator pos) {
+    if (arena_ == NULL) delete pos.operator->();
+    iterator i = pos++;
+    if (old_style_)
+      deprecated_elements_->erase(i.dit_);
+    else
+      elements_->erase(i.it_);
+    return pos;
   }
   void erase(iterator first, iterator last) {
-    for (iterator it = first; it != last;) {
-      if (arena_ == NULL) delete it.it_->second;
-      elements_.erase((it++).it_);
+    while (first != last) {
+      first = erase(first);
     }
   }
-  void clear() {
-    for (iterator it = begin(); it != end(); ++it) {
-      if (arena_ == NULL) delete it.it_->second;
-    }
-    elements_.clear();
-  }
+  void clear() { erase(begin(), end()); }
 
   // Assign
   Map& operator=(const Map& other) {
@@ -776,6 +1601,13 @@
     return *this;
   }
 
+  // Access to hasher.  Currently this returns a copy, but it may
+  // be modified to return a const reference in the future.
+  hasher hash_function() const {
+    return old_style_ ? deprecated_elements_->hash_function()
+                      : elements_->hash_function();
+  }
+
  private:
   // Set default enum value only for proto2 map field whose value is enum type.
   void SetDefaultEnumValue(int default_enum_value) {
@@ -810,9 +1642,15 @@
   }
 
   Arena* arena_;
-  Allocator allocator_;
-  InnerMap elements_;
   int default_enum_value_;
+  // The following is a tagged union because we support two map styles
+  // for now.
+  // TODO(gpike): get rid of the old style.
+  const bool old_style_;
+  union {
+    InnerMap* elements_;
+    DeprecatedInnerMap* deprecated_elements_;
+  };
 
   friend class ::google::protobuf::Arena;
   typedef void InternalArenaConstructable_;
@@ -833,6 +1671,12 @@
   size_t
   operator()(const google::protobuf::MapKey& map_key) const {
     switch (map_key.type()) {
+      case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
+      case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
+      case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
+      case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
+        GOOGLE_LOG(FATAL) << "Unsupported";
+        break;
       case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
         return hash<string>()(map_key.GetStringValue());
       case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
@@ -845,11 +1689,6 @@
         return hash< ::google::protobuf::uint32>()(map_key.GetUInt32Value());
       case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
         return hash<bool>()(map_key.GetBoolValue());
-      case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
-      case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
-      case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
-      case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
-        GOOGLE_LOG(FATAL) << "Can't get here.";
     }
     GOOGLE_LOG(FATAL) << "Can't get here.";
     return 0;
@@ -857,26 +1696,7 @@
   bool
   operator()(const google::protobuf::MapKey& map_key1,
              const google::protobuf::MapKey& map_key2) const {
-    switch (map_key1.type()) {
-#define COMPARE_CPPTYPE(CPPTYPE, CPPTYPE_METHOD)             \
-      case google::protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE: \
-        return map_key1.Get##CPPTYPE_METHOD##Value() <           \
-               map_key2.Get##CPPTYPE_METHOD##Value();
-      COMPARE_CPPTYPE(STRING, String)
-      COMPARE_CPPTYPE(INT64,  Int64)
-      COMPARE_CPPTYPE(INT32,  Int32)
-      COMPARE_CPPTYPE(UINT64, UInt64)
-      COMPARE_CPPTYPE(UINT32, UInt32)
-      COMPARE_CPPTYPE(BOOL,   Bool)
-#undef COMPARE_CPPTYPE
-      case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
-      case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
-      case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
-      case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
-        GOOGLE_LOG(FATAL) << "Can't get here.";
-    }
-    GOOGLE_LOG(FATAL) << "Can't get here.";
-    return true;
+    return map_key1 < map_key2;
   }
 };
 GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END
diff --git a/src/google/protobuf/map_test.cc b/src/google/protobuf/map_test.cc
index 451b02e..1f3de4f 100644
--- a/src/google/protobuf/map_test.cc
+++ b/src/google/protobuf/map_test.cc
@@ -28,12 +28,16 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+#include <algorithm>
+#include <google/protobuf/stubs/hash.h>
 #include <map>
 #include <memory>
 #ifndef _SHARED_PTR_H
 #include <google/protobuf/stubs/shared_ptr.h>
 #endif
+#include <set>
 #include <sstream>
+#include <vector>
 
 #include <google/protobuf/stubs/casts.h>
 #include <google/protobuf/stubs/logging.h>
@@ -62,6 +66,7 @@
 #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/util/time_util.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/substitute.h>
 #include <google/protobuf/testing/googletest.h>
@@ -79,10 +84,11 @@
 
 // Map API Test =====================================================
 
-class MapImplTest : public ::testing::Test {
+// Parameterized tests on whether to use old style maps.
+class MapImplTest : public testing::TestWithParam<bool> {
  protected:
   MapImplTest()
-      : map_ptr_(new Map<int32, int32>),
+      : map_ptr_(new Map<int32, int32>(GetParam())),
         map_(*map_ptr_),
         const_map_(*map_ptr_) {
     EXPECT_TRUE(map_.empty());
@@ -159,7 +165,7 @@
   const Map<int32, int32>& const_map_;
 };
 
-TEST_F(MapImplTest, OperatorBracket) {
+TEST_P(MapImplTest, OperatorBracket) {
   int32 key = 0;
   int32 value1 = 100;
   int32 value2 = 101;
@@ -173,7 +179,7 @@
   ExpectSingleElement(key, value2);
 }
 
-TEST_F(MapImplTest, OperatorBracketNonExist) {
+TEST_P(MapImplTest, OperatorBracketNonExist) {
   int32 key = 0;
   int32 default_value = 0;
 
@@ -181,7 +187,7 @@
   ExpectSingleElement(key, default_value);
 }
 
-TEST_F(MapImplTest, MutableAt) {
+TEST_P(MapImplTest, MutableAt) {
   int32 key = 0;
   int32 value1 = 100;
   int32 value2 = 101;
@@ -195,15 +201,15 @@
 
 #ifdef PROTOBUF_HAS_DEATH_TEST
 
-TEST_F(MapImplTest, MutableAtNonExistDeathTest) {
+TEST_P(MapImplTest, MutableAtNonExistDeathTest) {
   EXPECT_DEATH(map_.at(0), "");
 }
 
-TEST_F(MapImplTest, ImmutableAtNonExistDeathTest) {
+TEST_P(MapImplTest, ImmutableAtNonExistDeathTest) {
   EXPECT_DEATH(const_map_.at(0), "");
 }
 
-TEST_F(MapImplTest, UsageErrors) {
+TEST_P(MapImplTest, UsageErrors) {
   MapKey key;
   key.SetInt64Value(1);
   EXPECT_DEATH(key.GetUInt64Value(),
@@ -220,23 +226,23 @@
 
 #endif  // PROTOBUF_HAS_DEATH_TEST
 
-TEST_F(MapImplTest, CountNonExist) {
+TEST_P(MapImplTest, CountNonExist) {
   EXPECT_EQ(0, map_.count(0));
 }
 
-TEST_F(MapImplTest, MutableFindNonExist) {
+TEST_P(MapImplTest, MutableFindNonExist) {
   EXPECT_TRUE(map_.end() == map_.find(0));
 }
 
-TEST_F(MapImplTest, ImmutableFindNonExist) {
+TEST_P(MapImplTest, ImmutableFindNonExist) {
   EXPECT_TRUE(const_map_.end() == const_map_.find(0));
 }
 
-TEST_F(MapImplTest, ConstEnd) {
+TEST_P(MapImplTest, ConstEnd) {
   EXPECT_TRUE(const_map_.end() == const_map_.cend());
 }
 
-TEST_F(MapImplTest, GetReferenceFromIterator) {
+TEST_P(MapImplTest, GetReferenceFromIterator) {
   for (int i = 0; i < 10; i++) {
     map_[i] = i;
   }
@@ -259,7 +265,7 @@
   }
 }
 
-TEST_F(MapImplTest, IteratorBasic) {
+TEST_P(MapImplTest, IteratorBasic) {
   map_[0] = 0;
 
   // Default constructible (per forward iterator requirements).
@@ -281,6 +287,281 @@
   EXPECT_TRUE(it == cit);
 }
 
+template <typename Iterator>
+static int64 median(Iterator i0, Iterator i1) {
+  vector<int64> v(i0, i1);
+  std::nth_element(v.begin(), v.begin() + v.size() / 2, v.end());
+  return v[v.size() / 2];
+}
+
+static int64 Now() {
+  return google::protobuf::util::TimeUtil::TimestampToNanoseconds(
+      google::protobuf::util::TimeUtil::GetCurrentTime());
+}
+
+// A naive begin() implementation will cause begin() to get slower and slower
+// if one erases elements at the "front" of the hash map, and we'd like to
+// avoid that, as std::unordered_map does.
+TEST_P(MapImplTest, BeginIsFast) {
+  if (GetParam()) return;
+  Map<int32, int32> map(false);  // This test uses new-style maps only.
+  const int kTestSize = 250000;
+  for (int i = 0; i < kTestSize; i++) {
+    map[i] = i;
+  }
+  vector<int64> times;
+  // We're going to do map.erase(map.begin()) over and over again.  But,
+  // just in case one iteration is fast compared to the granularity of
+  // our time keeping, we measure kChunkSize iterations per outer-loop iter.
+  const int kChunkSize = 1000;
+  GOOGLE_CHECK_EQ(kTestSize % kChunkSize, 0);
+  do {
+    const int64 start = Now();
+    for (int i = 0; i < kChunkSize; i++) {
+      map.erase(map.begin());
+    }
+    const int64 end = Now();
+    if (end > start) {
+      times.push_back(end - start);
+    }
+  } while (!map.empty());
+  if (times.size() < .99 * kTestSize / kChunkSize) {
+    GOOGLE_LOG(WARNING) << "Now() isn't helping us measure time";
+    return;
+  }
+  int64 x0 = median(times.begin(), times.begin() + 9);
+  int64 x1 = median(times.begin() + times.size() - 9, times.end());
+  GOOGLE_LOG(INFO) << "x0=" << x0 << ", x1=" << x1;
+  // x1 will greatly exceed x0 if the code we just executed took O(n^2) time.
+  // And we'll probably time out and never get here.  So, this test is
+  // intentionally loose: we check that x0 and x1 are within a factor of 8.
+  EXPECT_GE(x1, x0 / 8);
+  EXPECT_GE(x0, x1 / 8);
+}
+
+// Try to create kTestSize keys that will land in just a few buckets, and
+// time the insertions, to get a rough estimate of whether an O(n^2) worst case
+// was triggered.  This test is a hacky, but probably better than nothing.
+TEST_P(MapImplTest, HashFlood) {
+  const int kTestSize = 1024;  // must be a power of 2
+  std::set<int> s;
+  for (int i = 0; s.size() < kTestSize; i++) {
+    if ((map_.hash_function()(i) & (kTestSize - 1)) < 3) {
+      s.insert(i);
+    }
+  }
+  // Create hash table with kTestSize entries that hash flood a table with
+  // 1024 (or 512 or 2048 or ...) entries.  This assumes that map_ uses powers
+  // of 2 for table sizes, and that it's sufficient to "flood" with respect to
+  // the low bits of the output of map_.hash_function().
+  vector<int64> times;
+  std::set<int>::iterator it = s.begin();
+  int count = 0;
+  do {
+    const int64 start = Now();
+    map_[*it] = 0;
+    const int64 end = Now();
+    if (end > start) {
+      times.push_back(end - start);
+    }
+    ++count;
+    ++it;
+  } while (it != s.end());
+  if (times.size() < .99 * count) return;
+  int64 x0 = median(times.begin(), times.begin() + 9);
+  int64 x1 = median(times.begin() + times.size() - 9, times.end());
+  // x1 will greatly exceed x0 if the code we just executed took O(n^2) time.
+  // But we want to allow O(n log n).  A factor of 20 should be generous enough.
+  EXPECT_LE(x1, x0 * 20);
+}
+
+// Arbitrary odd integers for creating test data.
+static int k0 = 812398771;
+static int k1 = 1312938717;
+static int k2 = 1321555333;
+
+template <typename T, typename U>
+static void TestValidityForAllKeysExcept(int key_to_avoid,
+                                         const T& check_map,
+                                         const U& map) {
+  typedef typename U::value_type value_type;  // a key-value pair
+  for (typename U::const_iterator it = map.begin(); it != map.end(); ++it) {
+    const int key = it->first;
+    if (key == key_to_avoid) continue;
+    // All iterators relevant to this key, whether old (from check_map) or new,
+    // must point to the same memory.  So, test pointer equality here.
+    const value_type* check_val = &*check_map.find(key)->second;
+    EXPECT_EQ(check_val, &*it);
+    EXPECT_EQ(check_val, &*map.find(key));
+  }
+}
+
+// EXPECT i0 and i1 to be the same.  Advancing them should have the same effect,
+// too.
+template <typename Iter>
+static void TestEqualIterators(Iter i0, Iter i1, Iter end) {
+  const int kMaxAdvance = 10;
+  for (int i = 0; i < kMaxAdvance; i++) {
+    EXPECT_EQ(i0 == end, i1 == end);
+    if (i0 == end) return;
+    EXPECT_EQ(&*i0, &*i1) << "iter " << i;
+    ++i0;
+    ++i1;
+  }
+}
+
+template <typename IteratorType>
+static void TestOldVersusNewIterator(int skip, Map<int, int>* m) {
+  const int initial_size = m->size();
+  IteratorType it = m->begin();
+  for (int i = 0; i < skip && it != m->end(); it++, i++) {}
+  if (it == m->end()) return;
+  const IteratorType old = it;
+  GOOGLE_LOG(INFO) << "skip=" << skip << ", old->first=" << old->first;
+  const int target_size =
+      initial_size < 100 ? initial_size * 5 : initial_size * 5 / 4;
+  for (int i = 0; m->size() <= target_size; i++) {
+    (*m)[i] = 0;
+  }
+  // Iterator 'old' should still work just fine despite the growth of *m.
+  const IteratorType after_growth = m->find(old->first);
+  TestEqualIterators<IteratorType>(old, after_growth, m->end());
+
+  // Now shrink the number of elements.  Do this with a mix of erases and
+  // inserts to increase the chance that the hashtable will resize to a lower
+  // number of buckets.  (But, in any case, the test is still useful.)
+  for (int i = 0; i < 2 * (target_size - initial_size); i++) {
+    if (i != old->first) {
+      m->erase(i);
+    }
+    if (((i ^ m->begin()->first) & 15) == 0) {
+      (*m)[i * 342] = i;
+    }
+  }
+  // Now, the table has grown and shrunk; test again.
+  TestEqualIterators<IteratorType>(old, m->find(old->first), m->end());
+  TestEqualIterators<IteratorType>(old, after_growth, m->end());
+}
+
+// Create and test an n-element Map, with emphasis on iterator correctness.
+static void StressTestIterators(int n, bool test_old_style_proto2_maps) {
+  GOOGLE_LOG(INFO) << "StressTestIterators " << n;
+  GOOGLE_CHECK_GT(n, 0);
+  // Create a random-looking map of size n.  Use non-negative integer keys.
+  Map<int, int> m(test_old_style_proto2_maps);
+  uint32 frog = 123987 + n;
+  int last_key = 0;
+  int counter = 0;
+  while (m.size() < n) {
+    frog *= static_cast<uint32>(k0);
+    frog ^= frog >> 17;
+    frog += counter++;
+    last_key =
+        static_cast<int>(frog) >= 0 ? static_cast<int>(frog) : last_key ^ 1;
+    GOOGLE_DCHECK_GE(last_key, 0);
+    m[last_key] = last_key ^ 1;
+  }
+  // Test it.
+  ASSERT_EQ(n, m.size());
+  // Create maps of pointers and iterators.
+  // These should remain valid even if we modify m.
+  hash_map<int, Map<int, int>::value_type*> mp(n);
+  hash_map<int, Map<int, int>::iterator> mi(n);
+  for (Map<int, int>::iterator it = m.begin(); it != m.end(); ++it) {
+    mp[it->first] = &*it;
+    mi[it->first] = it;
+  }
+  ASSERT_EQ(m.size(), mi.size());
+  ASSERT_EQ(m.size(), mp.size());
+  m.erase(last_key);
+  ASSERT_EQ(n - 1, m.size());
+  TestValidityForAllKeysExcept(last_key, mp, m);
+  TestValidityForAllKeysExcept(last_key, mi, m);
+
+  m[last_key] = 0;
+  ASSERT_EQ(n, m.size());
+  // Test old iterator vs new iterator, with table modification in between.
+  TestOldVersusNewIterator<Map<int, int>::const_iterator>(n % 3, &m);
+  TestOldVersusNewIterator<Map<int, int>::iterator>(n % (1 + (n / 40)), &m);
+  // Finally, ensure erase(iterator) doesn't reorder anything, becuase that is
+  // what its documentation says.
+  m[last_key] = m[last_key ^ 999] = 0;
+  vector<Map<int, int>::iterator> v;
+  v.reserve(m.size());
+  int position_of_last_key = 0;
+  for (Map<int, int>::iterator it = m.begin(); it != m.end(); ++it) {
+    if (it->first == last_key) {
+      position_of_last_key = v.size();
+    }
+    v.push_back(it);
+  }
+  ASSERT_EQ(m.size(), v.size());
+  const Map<int, int>::iterator erase_result = m.erase(m.find(last_key));
+  int index = 0;
+  for (Map<int, int>::iterator it = m.begin(); it != m.end(); ++it, ++index) {
+    if (index == position_of_last_key) {
+      EXPECT_EQ(&*erase_result, &*v[++index]);
+    }
+    ASSERT_EQ(&*it, &*v[index]);
+  }
+}
+
+TEST_P(MapImplTest, IteratorInvalidation) {
+  // As multiple underlying hash_map implementations do not follow the
+  // validation requirement, the test is disabled for old-style maps.
+  if (GetParam()) return;
+  // Create a set of pseudo-random sizes to test.
+#ifndef NDEBUG
+  const int kMaxSizeToTest = 100 * 1000;
+#else
+  const int kMaxSizeToTest = 1000 * 1000;
+#endif
+  std::set<int> s;
+  int n = kMaxSizeToTest;
+  int frog = k1 + n;
+  while (n > 1 && s.size() < 25) {
+    s.insert(n);
+    n = static_cast<int>(n * 100 / (101.0 + (frog & 63)));
+    frog *= k2;
+    frog ^= frog >> 17;
+  }
+  // Ensure we test a few small sizes.
+  s.insert(1);
+  s.insert(2);
+  s.insert(3);
+  // Now, the real work.
+  for (std::set<int>::iterator i = s.begin(); i != s.end(); ++i) {
+    StressTestIterators(*i, GetParam());
+  }
+}
+
+// Test that erase() revalidates iterators.
+TEST_P(MapImplTest, EraseRevalidates) {
+  // As multiple underlying hash_map implementations do not follow the
+  // validation requirement, the test is disabled for old-style maps.
+  if (GetParam()) return;
+  map_[3] = map_[13] = map_[20] = 0;
+  const int initial_size = map_.size();
+  EXPECT_EQ(3, initial_size);
+  vector<Map<int, int>::iterator> v;
+  for (Map<int, int>::iterator it = map_.begin(); it != map_.end(); ++it) {
+    v.push_back(it);
+  }
+  EXPECT_EQ(initial_size, v.size());
+  for (int i = 0; map_.size() <= initial_size * 20; i++) {
+    map_[i] = 0;
+  }
+  const int larger_size = map_.size();
+  // We've greatly increased the size of the map, so it is highly likely that
+  // the following will corrupt m if erase() doesn't properly revalidate
+  // iterators passed to it.  Finishing this routine without crashing indicates
+  // success.
+  for (int i = 0; i < v.size(); i++) {
+    map_.erase(v[i]);
+  }
+  EXPECT_EQ(larger_size - v.size(), map_.size());
+}
+
 template <typename T>
 bool IsConstHelper(T& /*t*/) {  // NOLINT. We want to catch non-const refs here.
   return false;
@@ -290,7 +571,7 @@
   return true;
 }
 
-TEST_F(MapImplTest, IteratorConstness) {
+TEST_P(MapImplTest, IteratorConstness) {
   map_[0] = 0;
   EXPECT_TRUE(IsConstHelper(*map_.cbegin()));
   EXPECT_TRUE(IsConstHelper(*const_map_.begin()));
@@ -303,14 +584,14 @@
   return false;
 }
 
-TEST_F(MapImplTest, IteratorCategory) {
+TEST_P(MapImplTest, IteratorCategory) {
   EXPECT_TRUE(IsForwardIteratorHelper(
       std::iterator_traits<Map<int, int>::iterator>::iterator_category()));
   EXPECT_TRUE(IsForwardIteratorHelper(std::iterator_traits<
       Map<int, int>::const_iterator>::iterator_category()));
 }
 
-TEST_F(MapImplTest, InsertSingle) {
+TEST_P(MapImplTest, InsertSingle) {
   int32 key = 0;
   int32 value1 = 100;
   int32 value2 = 101;
@@ -335,7 +616,7 @@
   EXPECT_FALSE(result2.second);
 }
 
-TEST_F(MapImplTest, InsertByIterator) {
+TEST_P(MapImplTest, InsertByIterator) {
   int32 key1 = 0;
   int32 key2 = 1;
   int32 value1a = 100;
@@ -358,7 +639,7 @@
   ExpectElements(map1);
 }
 
-TEST_F(MapImplTest, EraseSingleByKey) {
+TEST_P(MapImplTest, EraseSingleByKey) {
   int32 key = 0;
   int32 value = 100;
 
@@ -376,7 +657,7 @@
   EXPECT_EQ(0, map_.erase(key));
 }
 
-TEST_F(MapImplTest, EraseMutipleByKey) {
+TEST_P(MapImplTest, EraseMutipleByKey) {
   // erase in one specific order to trigger corner cases
   for (int i = 0; i < 5; i++) {
     map_[i] = i;
@@ -403,7 +684,7 @@
   EXPECT_TRUE(map_.end() == map_.find(2));
 }
 
-TEST_F(MapImplTest, EraseSingleByIterator) {
+TEST_P(MapImplTest, EraseSingleByIterator) {
   int32 key = 0;
   int32 value = 100;
 
@@ -418,7 +699,7 @@
   EXPECT_TRUE(map_.begin() == map_.end());
 }
 
-TEST_F(MapImplTest, ValidIteratorAfterErase) {
+TEST_P(MapImplTest, ValidIteratorAfterErase) {
   for (int i = 0; i < 10; i++) {
     map_[i] = i;
   }
@@ -438,7 +719,7 @@
   EXPECT_EQ(5, map_.size());
 }
 
-TEST_F(MapImplTest, EraseByIterator) {
+TEST_P(MapImplTest, EraseByIterator) {
   int32 key1 = 0;
   int32 key2 = 1;
   int32 value1 = 100;
@@ -459,7 +740,7 @@
   EXPECT_TRUE(map_.begin() == map_.end());
 }
 
-TEST_F(MapImplTest, Clear) {
+TEST_P(MapImplTest, Clear) {
   int32 key = 0;
   int32 value = 100;
 
@@ -474,7 +755,7 @@
   EXPECT_TRUE(map_.begin() == map_.end());
 }
 
-TEST_F(MapImplTest, CopyConstructor) {
+static void CopyConstructorHelper(Arena* arena, Map<int32, int32>* m) {
   int32 key1 = 0;
   int32 key2 = 1;
   int32 value1 = 100;
@@ -484,16 +765,25 @@
   map[key1] = value1;
   map[key2] = value2;
 
-  map_.insert(map.begin(), map.end());
+  m->insert(map.begin(), map.end());
 
-  Map<int32, int32> other(map_);
+  Map<int32, int32> other(*m);
 
   EXPECT_EQ(2, other.size());
   EXPECT_EQ(value1, other.at(key1));
   EXPECT_EQ(value2, other.at(key2));
 }
 
-TEST_F(MapImplTest, IterConstructor) {
+TEST_P(MapImplTest, CopyConstructorWithArena) {
+  Arena a;
+  CopyConstructorHelper(&a, &map_);
+}
+
+TEST_P(MapImplTest, CopyConstructorWithoutArena) {
+  CopyConstructorHelper(NULL, &map_);
+}
+
+TEST_P(MapImplTest, IterConstructor) {
   int32 key1 = 0;
   int32 key2 = 1;
   int32 value1 = 100;
@@ -503,14 +793,15 @@
   map[key1] = value1;
   map[key2] = value2;
 
-  Map<int32, int32> new_map(map.begin(), map.end());
+  Map<int32, int32> new_map(map.begin(), map.end(),
+                            GetParam());
 
   EXPECT_EQ(2, new_map.size());
   EXPECT_EQ(value1, new_map.at(key1));
   EXPECT_EQ(value2, new_map.at(key2));
 }
 
-TEST_F(MapImplTest, Assigner) {
+TEST_P(MapImplTest, Assigner) {
   int32 key1 = 0;
   int32 key2 = 1;
   int32 value1 = 100;
@@ -522,7 +813,7 @@
 
   map_.insert(map.begin(), map.end());
 
-  Map<int32, int32> other;
+  Map<int32, int32> other(GetParam());
   int32 key_other = 123;
   int32 value_other = 321;
   other[key_other] = value_other;
@@ -540,9 +831,16 @@
   EXPECT_EQ(2, other.size());
   EXPECT_EQ(value1, other.at(key1));
   EXPECT_EQ(value2, other.at(key2));
+
+  // Try assignment to a map with a different choice of "style."
+  Map<int32, int32> m(!GetParam());
+  m = other;
+  EXPECT_EQ(2, m.size());
+  EXPECT_EQ(value1, m.at(key1));
+  EXPECT_EQ(value2, m.at(key2));
 }
 
-TEST_F(MapImplTest, Rehash) {
+TEST_P(MapImplTest, Rehash) {
   const int test_size = 50;
   std::map<int32, int32> reference_map;
   for (int i = 0; i < test_size; i++) {
@@ -559,7 +857,7 @@
   EXPECT_TRUE(map_.empty());
 }
 
-TEST_F(MapImplTest, EqualRange) {
+TEST_P(MapImplTest, EqualRange) {
   int key = 100, key_missing = 101;
   map_[key] = 100;
 
@@ -583,14 +881,14 @@
   EXPECT_TRUE(const_map_.end() == const_range.second);
 }
 
-TEST_F(MapImplTest, ConvertToStdMap) {
+TEST_P(MapImplTest, ConvertToStdMap) {
   map_[100] = 101;
   std::map<int32, int32> std_map(map_.begin(), map_.end());
   EXPECT_EQ(1, std_map.size());
   EXPECT_EQ(101, std_map[100]);
 }
 
-TEST_F(MapImplTest, ConvertToStdVectorOfPairs) {
+TEST_P(MapImplTest, ConvertToStdVectorOfPairs) {
   map_[100] = 101;
   std::vector<std::pair<int32, int32> > std_vec(map_.begin(), map_.end());
   EXPECT_EQ(1, std_vec.size());
@@ -598,6 +896,8 @@
   EXPECT_EQ(101, std_vec[0].second);
 }
 
+INSTANTIATE_TEST_CASE_P(BoolSequence, MapImplTest, testing::Bool());
+
 // Map Field Reflection Test ========================================
 
 static int Func(int i, int j) {
diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc
index 032748b..d62ca79 100644
--- a/src/google/protobuf/message.cc
+++ b/src/google/protobuf/message.cc
@@ -69,7 +69,7 @@
   GOOGLE_CHECK_EQ(from.GetDescriptor(), descriptor)
     << ": Tried to merge from a message with a different type.  "
        "to: " << descriptor->full_name() << ", "
-       "from:" << from.GetDescriptor()->full_name();
+       "from: " << from.GetDescriptor()->full_name();
   ReflectionOps::Merge(from, this);
 }
 
@@ -82,7 +82,7 @@
   GOOGLE_CHECK_EQ(from.GetDescriptor(), descriptor)
     << ": Tried to copy from a message with a different type. "
        "to: " << descriptor->full_name() << ", "
-       "from:" << from.GetDescriptor()->full_name();
+       "from: " << from.GetDescriptor()->full_name();
   ReflectionOps::Copy(from, this);
 }
 
diff --git a/src/google/protobuf/message_lite.cc b/src/google/protobuf/message_lite.cc
index 5bd8bcf..fe124c4 100644
--- a/src/google/protobuf/message_lite.cc
+++ b/src/google/protobuf/message_lite.cc
@@ -62,13 +62,15 @@
 // provide a useful error message.
 void ByteSizeConsistencyError(int byte_size_before_serialization,
                               int byte_size_after_serialization,
-                              int bytes_produced_by_serialization) {
+                              int bytes_produced_by_serialization,
+                              const MessageLite& message) {
   GOOGLE_CHECK_EQ(byte_size_before_serialization, byte_size_after_serialization)
-      << "Protocol message was modified concurrently during serialization.";
+      << message.GetTypeName()
+      << " was modified concurrently during serialization.";
   GOOGLE_CHECK_EQ(bytes_produced_by_serialization, byte_size_before_serialization)
       << "Byte size calculation and serialization were inconsistent.  This "
          "may indicate a bug in protocol buffers or it may be caused by "
-         "concurrent modification of the message.";
+         "concurrent modification of " << message.GetTypeName() << ".";
   GOOGLE_LOG(FATAL) << "This shouldn't be called if all the sizes are equal.";
 }
 
@@ -248,7 +250,7 @@
   if (buffer != NULL) {
     uint8* end = SerializeWithCachedSizesToArray(buffer);
     if (end - buffer != size) {
-      ByteSizeConsistencyError(size, ByteSize(), end - buffer);
+      ByteSizeConsistencyError(size, ByteSize(), end - buffer, *this);
     }
     return true;
   } else {
@@ -261,7 +263,7 @@
 
     if (final_byte_count - original_byte_count != size) {
       ByteSizeConsistencyError(size, ByteSize(),
-                               final_byte_count - original_byte_count);
+                               final_byte_count - original_byte_count, *this);
     }
 
     return true;
@@ -299,7 +301,7 @@
       reinterpret_cast<uint8*>(io::mutable_string_data(output) + old_size);
   uint8* end = SerializeWithCachedSizesToArray(start);
   if (end - start != byte_size) {
-    ByteSizeConsistencyError(byte_size, ByteSize(), end - start);
+    ByteSizeConsistencyError(byte_size, ByteSize(), end - start, *this);
   }
   return true;
 }
@@ -325,7 +327,7 @@
   uint8* start = reinterpret_cast<uint8*>(data);
   uint8* end = SerializeWithCachedSizesToArray(start);
   if (end - start != byte_size) {
-    ByteSizeConsistencyError(byte_size, ByteSize(), end - start);
+    ByteSizeConsistencyError(byte_size, ByteSize(), end - start, *this);
   }
   return true;
 }
diff --git a/src/google/protobuf/message_unittest.cc b/src/google/protobuf/message_unittest.cc
index 2d4780f..d668a1a 100644
--- a/src/google/protobuf/message_unittest.cc
+++ b/src/google/protobuf/message_unittest.cc
@@ -55,6 +55,7 @@
 
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
 
diff --git a/src/google/protobuf/metadata.h b/src/google/protobuf/metadata.h
index 219645d..fdee150 100644
--- a/src/google/protobuf/metadata.h
+++ b/src/google/protobuf/metadata.h
@@ -56,7 +56,7 @@
 // The tagged pointer uses the LSB to disambiguate cases, and uses bit 0 == 0 to
 // indicate an arena pointer and bit 0 == 1 to indicate a UFS+Arena-container
 // pointer.
-class InternalMetadataWithArena {
+class LIBPROTOBUF_EXPORT InternalMetadataWithArena {
  public:
   InternalMetadataWithArena() : ptr_(NULL) {}
   explicit InternalMetadataWithArena(Arena* arena)
diff --git a/src/google/protobuf/repeated_field.cc b/src/google/protobuf/repeated_field.cc
index 949e0a2..77004f5 100644
--- a/src/google/protobuf/repeated_field.cc
+++ b/src/google/protobuf/repeated_field.cc
@@ -52,8 +52,8 @@
   }
   Rep* old_rep = rep_;
   Arena* arena = GetArenaNoVirtual();
-  new_size = max(kMinRepeatedFieldAllocationSize,
-                 max(total_size_ * 2, new_size));
+  new_size = std::max(kMinRepeatedFieldAllocationSize,
+                      std::max(total_size_ * 2, new_size));
   GOOGLE_CHECK_LE(new_size,
            (std::numeric_limits<size_t>::max() - kRepHeaderSize) /
            sizeof(old_rep->elements[0]))
diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h
index 5447fa4..deeb7d5 100644
--- a/src/google/protobuf/repeated_field.h
+++ b/src/google/protobuf/repeated_field.h
@@ -244,7 +244,7 @@
   int total_size_;
   struct Rep {
     Arena* arena;
-    Element  elements[1];
+    Element elements[1];
   };
   // We can not use sizeof(Rep) - sizeof(Element) due to the trailing padding on
   // the struct. We can not use sizeof(Arena*) as well because there might be
@@ -272,6 +272,22 @@
   inline Arena* GetArenaNoVirtual() const {
     return (rep_ == NULL) ? NULL : rep_->arena;
   }
+
+  // Internal helper to delete all elements and deallocate the storage.
+  // If Element has a trivial destructor (for example, if it's a fundamental
+  // type, like int32), the loop will be removed by the optimizer.
+  void InternalDeallocate(Rep* rep, int size) {
+    if (rep != NULL) {
+      Element* e = &rep->elements[0];
+      Element* limit = &rep->elements[size];
+      for (; e < limit; e++) {
+        e->Element::~Element();
+      }
+      if (rep->arena == NULL) {
+        delete[] reinterpret_cast<char*>(rep);
+      }
+    }
+  }
 };
 
 template<typename Element>
@@ -836,6 +852,15 @@
   // Add an already-allocated object, skipping arena-ownership checks. The user
   // must guarantee that the given object is in the same arena as this
   // RepeatedPtrField.
+  // It is also useful in legacy code that uses temporary ownership to avoid
+  // copies. Example:
+  // RepeatedPtrField<T> temp_field;
+  // temp_field.AddAllocated(new T);
+  // ... // Do something with temp_field
+  // temp_field.ExtractSubrange(0, temp_field.size(), NULL);
+  // If you put temp_field on the arena this fails, because the ownership
+  // transfers to the arena at the "AddAllocated" call and is not released
+  // anymore causing a double delete. UnsafeArenaAddAllocated prevents this.
   void UnsafeArenaAddAllocated(Element* value);
 
   // Remove the last element and return it.  Works only when operating on an
@@ -992,19 +1017,8 @@
 template <typename Element>
 RepeatedField<Element>::~RepeatedField() {
   // See explanation in Reserve(): we need to invoke destructors here for the
-  // case that Element has a non-trivial destructor. If Element has a trivial
-  // destructor (for example, if it's a primitive type, like int32), this entire
-  // loop will be removed by the optimizer.
-  if (rep_ != NULL) {
-    Element* e = &rep_->elements[0];
-    Element* limit = &rep_->elements[total_size_];
-    for (; e < limit; e++) {
-      e->Element::~Element();
-    }
-    if (rep_->arena == NULL) {
-      delete[] reinterpret_cast<char*>(rep_);
-    }
-  }
+  // case that Element has a non-trivial destructor.
+  InternalDeallocate(rep_, total_size_);
 }
 
 template <typename Element>
@@ -1240,8 +1254,8 @@
   if (total_size_ >= new_size) return;
   Rep* old_rep = rep_;
   Arena* arena = GetArenaNoVirtual();
-  new_size = max(google::protobuf::internal::kMinRepeatedFieldAllocationSize,
-                 max(total_size_ * 2, new_size));
+  new_size = std::max(google::protobuf::internal::kMinRepeatedFieldAllocationSize,
+                      std::max(total_size_ * 2, new_size));
   GOOGLE_CHECK_LE(static_cast<size_t>(new_size),
            (std::numeric_limits<size_t>::max() - kRepHeaderSize) /
            sizeof(Element))
@@ -1274,18 +1288,10 @@
   if (current_size_ > 0) {
     MoveArray(rep_->elements, old_rep->elements, current_size_);
   }
-  if (old_rep) {
-    // Likewise, we need to invoke destructors on the old array. If Element has
-    // no destructor, this loop will disappear.
-    e = &old_rep->elements[0];
-    limit = &old_rep->elements[old_total_size];
-    for (; e < limit; e++) {
-      e->Element::~Element();
-    }
-    if (arena == NULL) {
-      delete[] reinterpret_cast<char*>(old_rep);
-    }
-  }
+
+  // Likewise, we need to invoke destructors on the old array.
+  InternalDeallocate(old_rep, old_total_size);
+
 }
 
 template <typename Element>
@@ -2380,6 +2386,37 @@
  private:
   RepeatedPtrField<T>* field_;
 };
+
+// Almost identical to AllocatedRepeatedPtrFieldBackInsertIterator. This one
+// uses the UnsafeArenaAddAllocated instead.
+template<typename T>
+class UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator
+    : public std::iterator<std::output_iterator_tag, T> {
+ public:
+  explicit UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator(
+    ::google::protobuf::RepeatedPtrField<T>* const mutable_field)
+  : field_(mutable_field) {
+  }
+  UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator<T>& operator=(
+    T const* const ptr_to_value) {
+    field_->UnsafeArenaAddAllocated(const_cast<T*>(ptr_to_value));
+    return *this;
+  }
+  UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator<T>& operator*() {
+    return *this;
+  }
+  UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator<T>& operator++() {
+    return *this;
+  }
+  UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator<T>& operator++(
+      int /* unused */) {
+    return *this;
+  }
+
+ private:
+  ::google::protobuf::RepeatedPtrField<T>* field_;
+};
+
 }  // namespace internal
 
 // Provides a back insert iterator for RepeatedField instances,
@@ -2414,6 +2451,25 @@
       mutable_field);
 }
 
+// Similar to AllocatedRepeatedPtrFieldBackInserter, using
+// UnsafeArenaAddAllocated instead of AddAllocated.
+// This is slightly faster if that matters. It is also useful in legacy code
+// that uses temporary ownership to avoid copies. Example:
+// RepeatedPtrField<T> temp_field;
+// temp_field.AddAllocated(new T);
+// ... // Do something with temp_field
+// temp_field.ExtractSubrange(0, temp_field.size(), NULL);
+// If you put temp_field on the arena this fails, because the ownership
+// transfers to the arena at the "AddAllocated" call and is not released anymore
+// causing a double delete. Using UnsafeArenaAddAllocated prevents this.
+template<typename T>
+internal::UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator<T>
+UnsafeArenaAllocatedRepeatedPtrFieldBackInserter(
+    ::google::protobuf::RepeatedPtrField<T>* const mutable_field) {
+  return internal::UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator<T>(
+      mutable_field);
+}
+
 }  // namespace protobuf
 
 }  // namespace google
diff --git a/src/google/protobuf/repeated_field_unittest.cc b/src/google/protobuf/repeated_field_unittest.cc
index b45664b..39b24b3 100644
--- a/src/google/protobuf/repeated_field_unittest.cc
+++ b/src/google/protobuf/repeated_field_unittest.cc
@@ -1522,6 +1522,44 @@
   EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString());
 }
 
+TEST_F(RepeatedFieldInsertionIteratorsTest,
+       UnsafeArenaAllocatedRepeatedPtrFieldWithStringIntData) {
+  vector<Nested*> data;
+  TestAllTypes goldenproto;
+  for (int i = 0; i < 10; ++i) {
+    Nested* new_data = new Nested;
+    new_data->set_bb(i);
+    data.push_back(new_data);
+
+    new_data = goldenproto.add_repeated_nested_message();
+    new_data->set_bb(i);
+  }
+  TestAllTypes testproto;
+  std::copy(data.begin(), data.end(),
+            UnsafeArenaAllocatedRepeatedPtrFieldBackInserter(
+                testproto.mutable_repeated_nested_message()));
+  EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString());
+}
+
+TEST_F(RepeatedFieldInsertionIteratorsTest,
+       UnsafeArenaAllocatedRepeatedPtrFieldWithString) {
+  vector<string*> data;
+  TestAllTypes goldenproto;
+  for (int i = 0; i < 10; ++i) {
+    string* new_data = new string;
+    *new_data = "name-" + SimpleItoa(i);
+    data.push_back(new_data);
+
+    new_data = goldenproto.add_repeated_string();
+    *new_data = "name-" + SimpleItoa(i);
+  }
+  TestAllTypes testproto;
+  std::copy(data.begin(), data.end(),
+            UnsafeArenaAllocatedRepeatedPtrFieldBackInserter(
+                testproto.mutable_repeated_string()));
+  EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString());
+}
+
 }  // namespace
 
 }  // namespace protobuf
diff --git a/src/google/protobuf/struct.pb.cc b/src/google/protobuf/struct.pb.cc
index e020597..9e5b086 100644
--- a/src/google/protobuf/struct.pb.cc
+++ b/src/google/protobuf/struct.pb.cc
@@ -166,9 +166,11 @@
     "\000\0220\n\nlist_value\030\006 \001(\0132\032.google.protobuf."
     "ListValueH\000B\006\n\004kind\"3\n\tListValue\022&\n\006valu"
     "es\030\001 \003(\0132\026.google.protobuf.Value*\033\n\tNull"
-    "Value\022\016\n\nNULL_VALUE\020\000BN\n\023com.google.prot"
-    "obufB\013StructProtoP\001\240\001\001\242\002\003GPB\252\002\036Google.Pr"
-    "otobuf.WellKnownTypesb\006proto3", 589);
+    "Value\022\016\n\nNULL_VALUE\020\000B\201\001\n\023com.google.pro"
+    "tobufB\013StructProtoP\001Z1github.com/golang/"
+    "protobuf/ptypes/struct;structpb\240\001\001\242\002\003GPB"
+    "\252\002\036Google.Protobuf.WellKnownTypesb\006proto"
+    "3", 641);
   ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
     "google/protobuf/struct.proto", &protobuf_RegisterTypes);
   Struct::default_instance_ = new Struct();
diff --git a/src/google/protobuf/struct.proto b/src/google/protobuf/struct.proto
index 8562e2c..beeba81 100644
--- a/src/google/protobuf/struct.proto
+++ b/src/google/protobuf/struct.proto
@@ -33,6 +33,7 @@
 package google.protobuf;
 
 option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option go_package = "github.com/golang/protobuf/ptypes/struct;structpb";
 option java_package = "com.google.protobuf";
 option java_outer_classname = "StructProto";
 option java_multiple_files = true;
@@ -49,7 +50,7 @@
 //
 // The JSON representation for `Struct` is JSON object.
 message Struct {
-  // Map of dynamically typed values.
+  // Unordered map of dynamically typed values.
   map<string, Value> fields = 1;
 }
 
diff --git a/src/google/protobuf/stubs/hash.h b/src/google/protobuf/stubs/hash.h
index 5833432..bbd8ee6 100755
--- a/src/google/protobuf/stubs/hash.h
+++ b/src/google/protobuf/stubs/hash.h
@@ -214,6 +214,8 @@
   hash_map(int a = 0, const HashFcn& b = HashFcn(),
            const EqualKey& c = EqualKey(),
            const Alloc& d = Alloc()) : BaseClass(b, d) {}
+
+  HashFcn hash_function() const { return HashFcn(); }
 };
 
 template <typename Key,
@@ -222,6 +224,8 @@
 class hash_set : public std::set<Key, HashFcn> {
  public:
   hash_set(int = 0) {}
+
+  HashFcn hash_function() const { return HashFcn(); }
 };
 
 #elif defined(_MSC_VER) && !defined(_STLPORT_VERSION)
@@ -257,6 +261,8 @@
   hash_map(int a = 0, const HashFcn& b = HashFcn(),
            const EqualKey& c = EqualKey(),
            const Alloc& d = Alloc()) : BaseClass(a, b, c, d) {}
+
+  HashFcn hash_function() const { return HashFcn(); }
 };
 
 template <typename Key, typename HashFcn = hash<Key>,
@@ -266,6 +272,8 @@
           Key, HashFcn, EqualKey> {
  public:
   hash_set(int = 0) {}
+
+  HashFcn hash_function() const { return HashFcn(); }
 };
 
 #else
@@ -315,6 +323,8 @@
   hash_map(int a = 0, const HashFcn& b = HashFcn(),
            const EqualKey& c = EqualKey(),
            const Alloc& d = Alloc()) : BaseClass(a, b, c, d) {}
+
+  HashFcn hash_function() const { return HashFcn(); }
 };
 
 template <typename Key, typename HashFcn = hash<Key>,
@@ -324,6 +334,8 @@
           Key, HashFcn, EqualKey> {
  public:
   hash_set(int = 0) {}
+
+  HashFcn hash_function() const { return HashFcn(); }
 };
 
 #endif  // !GOOGLE_PROTOBUF_MISSING_HASH
diff --git a/src/google/protobuf/stubs/logging.h b/src/google/protobuf/stubs/logging.h
index 3108db8..f69605d 100644
--- a/src/google/protobuf/stubs/logging.h
+++ b/src/google/protobuf/stubs/logging.h
@@ -174,7 +174,7 @@
 
 #ifdef NDEBUG
 
-#define GOOGLE_DLOG GOOGLE_LOG_IF(INFO, false)
+#define GOOGLE_DLOG(LEVEL) GOOGLE_LOG_IF(LEVEL, false)
 
 #define GOOGLE_DCHECK(EXPRESSION) while(false) GOOGLE_CHECK(EXPRESSION)
 #define GOOGLE_DCHECK_OK(E) GOOGLE_DCHECK(::google::protobuf::internal::IsOk(E))
diff --git a/src/google/protobuf/stubs/mathutil.h b/src/google/protobuf/stubs/mathutil.h
index 3a1ef8a..27956a8 100644
--- a/src/google/protobuf/stubs/mathutil.h
+++ b/src/google/protobuf/stubs/mathutil.h
@@ -83,7 +83,7 @@
     if (value == T(0) || ::google::protobuf::internal::IsNan<T>(value)) {
       return value;
     }
-    return value > T(0) ? value : -value;
+    return value > T(0) ? 1 : -1;
   }
 
   template<typename T>
diff --git a/src/google/protobuf/stubs/stringpiece.h b/src/google/protobuf/stubs/stringpiece.h
index ec3ffd5..9167165 100644
--- a/src/google/protobuf/stubs/stringpiece.h
+++ b/src/google/protobuf/stubs/stringpiece.h
@@ -435,6 +435,44 @@
 // allow StringPiece to be logged
 extern std::ostream& operator<<(std::ostream& o, StringPiece piece);
 
+namespace internal {
+// StringPiece is not a POD and can not be used in an union (pre C++11). We
+// need a POD version of it.
+struct StringPiecePod {
+  // Create from a StringPiece.
+  static StringPiecePod CreateFromStringPiece(StringPiece str) {
+    StringPiecePod pod;
+    pod.data_ = str.data();
+    pod.size_ = str.size();
+    return pod;
+  }
+
+  // Cast to StringPiece.
+  operator StringPiece() const { return StringPiece(data_, size_); }
+
+  bool operator==(const char* value) const {
+    return StringPiece(data_, size_) == StringPiece(value);
+  }
+
+  char operator[](stringpiece_ssize_type i) const {
+    assert(0 <= i);
+    assert(i < size_);
+    return data_[i];
+  }
+
+  const char* data() const { return data_; }
+
+  stringpiece_ssize_type size() const {
+    return size_;
+  }
+
+  std::string ToString() const { return std::string(data_, size_); }
+ private:
+  const char* data_;
+  stringpiece_ssize_type size_;
+};
+
+}  // namespace internal
 }  // namespace protobuf
 }  // namespace google
 
diff --git a/src/google/protobuf/stubs/strutil.h b/src/google/protobuf/stubs/strutil.h
index 27d4757..8bdd611 100644
--- a/src/google/protobuf/stubs/strutil.h
+++ b/src/google/protobuf/stubs/strutil.h
@@ -648,6 +648,9 @@
   AlphaNum(StringPiece str)
       : piece_data_(str.data()), piece_size_(str.size()) {}
 
+  AlphaNum(internal::StringPiecePod str)
+      : piece_data_(str.data()), piece_size_(str.size()) {}
+
   size_t size() const { return piece_size_; }
   const char *data() const { return piece_data_; }
 
@@ -847,6 +850,11 @@
 LIBPROTOBUF_EXPORT void WebSafeBase64Escape(const unsigned char* src, int szsrc,
                                             string* dest, bool do_padding);
 
+inline bool IsValidCodePoint(uint32 code_point) {
+  return code_point < 0xD800 ||
+         (code_point >= 0xE000 && code_point <= 0x10FFFF);
+}
+
 static const int UTFmax = 4;
 // ----------------------------------------------------------------------
 // EncodeAsUTF8Char()
diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc
index b0a5ce6..1ed7439 100644
--- a/src/google/protobuf/text_format.cc
+++ b/src/google/protobuf/text_format.cc
@@ -91,7 +91,10 @@
 string Message::DebugString() const {
   string debug_string;
 
-  TextFormat::PrintToString(*this, &debug_string);
+  TextFormat::Printer printer;
+  printer.SetExpandAny(true);
+
+  printer.PrintToString(*this, &debug_string);
 
   return debug_string;
 }
@@ -101,6 +104,7 @@
 
   TextFormat::Printer printer;
   printer.SetSingleLineMode(true);
+  printer.SetExpandAny(true);
 
   printer.PrintToString(*this, &debug_string);
   // Single line mode currently might have an extra space at the end.
@@ -117,6 +121,7 @@
 
   TextFormat::Printer printer;
   printer.SetUseUtf8StringEscaping(true);
+  printer.SetExpandAny(true);
 
   printer.PrintToString(*this, &debug_string);
 
@@ -1153,10 +1158,10 @@
   }
 
   // Print text to the output stream.
-  void Print(const char* text, int size) {
-    int pos = 0;  // The number of bytes we've written so far.
+  void Print(const char* text, size_t size) {
+    size_t pos = 0;  // The number of bytes we've written so far.
 
-    for (int i = 0; i < size; i++) {
+    for (size_t i = 0; i < size; i++) {
       if (text[i] == '\n') {
         // Saw newline.  If there is more text, we may need to insert an indent
         // here.  So, write what we have so far, including the '\n'.
@@ -1181,7 +1186,7 @@
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TextGenerator);
 
-  void Write(const char* data, int size) {
+  void Write(const char* data, size_t size) {
     if (failed_) return;
     if (size == 0) return;
 
diff --git a/src/google/protobuf/text_format_unittest.cc b/src/google/protobuf/text_format_unittest.cc
index 8d61be1..f97658f 100644
--- a/src/google/protobuf/text_format_unittest.cc
+++ b/src/google/protobuf/text_format_unittest.cc
@@ -44,6 +44,7 @@
 
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/testing/file.h>
 #include <google/protobuf/test_util.h>
 #include <google/protobuf/unittest.pb.h>
diff --git a/src/google/protobuf/timestamp.pb.cc b/src/google/protobuf/timestamp.pb.cc
index c1c4402..1393cc9 100644
--- a/src/google/protobuf/timestamp.pb.cc
+++ b/src/google/protobuf/timestamp.pb.cc
@@ -83,9 +83,10 @@
   ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
     "\n\037google/protobuf/timestamp.proto\022\017googl"
     "e.protobuf\"+\n\tTimestamp\022\017\n\007seconds\030\001 \001(\003"
-    "\022\r\n\005nanos\030\002 \001(\005BT\n\023com.google.protobufB\016"
-    "TimestampProtoP\001\240\001\001\370\001\001\242\002\003GPB\252\002\036Google.Pr"
-    "otobuf.WellKnownTypesb\006proto3", 189);
+    "\022\r\n\005nanos\030\002 \001(\005B\201\001\n\023com.google.protobufB"
+    "\016TimestampProtoP\001Z+github.com/golang/pro"
+    "tobuf/ptypes/timestamp\240\001\001\370\001\001\242\002\003GPB\252\002\036Goo"
+    "gle.Protobuf.WellKnownTypesb\006proto3", 235);
   ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
     "google/protobuf/timestamp.proto", &protobuf_RegisterTypes);
   Timestamp::default_instance_ = new Timestamp();
diff --git a/src/google/protobuf/timestamp.proto b/src/google/protobuf/timestamp.proto
index b51fc3f..7992a85 100644
--- a/src/google/protobuf/timestamp.proto
+++ b/src/google/protobuf/timestamp.proto
@@ -34,6 +34,7 @@
 
 option csharp_namespace = "Google.Protobuf.WellKnownTypes";
 option cc_enable_arenas = true;
+option go_package = "github.com/golang/protobuf/ptypes/timestamp";
 option java_package = "com.google.protobuf";
 option java_outer_classname = "TimestampProto";
 option java_multiple_files = true;
diff --git a/src/google/protobuf/unittest.proto b/src/google/protobuf/unittest.proto
index 85fe615..da56ae0 100644
--- a/src/google/protobuf/unittest.proto
+++ b/src/google/protobuf/unittest.proto
@@ -696,6 +696,7 @@
   }
 }
 
+
 // Test messages for packed fields
 
 message TestPackedTypes {
diff --git a/src/google/protobuf/unittest_lite.proto b/src/google/protobuf/unittest_lite.proto
index 662c0e4..41ed845 100644
--- a/src/google/protobuf/unittest_lite.proto
+++ b/src/google/protobuf/unittest_lite.proto
@@ -43,8 +43,10 @@
 
 // Same as TestAllTypes but with the lite runtime.
 message TestAllTypesLite {
+
   message NestedMessage {
     optional int32 bb = 1;
+    optional int64 cc = 2;
   }
 
   enum NestedEnum {
@@ -159,6 +161,7 @@
     NestedMessage oneof_nested_message = 112;
     string oneof_string = 113;
     bytes oneof_bytes = 114;
+    NestedMessage oneof_lazy_nested_message = 115 [lazy = true];
   }
 }
 
diff --git a/src/google/protobuf/util/field_comparator.h b/src/google/protobuf/util/field_comparator.h
index 8b83c69..1b4d65b 100644
--- a/src/google/protobuf/util/field_comparator.h
+++ b/src/google/protobuf/util/field_comparator.h
@@ -91,9 +91,9 @@
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldComparator);
 };
 
-// Basic implementation of FieldComparator.  Supports four modes of floating
+// Basic implementation of FieldComparator.  Supports three modes of floating
 // point value comparison: exact, approximate using MathUtil::AlmostEqual
-// method, and arbitrarilly precise using MathUtil::WithinFractionOrMargin.
+// method, and arbitrarily precise using MathUtil::WithinFractionOrMargin.
 class LIBPROTOBUF_EXPORT DefaultFieldComparator : public FieldComparator {
  public:
   enum FloatComparison {
diff --git a/src/google/protobuf/util/field_comparator_test.cc b/src/google/protobuf/util/field_comparator_test.cc
index 23f7d51..6fd631d 100644
--- a/src/google/protobuf/util/field_comparator_test.cc
+++ b/src/google/protobuf/util/field_comparator_test.cc
@@ -42,7 +42,6 @@
 // and the opensource version gtest.h header includes cmath transitively
 // somehow.
 #include <gtest/gtest.h>
-
 namespace google {
 namespace protobuf {
 namespace util {
diff --git a/src/google/protobuf/util/field_mask_util.cc b/src/google/protobuf/util/field_mask_util.cc
index c59f43a..547c9fb 100644
--- a/src/google/protobuf/util/field_mask_util.cc
+++ b/src/google/protobuf/util/field_mask_util.cc
@@ -52,6 +52,82 @@
   }
 }
 
+bool FieldMaskUtil::SnakeCaseToCamelCase(StringPiece input, string* output) {
+  output->clear();
+  bool after_underscore = false;
+  for (int i = 0; i < input.size(); ++i) {
+    if (input[i] >= 'A' && input[i] <= 'Z') {
+      // The field name must not contain uppercase letters.
+      return false;
+    }
+    if (after_underscore) {
+      if (input[i] >= 'a' && input[i] <= 'z') {
+        output->push_back(input[i] + 'A' - 'a');
+        after_underscore = false;
+      } else {
+        // The character after a "_" must be a lowercase letter.
+        return false;
+      }
+    } else if (input[i] == '_') {
+      after_underscore = true;
+    } else {
+      output->push_back(input[i]);
+    }
+  }
+  if (after_underscore) {
+    // Trailing "_".
+    return false;
+  }
+  return true;
+}
+
+bool FieldMaskUtil::CamelCaseToSnakeCase(StringPiece input, string* output) {
+  output->clear();
+  for (int i = 0; i < input.size(); ++i) {
+    if (input[i] == '_') {
+      // The field name must not contain "_"s.
+      return false;
+    }
+    if (input[i] >= 'A' && input[i] <= 'Z') {
+      output->push_back('_');
+      output->push_back(input[i] + 'a' - 'A');
+    } else {
+      output->push_back(input[i]);
+    }
+  }
+  return true;
+}
+
+bool FieldMaskUtil::ToJsonString(const FieldMask& mask, string* out) {
+  out->clear();
+  for (int i = 0; i < mask.paths_size(); ++i) {
+    const string& path = mask.paths(i);
+    string camelcase_path;
+    if (!SnakeCaseToCamelCase(path, &camelcase_path)) {
+      return false;
+    }
+    if (i > 0) {
+      out->push_back(',');
+    }
+    out->append(camelcase_path);
+  }
+  return true;
+}
+
+bool FieldMaskUtil::FromJsonString(StringPiece str, FieldMask* out) {
+  out->Clear();
+  vector<string> paths = Split(str, ",");
+  for (int i = 0; i < paths.size(); ++i) {
+    if (paths[i].empty()) continue;
+    string snakecase_path;
+    if (!CamelCaseToSnakeCase(paths[i], &snakecase_path)) {
+      return false;
+    }
+    out->add_paths(snakecase_path);
+  }
+  return true;
+}
+
 bool FieldMaskUtil::InternalIsValidPath(const Descriptor* descriptor,
                                         StringPiece path) {
   vector<string> parts = Split(path, ".");
diff --git a/src/google/protobuf/util/field_mask_util.h b/src/google/protobuf/util/field_mask_util.h
index 92f6989..644161b 100644
--- a/src/google/protobuf/util/field_mask_util.h
+++ b/src/google/protobuf/util/field_mask_util.h
@@ -45,11 +45,18 @@
   typedef google::protobuf::FieldMask FieldMask;
 
  public:
-  // Converts FieldMask to/from string, formatted according to proto3 JSON
-  // spec for FieldMask (e.g., "foo,bar,baz.quz").
+  // Converts FieldMask to/from string, formatted by separating each path
+  // with a comma (e.g., "foo_bar,baz.quz").
   static string ToString(const FieldMask& mask);
   static void FromString(StringPiece str, FieldMask* out);
 
+  // Converts FieldMask to/from string, formatted according to proto3 JSON
+  // spec for FieldMask (e.g., "fooBar,baz.quz"). If the field name is not
+  // style conforming (i.e., not snake_case when converted to string, or not
+  // camelCase when converted from string), the conversion will fail.
+  static bool ToJsonString(const FieldMask& mask, string* out);
+  static bool FromJsonString(StringPiece str, FieldMask* out);
+
   // Checks whether the given path is valid for type T.
   template <typename T>
   static bool IsValidPath(StringPiece path) {
@@ -105,6 +112,35 @@
                              const MergeOptions& options, Message* destination);
 
  private:
+  friend class SnakeCaseCamelCaseTest;
+  // Converts a field name from snake_case to camelCase:
+  //   1. Every character after "_" will be converted to uppercase.
+  //   2. All "_"s are removed.
+  // The conversion will fail if:
+  //   1. The field name contains uppercase letters.
+  //   2. Any character after a "_" is not a lowercase letter.
+  // If the conversion succeeds, it's guaranteed that the resulted
+  // camelCase name will yield the original snake_case name when
+  // converted using CamelCaseToSnakeCase().
+  //
+  // Note that the input can contain characters not allowed in C identifiers.
+  // For example, "foo_bar,baz_quz" will be converted to "fooBar,bazQuz"
+  // successfully.
+  static bool SnakeCaseToCamelCase(StringPiece input, string* output);
+  // Converts a field name from camelCase to snake_case:
+  //   1. Every uppercase letter is converted to lowercase with a additional
+  //      preceding "-".
+  // The conversion will fail if:
+  //   1. The field name contains "_"s.
+  // If the conversion succeeds, it's guaranteed that the resulted
+  // snake_case name will yield the original camelCase name when
+  // converted using SnakeCaseToCamelCase().
+  //
+  // Note that the input can contain characters not allowed in C identifiers.
+  // For example, "fooBar,bazQuz" will be converted to "foo_bar,baz_quz"
+  // successfully.
+  static bool CamelCaseToSnakeCase(StringPiece input, string* output);
+
   static bool InternalIsValidPath(const Descriptor* descriptor,
                                   StringPiece path);
 
diff --git a/src/google/protobuf/util/field_mask_util_test.cc b/src/google/protobuf/util/field_mask_util_test.cc
index a952325..b378785 100644
--- a/src/google/protobuf/util/field_mask_util_test.cc
+++ b/src/google/protobuf/util/field_mask_util_test.cc
@@ -30,6 +30,8 @@
 
 #include <google/protobuf/util/field_mask_util.h>
 
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
 #include <google/protobuf/field_mask.pb.h>
 #include <google/protobuf/unittest.pb.h>
 #include <google/protobuf/test_util.h>
@@ -38,8 +40,77 @@
 namespace google {
 namespace protobuf {
 namespace util {
+
+class SnakeCaseCamelCaseTest : public ::testing::Test {
+ protected:
+  string SnakeCaseToCamelCase(const string& input) {
+    string output;
+    if (FieldMaskUtil::SnakeCaseToCamelCase(input, &output)) {
+      return output;
+    } else {
+      return "#FAIL#";
+    }
+  }
+
+  string CamelCaseToSnakeCase(const string& input) {
+    string output;
+    if (FieldMaskUtil::CamelCaseToSnakeCase(input, &output)) {
+      return output;
+    } else {
+      return "#FAIL#";
+    }
+  }
+};
+
 namespace {
 
+TEST_F(SnakeCaseCamelCaseTest, SnakeToCamel) {
+  EXPECT_EQ("fooBar", SnakeCaseToCamelCase("foo_bar"));
+  EXPECT_EQ("FooBar", SnakeCaseToCamelCase("_foo_bar"));
+  EXPECT_EQ("foo3Bar", SnakeCaseToCamelCase("foo3_bar"));
+  // No uppercase letter is allowed.
+  EXPECT_EQ("#FAIL#", SnakeCaseToCamelCase("Foo"));
+  // Any character after a "_" must be a lowercase letter.
+  //   1. "_" cannot be followed by another "_".
+  //   2. "_" cannot be followed by a digit.
+  //   3. "_" cannot appear as the last character.
+  EXPECT_EQ("#FAIL#", SnakeCaseToCamelCase("foo__bar"));
+  EXPECT_EQ("#FAIL#", SnakeCaseToCamelCase("foo_3bar"));
+  EXPECT_EQ("#FAIL#", SnakeCaseToCamelCase("foo_bar_"));
+}
+
+TEST_F(SnakeCaseCamelCaseTest, CamelToSnake) {
+  EXPECT_EQ("foo_bar", CamelCaseToSnakeCase("fooBar"));
+  EXPECT_EQ("_foo_bar", CamelCaseToSnakeCase("FooBar"));
+  EXPECT_EQ("foo3_bar", CamelCaseToSnakeCase("foo3Bar"));
+  // "_"s are not allowed.
+  EXPECT_EQ("#FAIL#", CamelCaseToSnakeCase("foo_bar"));
+}
+
+TEST_F(SnakeCaseCamelCaseTest, RoundTripTest) {
+  // Enumerates all possible snake_case names and test that converting it to
+  // camelCase and then to snake_case again will yield the original name.
+  string name = "___abc123";
+  std::sort(name.begin(), name.end());
+  do {
+    string camelName = SnakeCaseToCamelCase(name);
+    if (camelName != "#FAIL#") {
+      EXPECT_EQ(name, CamelCaseToSnakeCase(camelName));
+    }
+  } while (std::next_permutation(name.begin(), name.end()));
+
+  // Enumerates all possible camelCase names and test that converting it to
+  // snake_case and then to camelCase again will yield the original name.
+  name = "abcABC123";
+  std::sort(name.begin(), name.end());
+  do {
+    string camelName = CamelCaseToSnakeCase(name);
+    if (camelName != "#FAIL#") {
+      EXPECT_EQ(name, SnakeCaseToCamelCase(camelName));
+    }
+  } while (std::next_permutation(name.begin(), name.end()));
+}
+
 using protobuf_unittest::TestAllTypes;
 using protobuf_unittest::NestedTestAllTypes;
 using google::protobuf::FieldMask;
@@ -47,20 +118,43 @@
 TEST(FieldMaskUtilTest, StringFormat) {
   FieldMask mask;
   EXPECT_EQ("", FieldMaskUtil::ToString(mask));
-  mask.add_paths("foo");
-  EXPECT_EQ("foo", FieldMaskUtil::ToString(mask));
-  mask.add_paths("bar");
-  EXPECT_EQ("foo,bar", FieldMaskUtil::ToString(mask));
+  mask.add_paths("foo_bar");
+  EXPECT_EQ("foo_bar", FieldMaskUtil::ToString(mask));
+  mask.add_paths("baz_quz");
+  EXPECT_EQ("foo_bar,baz_quz", FieldMaskUtil::ToString(mask));
 
   FieldMaskUtil::FromString("", &mask);
   EXPECT_EQ(0, mask.paths_size());
-  FieldMaskUtil::FromString("foo", &mask);
+  FieldMaskUtil::FromString("fooBar", &mask);
   EXPECT_EQ(1, mask.paths_size());
-  EXPECT_EQ("foo", mask.paths(0));
-  FieldMaskUtil::FromString("foo,bar", &mask);
+  EXPECT_EQ("fooBar", mask.paths(0));
+  FieldMaskUtil::FromString("fooBar,bazQuz", &mask);
   EXPECT_EQ(2, mask.paths_size());
-  EXPECT_EQ("foo", mask.paths(0));
-  EXPECT_EQ("bar", mask.paths(1));
+  EXPECT_EQ("fooBar", mask.paths(0));
+  EXPECT_EQ("bazQuz", mask.paths(1));
+}
+
+TEST(FieldMaskUtilTest, JsonStringFormat) {
+  FieldMask mask;
+  string value;
+  EXPECT_TRUE(FieldMaskUtil::ToJsonString(mask, &value));
+  EXPECT_EQ("", value);
+  mask.add_paths("foo_bar");
+  EXPECT_TRUE(FieldMaskUtil::ToJsonString(mask, &value));
+  EXPECT_EQ("fooBar", value);
+  mask.add_paths("bar_quz");
+  EXPECT_TRUE(FieldMaskUtil::ToJsonString(mask, &value));
+  EXPECT_EQ("fooBar,barQuz", value);
+
+  FieldMaskUtil::FromJsonString("", &mask);
+  EXPECT_EQ(0, mask.paths_size());
+  FieldMaskUtil::FromJsonString("fooBar", &mask);
+  EXPECT_EQ(1, mask.paths_size());
+  EXPECT_EQ("foo_bar", mask.paths(0));
+  FieldMaskUtil::FromJsonString("fooBar,bazQuz", &mask);
+  EXPECT_EQ(2, mask.paths_size());
+  EXPECT_EQ("foo_bar", mask.paths(0));
+  EXPECT_EQ("baz_quz", mask.paths(1));
 }
 
 TEST(FieldMaskUtilTest, TestIsVaildPath) {
diff --git a/src/google/protobuf/util/internal/constants.h b/src/google/protobuf/util/internal/constants.h
index 0cb8f6e..e556888 100644
--- a/src/google/protobuf/util/internal/constants.h
+++ b/src/google/protobuf/util/internal/constants.h
@@ -43,13 +43,23 @@
 const char kTypeServiceBaseUrl[] = "type.googleapis.com";
 
 // Format string for RFC3339 timestamp formatting.
-const char kRfc3339TimeFormat[] = "%Y-%m-%dT%H:%M:%S";
+const char kRfc3339TimeFormat[] = "%E4Y-%m-%dT%H:%M:%S";
 
-// Minimum seconds allowed in a google.protobuf.TimeStamp or Duration value.
-const int64 kMinSeconds = -315576000000;
+// Same as above, but the year value is not zero-padded i.e. this accepts
+// timestamps like "1-01-0001T23:59:59Z" instead of "0001-01-0001T23:59:59Z".
+const char kRfc3339TimeFormatNoPadding[] = "%Y-%m-%dT%H:%M:%S";
 
-// Maximum seconds allowed in a google.protobuf.TimeStamp or Duration value.
-const int64 kMaxSeconds = 315576000000;
+// Minimun seconds allowed in a google.protobuf.Timestamp value.
+const int64 kTimestampMinSeconds = -62135596800;
+
+// Maximum seconds allowed in a google.protobuf.Timestamp value.
+const int64 kTimestampMaxSeconds = 253402300799;
+
+// Minimum seconds allowed in a google.protobuf.Duration value.
+const int64 kDurationMinSeconds = -315576000000;
+
+// Maximum seconds allowed in a google.protobuf.Duration value.
+const int64 kDurationMaxSeconds = 315576000000;
 
 // Nano seconds in a second.
 const int32 kNanosPerSecond = 1000000000;
diff --git a/src/google/protobuf/util/internal/datapiece.cc b/src/google/protobuf/util/internal/datapiece.cc
index b557429..72c0aca 100644
--- a/src/google/protobuf/util/internal/datapiece.cc
+++ b/src/google/protobuf/util/internal/datapiece.cc
@@ -47,6 +47,7 @@
 using google::protobuf::EnumValueDescriptor;
 ;
 ;
+;
 using util::error::Code;
 using util::Status;
 using util::StatusOr;
@@ -248,11 +249,8 @@
   if (type_ == TYPE_BYTES) return str_.ToString();
   if (type_ == TYPE_STRING) {
     string decoded;
-    if (!WebSafeBase64Unescape(str_, &decoded)) {
-      if (!Base64Unescape(str_, &decoded)) {
-        return InvalidArgument(
-            ValueAsStringOrDefault("Invalid data in input."));
-      }
+    if (!DecodeBase64(str_, &decoded)) {
+      return InvalidArgument(ValueAsStringOrDefault("Invalid data in input."));
     }
     return decoded;
   } else {
@@ -313,11 +311,49 @@
 
 template <typename To>
 StatusOr<To> DataPiece::StringToNumber(bool (*func)(StringPiece, To*)) const {
+  if (str_.size() > 0 && (str_[0] == ' ' || str_[str_.size() - 1] == ' ')) {
+    return InvalidArgument(StrCat("\"", str_, "\""));
+  }
   To result;
   if (func(str_, &result)) return result;
   return InvalidArgument(StrCat("\"", str_.ToString(), "\""));
 }
 
+bool DataPiece::DecodeBase64(StringPiece src, string* dest) const {
+  // Try web-safe decode first, if it fails, try the non-web-safe decode.
+  if (WebSafeBase64Unescape(src, dest)) {
+    if (use_strict_base64_decoding_) {
+      // In strict mode, check if the escaped version gives us the same value as
+      // unescaped.
+      string encoded;
+      // WebSafeBase64Escape does no padding by default.
+      WebSafeBase64Escape(*dest, &encoded);
+      // Remove trailing padding '=' characters before comparison.
+      StringPiece src_no_padding(src, 0, src.ends_with("=")
+                                             ? src.find_last_not_of('=') + 1
+                                             : src.length());
+      return encoded == src_no_padding;
+    }
+    return true;
+  }
+
+  if (Base64Unescape(src, dest)) {
+    if (use_strict_base64_decoding_) {
+      string encoded;
+      Base64Escape(
+          reinterpret_cast<const unsigned char*>(dest->data()), dest->length(),
+          &encoded, false);
+      StringPiece src_no_padding(src, 0, src.ends_with("=")
+                                             ? src.find_last_not_of('=') + 1
+                                             : src.length());
+      return encoded == src_no_padding;
+    }
+    return true;
+  }
+
+  return false;
+}
+
 }  // namespace converter
 }  // namespace util
 }  // namespace protobuf
diff --git a/src/google/protobuf/util/internal/datapiece.h b/src/google/protobuf/util/internal/datapiece.h
index f22bfe7..8b2e35d 100644
--- a/src/google/protobuf/util/internal/datapiece.h
+++ b/src/google/protobuf/util/internal/datapiece.h
@@ -83,12 +83,15 @@
   explicit DataPiece(const double value) : type_(TYPE_DOUBLE), double_(value) {}
   explicit DataPiece(const float value) : type_(TYPE_FLOAT), float_(value) {}
   explicit DataPiece(const bool value) : type_(TYPE_BOOL), bool_(value) {}
-  explicit DataPiece(StringPiece value)
+  DataPiece(StringPiece value, bool use_strict_base64_decoding)
       : type_(TYPE_STRING),
-        str_(StringPiecePod::CreateFromStringPiece(value)) {}
+        str_(StringPiecePod::CreateFromStringPiece(value)),
+        use_strict_base64_decoding_(use_strict_base64_decoding) {}
   // Constructor for bytes. The second parameter is not used.
-  explicit DataPiece(StringPiece value, bool dummy)
-      : type_(TYPE_BYTES), str_(StringPiecePod::CreateFromStringPiece(value)) {}
+  DataPiece(StringPiece value, bool dummy, bool use_strict_base64_decoding)
+      : type_(TYPE_BYTES),
+        str_(StringPiecePod::CreateFromStringPiece(value)),
+        use_strict_base64_decoding_(use_strict_base64_decoding) {}
   DataPiece(const DataPiece& r) : type_(r.type_), str_(r.str_) {}
   DataPiece& operator=(const DataPiece& x) {
     type_ = x.type_;
@@ -165,32 +168,13 @@
   template <typename To>
   util::StatusOr<To> StringToNumber(bool (*func)(StringPiece, To*)) const;
 
+  // Decodes a base64 string. Returns true on success.
+  bool DecodeBase64(StringPiece src, string* dest) const;
+
   // Data type for this piece of data.
   Type type_;
 
-  // StringPiece is not a POD and can not be used in an union (pre C++11). We
-  // need a POD version of it.
-  struct StringPiecePod {
-    const char* data;
-    int size;
-
-    // Create from a StringPiece.
-    static StringPiecePod CreateFromStringPiece(StringPiece str) {
-      StringPiecePod pod;
-      pod.data = str.data();
-      pod.size = str.size();
-      return pod;
-    }
-
-    // Cast to StringPiece.
-    operator StringPiece() const { return StringPiece(data, size); }
-
-    bool operator==(const char* value) const {
-      return StringPiece(data, size) == StringPiece(value);
-    }
-
-    string ToString() const { return string(data, size); }
-  };
+  typedef ::google::protobuf::internal::StringPiecePod StringPiecePod;
 
   // Stored piece of data.
   union {
@@ -203,6 +187,9 @@
     bool bool_;
     StringPiecePod str_;
   };
+
+  // Uses a stricter version of base64 decoding for byte fields.
+  bool use_strict_base64_decoding_;
 };
 
 }  // namespace converter
diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.cc b/src/google/protobuf/util/internal/default_value_objectwriter.cc
index a63e560..21d7a2e 100644
--- a/src/google/protobuf/util/internal/default_value_objectwriter.cc
+++ b/src/google/protobuf/util/internal/default_value_objectwriter.cc
@@ -51,7 +51,7 @@
 T ConvertTo(StringPiece value, StatusOr<T> (DataPiece::*converter_fn)() const,
             T default_value) {
   if (value.empty()) return default_value;
-  StatusOr<T> result = (DataPiece(value).*converter_fn)();
+  StatusOr<T> result = (DataPiece(value, true).*converter_fn)();
   return result.ok() ? result.ValueOrDie() : default_value;
 }
 }  // namespace
@@ -64,6 +64,7 @@
       type_(type),
       current_(NULL),
       root_(NULL),
+      field_scrub_callback_(NULL),
       ow_(ow) {}
 
 DefaultValueObjectWriter::~DefaultValueObjectWriter() {
@@ -153,7 +154,7 @@
     // Since StringPiece is essentially a pointer, takes a copy of "value" to
     // avoid ownership issues.
     string_values_.push_back(new string(value.ToString()));
-    RenderDataPiece(name, DataPiece(*string_values_.back()));
+    RenderDataPiece(name, DataPiece(*string_values_.back(), true));
   }
   return this;
 }
@@ -163,7 +164,7 @@
   if (current_ == NULL) {
     ow_->RenderBytes(name, value);
   } else {
-    RenderDataPiece(name, DataPiece(value));
+    RenderDataPiece(name, DataPiece(value, false, true));
   }
   return this;
 }
@@ -178,16 +179,25 @@
   return this;
 }
 
+void DefaultValueObjectWriter::RegisterFieldScrubCallBack(
+    FieldScrubCallBackPtr field_scrub_callback) {
+  field_scrub_callback_.reset(field_scrub_callback.release());
+}
+
 DefaultValueObjectWriter::Node::Node(const string& name,
                                      const google::protobuf::Type* type,
                                      NodeKind kind, const DataPiece& data,
-                                     bool is_placeholder)
+                                     bool is_placeholder,
+                                     const vector<string>& path,
+                                     FieldScrubCallBack* field_scrub_callback)
     : name_(name),
       type_(type),
       kind_(kind),
       is_any_(false),
       data_(data),
-      is_placeholder_(is_placeholder) {}
+      is_placeholder_(is_placeholder),
+      path_(path),
+      field_scrub_callback_(field_scrub_callback) {}
 
 DefaultValueObjectWriter::Node* DefaultValueObjectWriter::Node::FindChild(
     StringPiece name) {
@@ -291,6 +301,19 @@
 
   for (int i = 0; i < type_->fields_size(); ++i) {
     const google::protobuf::Field& field = type_->fields(i);
+
+    // This code is checking if the field to be added to the tree should be
+    // scrubbed or not by calling the field_scrub_callback_ callback function.
+    vector<string> path;
+    if (!path_.empty()) {
+      path.insert(path.begin(), path_.begin(), path_.end());
+    }
+    path.push_back(field.name());
+    if (field_scrub_callback_ != NULL &&
+        field_scrub_callback_->Run(path, &field)) {
+      continue;
+    }
+
     hash_map<string, int>::iterator found =
         orig_children_map.find(field.name());
     // If the child field has already been set, we just add it to the new list
@@ -343,7 +366,7 @@
         field.json_name(), field_type, kind,
         kind == PRIMITIVE ? CreateDefaultDataPieceForField(field, typeinfo)
                           : DataPiece::NullData(),
-        true));
+        true, path, field_scrub_callback_));
     new_children.push_back(child.release());
   }
   // Adds all leftover nodes in children_ to the beginning of new_child.
@@ -368,7 +391,8 @@
 
 DataPiece DefaultValueObjectWriter::FindEnumDefault(
     const google::protobuf::Field& field, const TypeInfo* typeinfo) {
-  if (!field.default_value().empty()) return DataPiece(field.default_value());
+  if (!field.default_value().empty())
+    return DataPiece(field.default_value(), true);
 
   const google::protobuf::Enum* enum_type =
       typeinfo->GetEnumByTypeUrl(field.type_url());
@@ -379,7 +403,7 @@
   }
   // We treat the first value as the default if none is specified.
   return enum_type->enumvalue_size() > 0
-             ? DataPiece(enum_type->enumvalue(0).name())
+             ? DataPiece(enum_type->enumvalue(0).name(), true)
              : DataPiece::NullData();
 }
 
@@ -416,10 +440,10 @@
           ConvertTo<bool>(field.default_value(), &DataPiece::ToBool, false));
     }
     case google::protobuf::Field_Kind_TYPE_STRING: {
-      return DataPiece(field.default_value());
+      return DataPiece(field.default_value(), true);
     }
     case google::protobuf::Field_Kind_TYPE_BYTES: {
-      return DataPiece(field.default_value(), false);
+      return DataPiece(field.default_value(), false, true);
     }
     case google::protobuf::Field_Kind_TYPE_UINT32:
     case google::protobuf::Field_Kind_TYPE_FIXED32: {
@@ -436,8 +460,9 @@
 DefaultValueObjectWriter* DefaultValueObjectWriter::StartObject(
     StringPiece name) {
   if (current_ == NULL) {
+    vector<string> path;
     root_.reset(new Node(name.ToString(), &type_, OBJECT, DataPiece::NullData(),
-                         false));
+                         false, path, field_scrub_callback_.get()));
     root_->PopulateChildren(typeinfo_);
     current_ = root_.get();
     return this;
@@ -451,7 +476,9 @@
         name.ToString(), ((current_->kind() == LIST || current_->kind() == MAP)
                               ? current_->type()
                               : NULL),
-        OBJECT, DataPiece::NullData(), false));
+        OBJECT, DataPiece::NullData(), false,
+        child == NULL ? current_->path() : child->path(),
+        field_scrub_callback_.get()));
     child = node.get();
     current_->AddChild(node.release());
   }
@@ -480,8 +507,9 @@
 DefaultValueObjectWriter* DefaultValueObjectWriter::StartList(
     StringPiece name) {
   if (current_ == NULL) {
-    root_.reset(
-        new Node(name.ToString(), &type_, LIST, DataPiece::NullData(), false));
+    vector<string> path;
+    root_.reset(new Node(name.ToString(), &type_, LIST, DataPiece::NullData(),
+                         false, path, field_scrub_callback_.get()));
     current_ = root_.get();
     return this;
   }
@@ -489,7 +517,9 @@
   Node* child = current_->FindChild(name);
   if (child == NULL || child->kind() != LIST) {
     google::protobuf::scoped_ptr<Node> node(
-        new Node(name.ToString(), NULL, LIST, DataPiece::NullData(), false));
+        new Node(name.ToString(), NULL, LIST, DataPiece::NullData(), false,
+                 child == NULL ? current_->path() : child->path(),
+                 field_scrub_callback_.get()));
     child = node.get();
     current_->AddChild(node.release());
   }
@@ -545,7 +575,9 @@
   if (child == NULL || child->kind() != PRIMITIVE) {
     // No children are found, creates a new child.
     google::protobuf::scoped_ptr<Node> node(
-        new Node(name.ToString(), NULL, PRIMITIVE, data, false));
+        new Node(name.ToString(), NULL, PRIMITIVE, data, false,
+                 child == NULL ? current_->path() : child->path(),
+                 field_scrub_callback_.get()));
     child = node.get();
     current_->AddChild(node.release());
   } else {
diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.h b/src/google/protobuf/util/internal/default_value_objectwriter.h
index 695b9dd..1d85bed 100644
--- a/src/google/protobuf/util/internal/default_value_objectwriter.h
+++ b/src/google/protobuf/util/internal/default_value_objectwriter.h
@@ -38,6 +38,7 @@
 #include <stack>
 #include <vector>
 
+#include <google/protobuf/stubs/callback.h>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/util/internal/type_info.h>
 #include <google/protobuf/util/internal/datapiece.h>
@@ -59,6 +60,25 @@
 // with their default values (0 for numbers, "" for strings, etc).
 class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter {
  public:
+  // A Callback function to check whether a field needs to be scrubbed.
+  //
+  // Returns true if the field should not be present in the output. Returns
+  // false otherwise.
+  //
+  // The 'path' parameter is a vector of path to the field from root. For
+  // example: if a nested field "a.b.c" (b is the parent message field of c and
+  // a is the parent message field of b), then the vector should contain { "a",
+  // "b", "c" }.
+  //
+  // The Field* should point to the google::protobuf::Field of "c".
+  typedef ResultCallback2<bool /*return*/,
+                          const std::vector<string>& /*path of the field*/,
+                          const google::protobuf::Field* /*field*/>
+      FieldScrubCallBack;
+
+  // A unique pointer to a DefaultValueObjectWriter::FieldScrubCallBack.
+  typedef google::protobuf::scoped_ptr<FieldScrubCallBack> FieldScrubCallBackPtr;
+
   DefaultValueObjectWriter(TypeResolver* type_resolver,
                            const google::protobuf::Type& type,
                            ObjectWriter* ow);
@@ -98,6 +118,10 @@
 
   virtual DefaultValueObjectWriter* RenderNull(StringPiece name);
 
+  // Register the callback for scrubbing of fields. Owership of
+  // field_scrub_callback pointer is also transferred to this class
+  void RegisterFieldScrubCallBack(FieldScrubCallBackPtr field_scrub_callback);
+
  private:
   enum NodeKind {
     PRIMITIVE = 0,
@@ -111,7 +135,8 @@
   class LIBPROTOBUF_EXPORT Node {
    public:
     Node(const string& name, const google::protobuf::Type* type, NodeKind kind,
-         const DataPiece& data, bool is_placeholder);
+         const DataPiece& data, bool is_placeholder, const vector<string>& path,
+         FieldScrubCallBack* field_scrub_callback);
     virtual ~Node() {
       for (int i = 0; i < children_.size(); ++i) {
         delete children_[i];
@@ -137,17 +162,19 @@
     // Accessors
     const string& name() const { return name_; }
 
-    const google::protobuf::Type* type() { return type_; }
+    const vector<string>& path() const { return path_; }
+
+    const google::protobuf::Type* type() const { return type_; }
 
     void set_type(const google::protobuf::Type* type) { type_ = type; }
 
-    NodeKind kind() { return kind_; }
+    NodeKind kind() const { return kind_; }
 
-    int number_of_children() { return children_.size(); }
+    int number_of_children() const { return children_.size(); }
 
     void set_data(const DataPiece& data) { data_ = data; }
 
-    bool is_any() { return is_any_; }
+    bool is_any() const { return is_any_; }
 
     void set_is_any(bool is_any) { is_any_ = is_any; }
 
@@ -181,6 +208,15 @@
     // the parent node's StartObject()/StartList() method is called with this
     // node's name.
     bool is_placeholder_;
+
+    // Path of the field of this node
+    std::vector<string> path_;
+
+    // Pointer to function for determining whether a field needs to be scrubbed
+    // or not. This callback is owned by the creator of this node.
+    FieldScrubCallBack* field_scrub_callback_;
+
+    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Node);
   };
 
   // Populates children of "node" if it is an "any" Node and its real type has
@@ -221,6 +257,10 @@
   // The stack to hold the path of Nodes from current_ to root_;
   std::stack<Node*> stack_;
 
+  // Unique Pointer to function for determining whether a field needs to be
+  // scrubbed or not.
+  FieldScrubCallBackPtr field_scrub_callback_;
+
   ObjectWriter* ow_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DefaultValueObjectWriter);
diff --git a/src/google/protobuf/util/internal/json_objectwriter.cc b/src/google/protobuf/util/internal/json_objectwriter.cc
index 94d2ab7..b84210c 100644
--- a/src/google/protobuf/util/internal/json_objectwriter.cc
+++ b/src/google/protobuf/util/internal/json_objectwriter.cc
@@ -46,6 +46,7 @@
 namespace converter {
 
 using strings::ArrayByteSource;
+;
 
 JsonObjectWriter::~JsonObjectWriter() {
   if (!element_->is_root()) {
@@ -81,13 +82,11 @@
   return this;
 }
 
-JsonObjectWriter* JsonObjectWriter::RenderBool(StringPiece name,
-                                               bool value) {
+JsonObjectWriter* JsonObjectWriter::RenderBool(StringPiece name, bool value) {
   return RenderSimple(name, value ? "true" : "false");
 }
 
-JsonObjectWriter* JsonObjectWriter::RenderInt32(StringPiece name,
-                                                int32 value) {
+JsonObjectWriter* JsonObjectWriter::RenderInt32(StringPiece name, int32 value) {
   return RenderSimple(name, SimpleItoa(value));
 }
 
@@ -96,8 +95,7 @@
   return RenderSimple(name, SimpleItoa(value));
 }
 
-JsonObjectWriter* JsonObjectWriter::RenderInt64(StringPiece name,
-                                                int64 value) {
+JsonObjectWriter* JsonObjectWriter::RenderInt64(StringPiece name, int64 value) {
   WritePrefix(name);
   WriteChar('"');
   stream_->WriteString(SimpleItoa(value));
@@ -124,8 +122,7 @@
   return RenderString(name, DoubleAsString(value));
 }
 
-JsonObjectWriter* JsonObjectWriter::RenderFloat(StringPiece name,
-                                                float value) {
+JsonObjectWriter* JsonObjectWriter::RenderFloat(StringPiece name, float value) {
   if (MathLimits<float>::IsFinite(value)) {
     return RenderSimple(name, SimpleFtoa(value));
   }
@@ -148,7 +145,12 @@
                                                 StringPiece value) {
   WritePrefix(name);
   string base64;
-  Base64Escape(value, &base64);
+
+  if (use_websafe_base64_for_bytes_)
+    WebSafeBase64Escape(value.ToString(), &base64);
+  else
+    Base64Escape(value, &base64);
+
   WriteChar('"');
   // TODO(wpoon): Consider a ByteSink solution that writes the base64 bytes
   //              directly to the stream, rather than first putting them
diff --git a/src/google/protobuf/util/internal/json_objectwriter.h b/src/google/protobuf/util/internal/json_objectwriter.h
index 761a0a1..cb7e2fb 100644
--- a/src/google/protobuf/util/internal/json_objectwriter.h
+++ b/src/google/protobuf/util/internal/json_objectwriter.h
@@ -90,9 +90,10 @@
   JsonObjectWriter(StringPiece indent_string,
                    google::protobuf::io::CodedOutputStream* out)
       : element_(new Element(NULL)),
-        stream_(out), sink_(out),
-        indent_string_(indent_string.ToString()) {
-  }
+        stream_(out),
+        sink_(out),
+        indent_string_(indent_string.ToString()),
+        use_websafe_base64_for_bytes_(false) {}
   virtual ~JsonObjectWriter();
 
   // ObjectWriter methods.
@@ -111,6 +112,10 @@
   virtual JsonObjectWriter* RenderBytes(StringPiece name, StringPiece value);
   virtual JsonObjectWriter* RenderNull(StringPiece name);
 
+  void set_use_websafe_base64_for_bytes(bool value) {
+    use_websafe_base64_for_bytes_ = value;
+  }
+
  protected:
   class LIBPROTOBUF_EXPORT Element : public BaseElement {
    public:
@@ -195,6 +200,10 @@
   ByteSinkWrapper sink_;
   const string indent_string_;
 
+  // Whether to use regular or websafe base64 encoding for byte fields. Defaults
+  // to regular base64 encoding.
+  bool use_websafe_base64_for_bytes_;
+
   GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(JsonObjectWriter);
 };
 
diff --git a/src/google/protobuf/util/internal/json_objectwriter_test.cc b/src/google/protobuf/util/internal/json_objectwriter_test.cc
index 9d82016..b87b06a 100644
--- a/src/google/protobuf/util/internal/json_objectwriter_test.cc
+++ b/src/google/protobuf/util/internal/json_objectwriter_test.cc
@@ -58,7 +58,7 @@
   string output_;
   StringOutputStream* const str_stream_;
   CodedOutputStream* const out_stream_;
-  ObjectWriter* ow_;
+  JsonObjectWriter* ow_;
 };
 
 TEST_F(JsonObjectWriterTest, EmptyRootObject) {
@@ -283,6 +283,30 @@
       output_.substr(0, out_stream_->ByteCount()));
 }
 
+TEST_F(JsonObjectWriterTest, TestRegularByteEncoding) {
+  ow_ = new JsonObjectWriter("", out_stream_);
+  ow_->StartObject("")
+      ->RenderBytes("bytes", "\x03\xef\xc0")
+      ->EndObject();
+
+  // Test that we get regular (non websafe) base64 encoding on byte fields by
+  // default.
+  EXPECT_EQ("{\"bytes\":\"A+/A\"}",
+            output_.substr(0, out_stream_->ByteCount()));
+}
+
+TEST_F(JsonObjectWriterTest, TestWebsafeByteEncoding) {
+  ow_ = new JsonObjectWriter("", out_stream_);
+  ow_->set_use_websafe_base64_for_bytes(true);
+  ow_->StartObject("")
+      ->RenderBytes("bytes", "\x03\xef\xc0")
+      ->EndObject();
+
+  // Test that we get websafe base64 encoding when explicitly asked.
+  EXPECT_EQ("{\"bytes\":\"A-_A\"}",
+            output_.substr(0, out_stream_->ByteCount()));
+}
+
 }  // namespace converter
 }  // namespace util
 }  // namespace protobuf
diff --git a/src/google/protobuf/util/internal/json_stream_parser.cc b/src/google/protobuf/util/internal/json_stream_parser.cc
index df91675..39be7b0 100644
--- a/src/google/protobuf/util/internal/json_stream_parser.cc
+++ b/src/google/protobuf/util/internal/json_stream_parser.cc
@@ -42,8 +42,9 @@
 
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/util/internal/object_writer.h>
+#include <google/protobuf/util/internal/json_escaping.h>
+#include <google/protobuf/stubs/strutil.h>
 
 namespace google {
 namespace protobuf {
@@ -59,7 +60,7 @@
 
 namespace converter {
 
-// Number of digits in a unicode escape sequence (/uXXXX)
+// Number of digits in an escaped UTF-16 code unit ('\\' 'u' X X X X)
 static const int kUnicodeEscapedLength = 6;
 
 // Length of the true, false, and null literals.
@@ -419,9 +420,45 @@
     }
     code = (code << 4) + hex_digit_to_int(p_.data()[i]);
   }
+  if (code >= JsonEscaping::kMinHighSurrogate &&
+      code <= JsonEscaping::kMaxHighSurrogate) {
+    if (p_.length() < 2 * kUnicodeEscapedLength) {
+      if (!finishing_) {
+        return util::Status::CANCELLED;
+      }
+      if (!coerce_to_utf8_) {
+        return ReportFailure("Missing low surrogate.");
+      }
+    } else if (p_.data()[kUnicodeEscapedLength] == '\\' &&
+               p_.data()[kUnicodeEscapedLength + 1] == 'u') {
+      uint32 low_code = 0;
+      for (int i = kUnicodeEscapedLength + 2; i < 2 * kUnicodeEscapedLength;
+           ++i) {
+        if (!isxdigit(p_.data()[i])) {
+          return ReportFailure("Invalid escape sequence.");
+        }
+        low_code = (low_code << 4) + hex_digit_to_int(p_.data()[i]);
+      }
+      if (low_code >= JsonEscaping::kMinLowSurrogate &&
+          low_code <= JsonEscaping::kMaxLowSurrogate) {
+        // Convert UTF-16 surrogate pair to 21-bit Unicode codepoint.
+        code = (((code & 0x3FF) << 10) | (low_code & 0x3FF)) +
+               JsonEscaping::kMinSupplementaryCodePoint;
+        // Advance past the first code unit escape.
+        p_.remove_prefix(kUnicodeEscapedLength);
+      } else if (!coerce_to_utf8_) {
+        return ReportFailure("Invalid low surrogate.");
+      }
+    } else if (!coerce_to_utf8_) {
+      return ReportFailure("Missing low surrogate.");
+    }
+  }
+  if (!coerce_to_utf8_ && !IsValidCodePoint(code)) {
+    return ReportFailure("Invalid unicode code point.");
+  }
   char buf[UTFmax];
   int len = EncodeAsUTF8Char(code, buf);
-  // Advance past the unicode escape.
+  // Advance past the [final] code unit escape.
   p_.remove_prefix(kUnicodeEscapedLength);
   parsed_storage_.append(buf, len);
   return util::Status::OK;
@@ -473,7 +510,7 @@
       floating = true;
       continue;
     }
-    if (c == '+' || c == '-') continue;
+    if (c == '+' || c == '-' || c == 'x') continue;
     // Not a valid number character, break out.
     break;
   }
@@ -499,6 +536,10 @@
 
   // Positive non-floating point number, parse as a uint64.
   if (!negative) {
+    // Octal/Hex numbers are not valid JSON values.
+    if (number.length() >= 2 && number[0] == '0') {
+      return ReportFailure("Octal/hex numbers are not valid JSON values.");
+    }
     if (!safe_strtou64(number, &result->uint_val)) {
       return ReportFailure("Unable to parse number.");
     }
@@ -507,6 +548,10 @@
     return util::Status::OK;
   }
 
+  // Octal/Hex numbers are not valid JSON values.
+  if (number.length() >= 3 && number[1] == '0') {
+    return ReportFailure("Octal/hex numbers are not valid JSON values.");
+  }
   // Negative non-floating point number, parse as an int64.
   if (!safe_strto64(number, &result->int_val)) {
     return ReportFailure("Unable to parse number.");
@@ -677,8 +722,9 @@
   static const int kContextLength = 20;
   const char* p_start = p_.data();
   const char* json_start = json_.data();
-  const char* begin = max(p_start - kContextLength, json_start);
-  const char* end = min(p_start + kContextLength, json_start + json_.size());
+  const char* begin = std::max(p_start - kContextLength, json_start);
+  const char* end =
+      std::min(p_start + kContextLength, json_start + json_.size());
   StringPiece segment(begin, end - begin);
   string location(p_start - begin, ' ');
   location.push_back('^');
@@ -706,8 +752,8 @@
 void JsonStreamParser::Advance() {
   // Advance by moving one UTF8 character while making sure we don't go beyond
   // the length of StringPiece.
-  p_.remove_prefix(
-      min<int>(p_.length(), UTF8FirstLetterNumBytes(p_.data(), p_.length())));
+  p_.remove_prefix(std::min<int>(
+      p_.length(), UTF8FirstLetterNumBytes(p_.data(), p_.length())));
 }
 
 util::Status JsonStreamParser::ParseKey() {
diff --git a/src/google/protobuf/util/internal/json_stream_parser_test.cc b/src/google/protobuf/util/internal/json_stream_parser_test.cc
index 3414826..4b69110 100644
--- a/src/google/protobuf/util/internal/json_stream_parser_test.cc
+++ b/src/google/protobuf/util/internal/json_stream_parser_test.cc
@@ -124,8 +124,9 @@
     EXPECT_OK(result);
   }
 
-  void DoErrorTest(StringPiece json, int split, StringPiece error_prefix) {
-    util::Status result = RunTest(json, split);
+  void DoErrorTest(StringPiece json, int split, StringPiece error_prefix,
+                   bool coerce_utf8 = false) {
+    util::Status result = RunTest(json, split, coerce_utf8);
     EXPECT_EQ(util::error::INVALID_ARGUMENT, result.error_code());
     StringPiece error_message(result.error_message());
     EXPECT_EQ(error_prefix, error_message.substr(0, error_prefix.size()));
@@ -230,6 +231,32 @@
   }
 }
 
+TEST_F(JsonStreamParserTest, OctalNumberIsInvalid) {
+  StringPiece str = "01234";
+  for (int i = 0; i <= str.length(); ++i) {
+    DoErrorTest(str, i, "Octal/hex numbers are not valid JSON values.");
+  }
+  str = "-01234";
+  for (int i = 0; i <= str.length(); ++i) {
+    DoErrorTest(str, i, "Octal/hex numbers are not valid JSON values.");
+  }
+}
+
+TEST_F(JsonStreamParserTest, HexNumberIsInvalid) {
+  StringPiece str = "0x1234";
+  for (int i = 0; i <= str.length(); ++i) {
+    DoErrorTest(str, i, "Octal/hex numbers are not valid JSON values.");
+  }
+  str = "-0x1234";
+  for (int i = 0; i <= str.length(); ++i) {
+    DoErrorTest(str, i, "Octal/hex numbers are not valid JSON values.");
+  }
+  str = "12x34";
+  for (int i = 0; i <= str.length(); ++i) {
+    DoErrorTest(str, i, "Unable to parse number.");
+  }
+}
+
 // - single and double quoted strings
 TEST_F(JsonStreamParserTest, EmptyDoubleQuotedString) {
   StringPiece str = "\"\"";
@@ -351,19 +378,62 @@
   DoErrorTest("\xFF{}", 0, "Encountered non UTF-8 code points.");
 }
 
-#ifndef _MSC_VER
 // - unicode handling in strings
 TEST_F(JsonStreamParserTest, UnicodeEscaping) {
   StringPiece str = "[\"\\u0639\\u0631\\u0628\\u0649\"]";
   for (int i = 0; i <= str.length(); ++i) {
-    // TODO(xiaofeng): Figure out what default encoding to use for JSON strings.
-    // In protobuf we use UTF-8 for strings, but for JSON we probably should
-    // allow different encodings?
-    ow_.StartList("")->RenderString("", "\u0639\u0631\u0628\u0649")->EndList();
+    ow_.StartList("")
+        ->RenderString("", "\xD8\xB9\xD8\xB1\xD8\xA8\xD9\x89")
+        ->EndList();
     DoTest(str, i);
   }
 }
-#endif
+
+// - unicode UTF-16 surrogate pair handling in strings
+TEST_F(JsonStreamParserTest, UnicodeSurrogatePairEscaping) {
+  StringPiece str =
+      "[\"\\u0bee\\ud800\\uddf1\\uD80C\\uDDA4\\uD83d\\udC1D\U0001F36F\"]";
+  for (int i = 0; i <= str.length(); ++i) {
+    ow_.StartList("")
+        ->RenderString("",
+                       "\xE0\xAF\xAE\xF0\x90\x87\xB1\xF0\x93\x86\xA4\xF0"
+                       "\x9F\x90\x9D\xF0\x9F\x8D\xAF")
+        ->EndList();
+    DoTest(str, i);
+  }
+}
+
+
+TEST_F(JsonStreamParserTest, UnicodeEscapingInvalidCodePointWhenNotCoerced) {
+  // A low surrogate alone.
+  StringPiece str = "[\"\\ude36\"]";
+  for (int i = 0; i <= str.length(); ++i) {
+    DoErrorTest(str, i, "Invalid unicode code point.");
+  }
+}
+
+TEST_F(JsonStreamParserTest, UnicodeEscapingMissingLowSurrogateWhenNotCoerced) {
+  // A high surrogate alone.
+  StringPiece str = "[\"\\ud83d\"]";
+  for (int i = 0; i <= str.length(); ++i) {
+    DoErrorTest(str, i, "Missing low surrogate.");
+  }
+  // A high surrogate with some trailing characters.
+  str = "[\"\\ud83d|ude36\"]";
+  for (int i = 0; i <= str.length(); ++i) {
+    DoErrorTest(str, i, "Missing low surrogate.");
+  }
+  // A high surrogate with half a low surrogate.
+  str = "[\"\\ud83d\\ude--\"]";
+  for (int i = 0; i <= str.length(); ++i) {
+    DoErrorTest(str, i, "Invalid escape sequence.");
+  }
+  // Two high surrogates.
+  str = "[\"\\ud83d\\ud83d\"]";
+  for (int i = 0; i <= str.length(); ++i) {
+    DoErrorTest(str, i, "Invalid low surrogate.");
+  }
+}
 
 // - ascii escaping (\b, \f, \n, \r, \t, \v)
 TEST_F(JsonStreamParserTest, AsciiEscaping) {
@@ -629,6 +699,22 @@
 }
 */
 
+// invalid bare backslash.
+TEST_F(JsonStreamParserTest, UnfinishedEscape) {
+  StringPiece str = "\"\\";
+  for (int i = 0; i <= str.length(); ++i) {
+    DoErrorTest(str, i, "Closing quote expected in string.");
+  }
+}
+
+// invalid bare backslash u.
+TEST_F(JsonStreamParserTest, UnfinishedUnicodeEscape) {
+  StringPiece str = "\"\\u";
+  for (int i = 0; i <= str.length(); ++i) {
+    DoErrorTest(str, i, "Illegal hex string.");
+  }
+}
+
 // invalid unicode sequence.
 TEST_F(JsonStreamParserTest, UnicodeEscapeCutOff) {
   StringPiece str = "\"\\u12";
@@ -637,6 +723,15 @@
   }
 }
 
+// invalid unicode sequence (valid in modern EcmaScript but not in JSON).
+TEST_F(JsonStreamParserTest, BracketedUnicodeEscape) {
+  StringPiece str = "\"\\u{1f36f}\"";
+  for (int i = 0; i <= str.length(); ++i) {
+    DoErrorTest(str, i, "Invalid escape sequence.");
+  }
+}
+
+
 TEST_F(JsonStreamParserTest, UnicodeEscapeInvalidCharacters) {
   StringPiece str = "\"\\u12$4hello";
   for (int i = 0; i <= str.length(); ++i) {
@@ -644,6 +739,14 @@
   }
 }
 
+// invalid unicode sequence in low half surrogate: g is not a hex digit.
+TEST_F(JsonStreamParserTest, UnicodeEscapeLowHalfSurrogateInvalidCharacters) {
+  StringPiece str = "\"\\ud800\\udcfg\"";
+  for (int i = 0; i <= str.length(); ++i) {
+    DoErrorTest(str, i, "Invalid escape sequence.");
+  }
+}
+
 // Extra commas with an object or array.
 TEST_F(JsonStreamParserTest, ExtraCommaInObject) {
   StringPiece str = "{'k1': true,,'k2': false}";
diff --git a/src/google/protobuf/util/internal/object_writer.h b/src/google/protobuf/util/internal/object_writer.h
index e695f45..9f07363 100644
--- a/src/google/protobuf/util/internal/object_writer.h
+++ b/src/google/protobuf/util/internal/object_writer.h
@@ -105,10 +105,27 @@
   static void RenderDataPieceTo(const DataPiece& data, StringPiece name,
                                 ObjectWriter* ow);
 
+  // Indicates whether this ObjectWriter has completed writing the root message,
+  // usually this means writing of one complete object. Subclasses must override
+  // this behavior appropriately.
+  virtual bool done() { return false; }
+
+  void set_use_strict_base64_decoding(bool value) {
+    use_strict_base64_decoding_ = value;
+  }
+
+  bool use_strict_base64_decoding() const {
+    return use_strict_base64_decoding_;
+  }
+
  protected:
-  ObjectWriter() {}
+  ObjectWriter() : use_strict_base64_decoding_(true) {}
 
  private:
+  // If set to true, we use the stricter version of base64 decoding for byte
+  // fields by making sure decoded version encodes back to the original string.
+  bool use_strict_base64_decoding_;
+
   // Do not add any data members to this class.
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectWriter);
 };
diff --git a/src/google/protobuf/util/internal/proto_writer.cc b/src/google/protobuf/util/internal/proto_writer.cc
index 47e0009..36b7941 100644
--- a/src/google/protobuf/util/internal/proto_writer.cc
+++ b/src/google/protobuf/util/internal/proto_writer.cc
@@ -447,9 +447,7 @@
     return this;
   }
 
-    WriteTag(*field);
-  element_.reset(new ProtoElement(element_.release(), field, *type, false));
-  return this;
+  return StartObjectField(*field, *type);
 }
 
 ProtoWriter* ProtoWriter::EndObject() {
@@ -488,8 +486,7 @@
     return this;
   }
 
-  element_.reset(new ProtoElement(element_.release(), field, *type, true));
-  return this;
+  return StartListField(*field, *type);
 }
 
 ProtoWriter* ProtoWriter::EndList() {
@@ -518,98 +515,7 @@
     return this;
   }
 
-  // Pushing a ProtoElement and then pop it off at the end for 2 purposes:
-  // error location reporting and required field accounting.
-  element_.reset(new ProtoElement(element_.release(), field, *type, false));
-
-  if (field->kind() == google::protobuf::Field_Kind_TYPE_UNKNOWN ||
-      field->kind() == google::protobuf::Field_Kind_TYPE_MESSAGE) {
-    InvalidValue(field->type_url().empty()
-                     ? google::protobuf::Field_Kind_Name(field->kind())
-                     : field->type_url(),
-                 data.ValueAsStringOrDefault(""));
-    element_.reset(element()->pop());
-    return this;
-  }
-
-  switch (field->kind()) {
-    case google::protobuf::Field_Kind_TYPE_INT32: {
-      status = WriteInt32(field->number(), data, stream_.get());
-      break;
-    }
-    case google::protobuf::Field_Kind_TYPE_SFIXED32: {
-      status = WriteSFixed32(field->number(), data, stream_.get());
-      break;
-    }
-    case google::protobuf::Field_Kind_TYPE_SINT32: {
-      status = WriteSInt32(field->number(), data, stream_.get());
-      break;
-    }
-    case google::protobuf::Field_Kind_TYPE_FIXED32: {
-      status = WriteFixed32(field->number(), data, stream_.get());
-      break;
-    }
-    case google::protobuf::Field_Kind_TYPE_UINT32: {
-      status = WriteUInt32(field->number(), data, stream_.get());
-      break;
-    }
-    case google::protobuf::Field_Kind_TYPE_INT64: {
-      status = WriteInt64(field->number(), data, stream_.get());
-      break;
-    }
-    case google::protobuf::Field_Kind_TYPE_SFIXED64: {
-      status = WriteSFixed64(field->number(), data, stream_.get());
-      break;
-    }
-    case google::protobuf::Field_Kind_TYPE_SINT64: {
-      status = WriteSInt64(field->number(), data, stream_.get());
-      break;
-    }
-    case google::protobuf::Field_Kind_TYPE_FIXED64: {
-      status = WriteFixed64(field->number(), data, stream_.get());
-      break;
-    }
-    case google::protobuf::Field_Kind_TYPE_UINT64: {
-      status = WriteUInt64(field->number(), data, stream_.get());
-      break;
-    }
-    case google::protobuf::Field_Kind_TYPE_DOUBLE: {
-      status = WriteDouble(field->number(), data, stream_.get());
-      break;
-    }
-    case google::protobuf::Field_Kind_TYPE_FLOAT: {
-      status = WriteFloat(field->number(), data, stream_.get());
-      break;
-    }
-    case google::protobuf::Field_Kind_TYPE_BOOL: {
-      status = WriteBool(field->number(), data, stream_.get());
-      break;
-    }
-    case google::protobuf::Field_Kind_TYPE_BYTES: {
-      status = WriteBytes(field->number(), data, stream_.get());
-      break;
-    }
-    case google::protobuf::Field_Kind_TYPE_STRING: {
-      status = WriteString(field->number(), data, stream_.get());
-      break;
-    }
-    case google::protobuf::Field_Kind_TYPE_ENUM: {
-      status = WriteEnum(field->number(), data,
-                         typeinfo_->GetEnumByTypeUrl(field->type_url()),
-                         stream_.get());
-      break;
-    }
-    default:  // TYPE_GROUP or TYPE_MESSAGE
-      status = Status(INVALID_ARGUMENT, data.ToString().ValueOrDie());
-  }
-
-  if (!status.ok()) {
-    InvalidValue(google::protobuf::Field_Kind_Name(field->kind()),
-                 status.error_message());
-  }
-
-  element_.reset(element()->pop());
-  return this;
+  return RenderPrimitiveField(*field, *type, data);
 }
 
 bool ProtoWriter::ValidOneof(const google::protobuf::Field& field,
@@ -635,6 +541,118 @@
          google::protobuf::Field_Cardinality_CARDINALITY_REPEATED;
 }
 
+ProtoWriter* ProtoWriter::StartObjectField(const google::protobuf::Field& field,
+                                           const google::protobuf::Type& type) {
+    WriteTag(field);
+  element_.reset(new ProtoElement(element_.release(), &field, type, false));
+  return this;
+}
+
+ProtoWriter* ProtoWriter::StartListField(const google::protobuf::Field& field,
+                                         const google::protobuf::Type& type) {
+  element_.reset(new ProtoElement(element_.release(), &field, type, true));
+  return this;
+}
+
+ProtoWriter* ProtoWriter::RenderPrimitiveField(
+    const google::protobuf::Field& field, const google::protobuf::Type& type,
+    const DataPiece& data) {
+  Status status;
+
+  // Pushing a ProtoElement and then pop it off at the end for 2 purposes:
+  // error location reporting and required field accounting.
+  element_.reset(new ProtoElement(element_.release(), &field, type, false));
+
+  if (field.kind() == google::protobuf::Field_Kind_TYPE_UNKNOWN ||
+      field.kind() == google::protobuf::Field_Kind_TYPE_MESSAGE) {
+    InvalidValue(field.type_url().empty()
+                     ? google::protobuf::Field_Kind_Name(field.kind())
+                     : field.type_url(),
+                 data.ValueAsStringOrDefault(""));
+    element_.reset(element()->pop());
+    return this;
+  }
+
+  switch (field.kind()) {
+    case google::protobuf::Field_Kind_TYPE_INT32: {
+      status = WriteInt32(field.number(), data, stream_.get());
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_SFIXED32: {
+      status = WriteSFixed32(field.number(), data, stream_.get());
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_SINT32: {
+      status = WriteSInt32(field.number(), data, stream_.get());
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_FIXED32: {
+      status = WriteFixed32(field.number(), data, stream_.get());
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_UINT32: {
+      status = WriteUInt32(field.number(), data, stream_.get());
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_INT64: {
+      status = WriteInt64(field.number(), data, stream_.get());
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_SFIXED64: {
+      status = WriteSFixed64(field.number(), data, stream_.get());
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_SINT64: {
+      status = WriteSInt64(field.number(), data, stream_.get());
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_FIXED64: {
+      status = WriteFixed64(field.number(), data, stream_.get());
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_UINT64: {
+      status = WriteUInt64(field.number(), data, stream_.get());
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_DOUBLE: {
+      status = WriteDouble(field.number(), data, stream_.get());
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_FLOAT: {
+      status = WriteFloat(field.number(), data, stream_.get());
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_BOOL: {
+      status = WriteBool(field.number(), data, stream_.get());
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_BYTES: {
+      status = WriteBytes(field.number(), data, stream_.get());
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_STRING: {
+      status = WriteString(field.number(), data, stream_.get());
+      break;
+    }
+    case google::protobuf::Field_Kind_TYPE_ENUM: {
+      status = WriteEnum(field.number(), data,
+                         typeinfo_->GetEnumByTypeUrl(field.type_url()),
+                         stream_.get());
+      break;
+    }
+    default:  // TYPE_GROUP or TYPE_MESSAGE
+      status = Status(INVALID_ARGUMENT, data.ToString().ValueOrDie());
+  }
+
+  if (!status.ok()) {
+    InvalidValue(google::protobuf::Field_Kind_Name(field.kind()),
+                 status.error_message());
+  }
+
+  element_.reset(element()->pop());
+  return this;
+}
+
 const google::protobuf::Field* ProtoWriter::BeginNamed(StringPiece name,
                                                        bool is_list) {
   if (invalid_depth_ > 0) {
diff --git a/src/google/protobuf/util/internal/proto_writer.h b/src/google/protobuf/util/internal/proto_writer.h
index e631e56..957565e 100644
--- a/src/google/protobuf/util/internal/proto_writer.h
+++ b/src/google/protobuf/util/internal/proto_writer.h
@@ -106,10 +106,12 @@
     return RenderDataPiece(name, DataPiece(value));
   }
   virtual ProtoWriter* RenderString(StringPiece name, StringPiece value) {
-    return RenderDataPiece(name, DataPiece(value));
+    return RenderDataPiece(name,
+                           DataPiece(value, use_strict_base64_decoding()));
   }
   virtual ProtoWriter* RenderBytes(StringPiece name, StringPiece value) {
-    return RenderDataPiece(name, DataPiece(value, false));
+    return RenderDataPiece(
+        name, DataPiece(value, false, use_strict_base64_decoding()));
   }
   virtual ProtoWriter* RenderNull(StringPiece name) {
     return RenderDataPiece(name, DataPiece::NullData());
@@ -126,7 +128,7 @@
   }
 
   // When true, we finished writing to output a complete message.
-  bool done() const { return done_; }
+  bool done() { return done_; }
 
   // Returns the proto stream object.
   google::protobuf::io::CodedOutputStream* stream() { return stream_.get(); }
@@ -266,6 +268,19 @@
   // Returns true if the field is repeated.
   bool IsRepeated(const google::protobuf::Field& field);
 
+  // Starts an object given the field and the enclosing type.
+  ProtoWriter* StartObjectField(const google::protobuf::Field& field,
+                                const google::protobuf::Type& type);
+
+  // Starts a list given the field and the enclosing type.
+  ProtoWriter* StartListField(const google::protobuf::Field& field,
+                              const google::protobuf::Type& type);
+
+  // Renders a primitve field given the field and the enclosing type.
+  ProtoWriter* RenderPrimitiveField(const google::protobuf::Field& field,
+                                    const google::protobuf::Type& type,
+                                    const DataPiece& value);
+
  private:
   // Variables for describing the structure of the input tree:
   // master_type_: descriptor for the whole protobuf message.
diff --git a/src/google/protobuf/util/internal/protostream_objectsource.cc b/src/google/protobuf/util/internal/protostream_objectsource.cc
index 034d616..297c011 100644
--- a/src/google/protobuf/util/internal/protostream_objectsource.cc
+++ b/src/google/protobuf/util/internal/protostream_objectsource.cc
@@ -83,6 +83,29 @@
 
 // Utility function to format nanos.
 const string FormatNanos(uint32 nanos);
+
+StatusOr<string> MapKeyDefaultValueAsString(
+    const google::protobuf::Field& field) {
+  switch (field.kind()) {
+    case google::protobuf::Field_Kind_TYPE_BOOL:
+      return string("false");
+    case google::protobuf::Field_Kind_TYPE_INT32:
+    case google::protobuf::Field_Kind_TYPE_INT64:
+    case google::protobuf::Field_Kind_TYPE_UINT32:
+    case google::protobuf::Field_Kind_TYPE_UINT64:
+    case google::protobuf::Field_Kind_TYPE_SINT32:
+    case google::protobuf::Field_Kind_TYPE_SINT64:
+    case google::protobuf::Field_Kind_TYPE_SFIXED32:
+    case google::protobuf::Field_Kind_TYPE_SFIXED64:
+    case google::protobuf::Field_Kind_TYPE_FIXED32:
+    case google::protobuf::Field_Kind_TYPE_FIXED64:
+      return string("0");
+    case google::protobuf::Field_Kind_TYPE_STRING:
+      return string();
+    default:
+      return Status(util::error::INTERNAL, "Invalid map key type.");
+  }
+}
 }  // namespace
 
 
@@ -92,14 +115,19 @@
     : stream_(stream),
       typeinfo_(TypeInfo::NewTypeInfo(type_resolver)),
       own_typeinfo_(true),
-      type_(type) {
+      type_(type),
+      use_lower_camel_for_enums_(false) {
   GOOGLE_LOG_IF(DFATAL, stream == NULL) << "Input stream is NULL.";
 }
 
 ProtoStreamObjectSource::ProtoStreamObjectSource(
     google::protobuf::io::CodedInputStream* stream, const TypeInfo* typeinfo,
     const google::protobuf::Type& type)
-    : stream_(stream), typeinfo_(typeinfo), own_typeinfo_(false), type_(type) {
+    : stream_(stream),
+      typeinfo_(typeinfo),
+      own_typeinfo_(false),
+      type_(type),
+      use_lower_camel_for_enums_(false) {
   GOOGLE_LOG_IF(DFATAL, stream == NULL) << "Input stream is NULL.";
 }
 
@@ -238,9 +266,21 @@
         map_key = ReadFieldValueAsString(*field);
       } else if (field->number() == 2) {
         if (map_key.empty()) {
-          return Status(util::error::INTERNAL, "Map key must be non-empty");
+          // An absent map key is treated as the default.
+          const google::protobuf::Field* key_field =
+              FindFieldByNumber(*field_type, 1);
+          if (key_field == NULL) {
+            // The Type info for this map entry is incorrect. It should always
+            // have a field named "key" and with field number 1.
+            return Status(util::error::INTERNAL, "Invalid map entry.");
+          }
+          ASSIGN_OR_RETURN(map_key, MapKeyDefaultValueAsString(*key_field));
         }
         RETURN_IF_ERROR(RenderField(field, map_key, ow));
+      } else {
+        // The Type info for this map entry is incorrect. It should contain
+        // exactly two fields with field number 1 and 2.
+        return Status(util::error::INTERNAL, "Invalid map entry.");
       }
     }
     stream_->PopLimit(old_limit);
@@ -266,7 +306,7 @@
   pair<int64, int32> p = os->ReadSecondsAndNanos(type);
   int64 seconds = p.first;
   int32 nanos = p.second;
-  if (seconds > kMaxSeconds || seconds < kMinSeconds) {
+  if (seconds > kTimestampMaxSeconds || seconds < kTimestampMinSeconds) {
     return Status(
         util::error::INTERNAL,
         StrCat("Timestamp seconds exceeds limit for field: ", field_name));
@@ -290,7 +330,7 @@
   pair<int64, int32> p = os->ReadSecondsAndNanos(type);
   int64 seconds = p.first;
   int32 nanos = p.second;
-  if (seconds > kMaxSeconds || seconds < kMinSeconds) {
+  if (seconds > kDurationMaxSeconds || seconds < kDurationMinSeconds) {
     return Status(
         util::error::INTERNAL,
         StrCat("Duration seconds exceeds limit for field: ", field_name));
@@ -807,7 +847,10 @@
         const google::protobuf::EnumValue* enum_value =
             FindEnumValueByNumber(*en, buffer32);
         if (enum_value != NULL) {
-          ow->RenderString(field_name, enum_value->name());
+          if (use_lower_camel_for_enums_)
+            ow->RenderString(field_name, ToCamelCase(enum_value->name()));
+          else
+            ow->RenderString(field_name, enum_value->name());
         }
       } else {
         GOOGLE_LOG(INFO) << "Unknown enum skipped: " << field->type_url();
diff --git a/src/google/protobuf/util/internal/protostream_objectsource.h b/src/google/protobuf/util/internal/protostream_objectsource.h
index 78defa1..17e03b7 100644
--- a/src/google/protobuf/util/internal/protostream_objectsource.h
+++ b/src/google/protobuf/util/internal/protostream_objectsource.h
@@ -82,6 +82,34 @@
 
   virtual util::Status NamedWriteTo(StringPiece name, ObjectWriter* ow) const;
 
+  // Sets whether or not to use lowerCamelCase casing for enum values. If set to
+  // false, enum values are output without any case conversions.
+  //
+  // For example, if we have an enum:
+  // enum Type {
+  //   ACTION_AND_ADVENTURE = 1;
+  // }
+  // Type type = 20;
+  //
+  // And this option is set to true. Then the rendered "type" field will have
+  // the string "actionAndAdventure".
+  // {
+  //   ...
+  //   "type": "actionAndAdventure",
+  //   ...
+  // }
+  //
+  // If set to false, the rendered "type" field will have the string
+  // "ACTION_AND_ADVENTURE".
+  // {
+  //   ...
+  //   "type": "ACTION_AND_ADVENTURE",
+  //   ...
+  // }
+  void set_use_lower_camel_for_enums(bool value) {
+    use_lower_camel_for_enums_ = value;
+  }
+
  protected:
   // Writes a proto2 Message to the ObjectWriter. When the given end_tag is
   // found this method will complete, allowing it to be used for parsing both
@@ -237,6 +265,9 @@
   const google::protobuf::Type& type_;
 
 
+  // Whether to render enums using lowerCamelCase. Defaults to false.
+  bool use_lower_camel_for_enums_;
+
   GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoStreamObjectSource);
 };
 
diff --git a/src/google/protobuf/util/internal/protostream_objectsource_test.cc b/src/google/protobuf/util/internal/protostream_objectsource_test.cc
index 561f676..1b32c80 100644
--- a/src/google/protobuf/util/internal/protostream_objectsource_test.cc
+++ b/src/google/protobuf/util/internal/protostream_objectsource_test.cc
@@ -50,6 +50,7 @@
 #include <google/protobuf/util/internal/testdata/anys.pb.h>
 #include <google/protobuf/util/internal/testdata/maps.pb.h>
 #include <google/protobuf/util/internal/testdata/struct.pb.h>
+#include <google/protobuf/util/internal/testdata/timestamp_duration.pb.h>
 #include <gtest/gtest.h>
 
 
@@ -75,6 +76,8 @@
 using google::protobuf::testing::Primitive;
 using google::protobuf::testing::more_author;
 using google::protobuf::testing::maps::MapOut;
+using google::protobuf::testing::maps::MapOutWireFormat;
+using google::protobuf::testing::timestampduration::TimestampDuration;
 using google::protobuf::testing::anys::AnyOut;
 using google::protobuf::testing::anys::AnyM;
 using google::protobuf::testing::FieldMaskTest;
@@ -92,7 +95,11 @@
 class ProtostreamObjectSourceTest
     : public ::testing::TestWithParam<testing::TypeInfoSource> {
  protected:
-  ProtostreamObjectSourceTest() : helper_(GetParam()), mock_(), ow_(&mock_) {
+  ProtostreamObjectSourceTest()
+      : helper_(GetParam()),
+        mock_(),
+        ow_(&mock_),
+        use_lower_camel_for_enums_(false) {
     helper_.ResetTypeInfo(Book::descriptor());
   }
 
@@ -112,6 +119,7 @@
 
     google::protobuf::scoped_ptr<ProtoStreamObjectSource> os(
         helper_.NewProtoSource(&in_stream, GetTypeUrl(descriptor)));
+    if (use_lower_camel_for_enums_) os->set_use_lower_camel_for_enums(true);
     return os->WriteTo(&mock_);
   }
 
@@ -256,10 +264,13 @@
     return primitive;
   }
 
+  void UseLowerCamelForEnums() { use_lower_camel_for_enums_ = true; }
+
   testing::TypeInfoTestHelper helper_;
 
   ::testing::NiceMock<MockObjectWriter> mock_;
   ExpectingObjectWriter ow_;
+  bool use_lower_camel_for_enums_;
 };
 
 INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
@@ -461,6 +472,25 @@
   DoTest(book, Book::descriptor());
 }
 
+TEST_P(ProtostreamObjectSourceTest, LowerCamelEnumOutputTest) {
+  Book book;
+  book.set_type(Book::ACTION_AND_ADVENTURE);
+
+  UseLowerCamelForEnums();
+
+  ow_.StartObject("")->RenderString("type", "actionAndAdventure")->EndObject();
+  DoTest(book, Book::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceTest, EnumCaseIsUnchangedByDefault) {
+  Book book;
+  book.set_type(Book::ACTION_AND_ADVENTURE);
+  ow_.StartObject("")
+      ->RenderString("type", "ACTION_AND_ADVENTURE")
+      ->EndObject();
+  DoTest(book, Book::descriptor());
+}
+
 class ProtostreamObjectSourceMapsTest : public ProtostreamObjectSourceTest {
  protected:
   ProtostreamObjectSourceMapsTest() {
@@ -541,6 +571,67 @@
   DoTest(out, MapOut::descriptor());
 }
 
+TEST_P(ProtostreamObjectSourceMapsTest, MissingKeysTest) {
+  // MapOutWireFormat has the same wire representation with MapOut but uses
+  // repeated message fields to represent map fields so we can intentionally
+  // leave out the key field or the value field of a map entry.
+  MapOutWireFormat out;
+  // Create some map entries without keys. They will be rendered with the
+  // default values ("" for strings, "0" for integers, etc.).
+  // {
+  //   "map1": {
+  //     "": {
+  //       "foo": "foovalue"
+  //     }
+  //   },
+  //   "map2": {
+  //     "": {
+  //       "map1": {
+  //         "nested_key1": {
+  //           "foo": "nested_foo"
+  //         }
+  //       }
+  //     }
+  //   },
+  //   "map3": {
+  //     "0": "one one one"
+  //   },
+  //   "map4": {
+  //     "false": "bool"
+  //   }
+  // }
+  out.add_map1()->mutable_value()->set_foo("foovalue");
+  MapOut* nested = out.add_map2()->mutable_value();
+  (*nested->mutable_map1())["nested_key1"].set_foo("nested_foo");
+  out.add_map3()->set_value("one one one");
+  out.add_map4()->set_value("bool");
+
+  ow_.StartObject("")
+      ->StartObject("map1")
+      ->StartObject("")
+      ->RenderString("foo", "foovalue")
+      ->EndObject()
+      ->EndObject()
+      ->StartObject("map2")
+      ->StartObject("")
+      ->StartObject("map1")
+      ->StartObject("nested_key1")
+      ->RenderString("foo", "nested_foo")
+      ->EndObject()
+      ->EndObject()
+      ->EndObject()
+      ->EndObject()
+      ->StartObject("map3")
+      ->RenderString("0", "one one one")
+      ->EndObject()
+      ->StartObject("map4")
+      ->RenderString("false", "bool")
+      ->EndObject()
+      ->EndObject();
+
+  DoTest(out, MapOut::descriptor());
+}
+
 class ProtostreamObjectSourceAnysTest : public ProtostreamObjectSourceTest {
  protected:
   ProtostreamObjectSourceAnysTest() {
@@ -824,6 +915,63 @@
   DoTest(out, FieldMaskTest::descriptor());
 }
 
+class ProtostreamObjectSourceTimestampTest
+    : public ProtostreamObjectSourceTest {
+ protected:
+  ProtostreamObjectSourceTimestampTest() {
+    helper_.ResetTypeInfo(TimestampDuration::descriptor());
+  }
+};
+
+INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
+                        ProtostreamObjectSourceTimestampTest,
+                        ::testing::Values(
+                            testing::USE_TYPE_RESOLVER));
+
+TEST_P(ProtostreamObjectSourceTimestampTest, InvalidTimestampBelowMinTest) {
+  TimestampDuration out;
+  google::protobuf::Timestamp* ts = out.mutable_ts();
+  // Min allowed seconds - 1
+  ts->set_seconds(kTimestampMinSeconds - 1);
+  ow_.StartObject("");
+
+  Status status = ExecuteTest(out, TimestampDuration::descriptor());
+  EXPECT_EQ(util::error::INTERNAL, status.error_code());
+}
+
+TEST_P(ProtostreamObjectSourceTimestampTest, InvalidTimestampAboveMaxTest) {
+  TimestampDuration out;
+  google::protobuf::Timestamp* ts = out.mutable_ts();
+  // Max allowed seconds + 1
+  ts->set_seconds(kTimestampMaxSeconds + 1);
+  ow_.StartObject("");
+
+  Status status = ExecuteTest(out, TimestampDuration::descriptor());
+  EXPECT_EQ(util::error::INTERNAL, status.error_code());
+}
+
+TEST_P(ProtostreamObjectSourceTimestampTest, InvalidDurationBelowMinTest) {
+  TimestampDuration out;
+  google::protobuf::Duration* dur = out.mutable_dur();
+  // Min allowed seconds - 1
+  dur->set_seconds(kDurationMinSeconds - 1);
+  ow_.StartObject("");
+
+  Status status = ExecuteTest(out, TimestampDuration::descriptor());
+  EXPECT_EQ(util::error::INTERNAL, status.error_code());
+}
+
+TEST_P(ProtostreamObjectSourceTimestampTest, InvalidDurationAboveMaxTest) {
+  TimestampDuration out;
+  google::protobuf::Duration* dur = out.mutable_dur();
+  // Min allowed seconds + 1
+  dur->set_seconds(kDurationMaxSeconds + 1);
+  ow_.StartObject("");
+
+  Status status = ExecuteTest(out, TimestampDuration::descriptor());
+  EXPECT_EQ(util::error::INTERNAL, status.error_code());
+}
+
 }  // namespace converter
 }  // namespace util
 }  // namespace protobuf
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.cc b/src/google/protobuf/util/internal/protostream_objectwriter.cc
index 786bf0b..94ddb42 100644
--- a/src/google/protobuf/util/internal/protostream_objectwriter.cc
+++ b/src/google/protobuf/util/internal/protostream_objectwriter.cc
@@ -58,17 +58,20 @@
 
 ProtoStreamObjectWriter::ProtoStreamObjectWriter(
     TypeResolver* type_resolver, const google::protobuf::Type& type,
-    strings::ByteSink* output, ErrorListener* listener)
+    strings::ByteSink* output, ErrorListener* listener,
+    const ProtoStreamObjectWriter::Options& options)
     : ProtoWriter(type_resolver, type, output, listener),
       master_type_(type),
-      current_(NULL) {}
+      current_(NULL),
+      options_(options) {}
 
 ProtoStreamObjectWriter::ProtoStreamObjectWriter(
     const TypeInfo* typeinfo, const google::protobuf::Type& type,
     strings::ByteSink* output, ErrorListener* listener)
     : ProtoWriter(typeinfo, type, output, listener),
       master_type_(type),
-      current_(NULL) {}
+      current_(NULL),
+      options_(ProtoStreamObjectWriter::Options::Defaults()) {}
 
 ProtoStreamObjectWriter::~ProtoStreamObjectWriter() {
   if (current_ == NULL) return;
@@ -439,7 +442,8 @@
     // name):
     // { "key": "<name>", "value": {
     Push("", Item::MESSAGE, false, false);
-    ProtoWriter::RenderDataPiece("key", DataPiece(name));
+    ProtoWriter::RenderDataPiece("key",
+                                 DataPiece(name, use_strict_base64_decoding()));
     Push("value", Item::MESSAGE, true, false);
 
     // Make sure we are valid so far after starting map fields.
@@ -604,7 +608,8 @@
     // Render
     // { "key": "<name>", "value": {
     Push("", Item::MESSAGE, false, false);
-    ProtoWriter::RenderDataPiece("key", DataPiece(name));
+    ProtoWriter::RenderDataPiece("key",
+                                 DataPiece(name, use_strict_base64_decoding()));
     Push("value", Item::MESSAGE, true, false);
 
     // Make sure we are valid after pushing all above items.
@@ -758,8 +763,36 @@
   string struct_field_name;
   switch (data.type()) {
     // Our JSON parser parses numbers as either int64, uint64, or double.
-    case DataPiece::TYPE_INT64:
-    case DataPiece::TYPE_UINT64:
+    case DataPiece::TYPE_INT64: {
+      // If the option to treat integers as strings is set, then render them as
+      // strings. Otherwise, fallback to rendering them as double.
+      if (ow->options_.struct_integers_as_strings) {
+        StatusOr<int64> int_value = data.ToInt64();
+        if (int_value.ok()) {
+          ow->ProtoWriter::RenderDataPiece(
+              "string_value",
+              DataPiece(SimpleItoa(int_value.ValueOrDie()), true));
+          return Status::OK;
+        }
+      }
+      struct_field_name = "number_value";
+      break;
+    }
+    case DataPiece::TYPE_UINT64: {
+      // If the option to treat integers as strings is set, then render them as
+      // strings. Otherwise, fallback to rendering them as double.
+      if (ow->options_.struct_integers_as_strings) {
+        StatusOr<uint64> int_value = data.ToUint64();
+        if (int_value.ok()) {
+          ow->ProtoWriter::RenderDataPiece(
+              "string_value",
+              DataPiece(SimpleItoa(int_value.ValueOrDie()), true));
+          return Status::OK;
+        }
+      }
+      struct_field_name = "number_value";
+      break;
+    }
     case DataPiece::TYPE_DOUBLE: {
       struct_field_name = "number_value";
       break;
@@ -812,7 +845,7 @@
 static inline util::Status RenderOneFieldPath(ProtoStreamObjectWriter* ow,
                                                 StringPiece path) {
   ow->ProtoWriter::RenderDataPiece(
-      "paths", DataPiece(ConvertFieldMaskPath(path, &ToSnakeCase)));
+      "paths", DataPiece(ConvertFieldMaskPath(path, &ToSnakeCase), true));
   return Status::OK;
 }
 
@@ -871,7 +904,7 @@
   nanos = sign * nanos;
 
   int64 seconds = sign * unsigned_seconds;
-  if (seconds > kMaxSeconds || seconds < kMinSeconds ||
+  if (seconds > kDurationMaxSeconds || seconds < kDurationMinSeconds ||
       nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) {
     return Status(INVALID_ARGUMENT, "Duration value exceeds limits");
   }
@@ -925,7 +958,8 @@
     // Render an item in repeated map list.
     // { "key": "<name>", "value":
     Push("", Item::MESSAGE, false, false);
-    ProtoWriter::RenderDataPiece("key", DataPiece(name));
+    ProtoWriter::RenderDataPiece("key",
+                                 DataPiece(name, use_strict_base64_decoding()));
     field = Lookup("value");
     if (field == NULL) {
       GOOGLE_LOG(DFATAL) << "Map does not have a value field.";
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.h b/src/google/protobuf/util/internal/protostream_objectwriter.h
index 08ac6e3..96ea3f2 100644
--- a/src/google/protobuf/util/internal/protostream_objectwriter.h
+++ b/src/google/protobuf/util/internal/protostream_objectwriter.h
@@ -74,10 +74,30 @@
 // It also supports streaming.
 class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter {
  public:
+  // Options that control ProtoStreamObjectWriter class's behavior.
+  struct Options {
+    // Treats integer inputs in google.protobuf.Struct as strings. Normally,
+    // integer values are returned in double field "number_value" of
+    // google.protobuf.Struct. However, this can cause precision loss for
+    // int64/uint64 inputs. This option is provided for cases that want to
+    // preserve integer precision.
+    bool struct_integers_as_strings;
+
+    Options() : struct_integers_as_strings(false) {}
+
+    // Default instance of Options with all options set to defaults.
+    static const Options& Defaults() {
+      static Options defaults;
+      return defaults;
+    }
+  };
+
 // Constructor. Does not take ownership of any parameter passed in.
   ProtoStreamObjectWriter(TypeResolver* type_resolver,
                           const google::protobuf::Type& type,
-                          strings::ByteSink* output, ErrorListener* listener);
+                          strings::ByteSink* output, ErrorListener* listener,
+                          const ProtoStreamObjectWriter::Options& options =
+                              ProtoStreamObjectWriter::Options::Defaults());
   virtual ~ProtoStreamObjectWriter();
 
   // ObjectWriter methods.
@@ -301,6 +321,9 @@
   // The current element, variable for internal state processing.
   google::protobuf::scoped_ptr<Item> current_;
 
+  // Reference to the options that control this class's behavior.
+  const ProtoStreamObjectWriter::Options options_;
+
   GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoStreamObjectWriter);
 };
 
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter_test.cc b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc
index 5f9ffb9..41eaebc 100644
--- a/src/google/protobuf/util/internal/protostream_objectwriter_test.cc
+++ b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc
@@ -90,6 +90,12 @@
 }
 }  // namespace
 
+#if __cplusplus >= 201103L
+  using std::get;
+#else
+  using std::tr1::get;
+#endif
+
 class BaseProtoStreamObjectWriterTest
     : public ::testing::TestWithParam<testing::TypeInfoSource> {
  protected:
@@ -122,7 +128,13 @@
     GOOGLE_CHECK(!descriptors.empty()) << "Must have at least one descriptor!";
     helper_.ResetTypeInfo(descriptors);
     ow_.reset(helper_.NewProtoWriter(GetTypeUrl(descriptors[0]), output_.get(),
-                                     &listener_));
+                                     &listener_, options_));
+  }
+
+  void ResetTypeInfo(const Descriptor* descriptor) {
+    vector<const Descriptor*> descriptors;
+    descriptors.push_back(descriptor);
+    ResetTypeInfo(descriptors);
   }
 
   virtual ~BaseProtoStreamObjectWriterTest() {}
@@ -155,16 +167,12 @@
   MockErrorListener listener_;
   google::protobuf::scoped_ptr<GrowingArrayByteSink> output_;
   google::protobuf::scoped_ptr<ProtoStreamObjectWriter> ow_;
+  ProtoStreamObjectWriter::Options options_;
 };
 
 MATCHER_P(HasObjectLocation, expected,
           "Verifies the expected object location") {
-  string actual;
-#if __cplusplus >= 201103L
-  actual = std::get<0>(arg).ToString();
-#else
-  actual = std::tr1::get<0>(arg).ToString();
-#endif
+  string actual = get<0>(arg).ToString();
   if (actual.compare(expected) == 0) return true;
   *result_listener << "actual location is: " << actual;
   return false;
@@ -289,8 +297,7 @@
   full.add_rep_double(-8.05L);
   full.add_rep_bool(false);
 
-  ow_.reset(helper_.NewProtoWriter(GetTypeUrl(Primitive::descriptor()),
-                                   output_.get(), &listener_));
+  ResetTypeInfo(Primitive::descriptor());
 
   ow_->StartObject("")
       ->RenderString("fix32", "101")
@@ -363,8 +370,7 @@
   full.set_float_(std::numeric_limits<float>::infinity());
   full.set_str("-Infinity");
 
-  ow_.reset(helper_.NewProtoWriter(GetTypeUrl(Primitive::descriptor()),
-                                   output_.get(), &listener_));
+  ResetTypeInfo(Primitive::descriptor());
 
   EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_INT32"),
                                       StringPiece("\"Infinity\"")))
@@ -397,8 +403,7 @@
   full.set_float_(std::numeric_limits<float>::quiet_NaN());
   full.set_str("NaN");
 
-  ow_.reset(helper_.NewProtoWriter(GetTypeUrl(Primitive::descriptor()),
-                                   output_.get(), &listener_));
+  ResetTypeInfo(Primitive::descriptor());
 
   EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_INT32"),
                                       StringPiece("\"NaN\"")))
@@ -887,6 +892,124 @@
   CheckOutput(timestamp);
 }
 
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
+       ParseTimestampYearNotZeroPadded) {
+  TimestampDuration timestamp;
+  google::protobuf::Timestamp* ts = timestamp.mutable_ts();
+  ts->set_seconds(-61665654145);
+  ts->set_nanos(33155000);
+
+  ow_->StartObject("")
+      ->RenderString("ts", "15-11-23T03:37:35.033155Z")
+      ->EndObject();
+  CheckOutput(timestamp);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
+       ParseTimestampYearZeroPadded) {
+  TimestampDuration timestamp;
+  google::protobuf::Timestamp* ts = timestamp.mutable_ts();
+  ts->set_seconds(-61665654145);
+  ts->set_nanos(33155000);
+
+  ow_->StartObject("")
+      ->RenderString("ts", "0015-11-23T03:37:35.033155Z")
+      ->EndObject();
+  CheckOutput(timestamp);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
+       ParseTimestampWithPositiveOffset) {
+  TimestampDuration timestamp;
+  google::protobuf::Timestamp* ts = timestamp.mutable_ts();
+  ts->set_seconds(1448249855);
+  ts->set_nanos(33155000);
+
+  ow_->StartObject("")
+      ->RenderString("ts", "2015-11-23T11:47:35.033155+08:10")
+      ->EndObject();
+  CheckOutput(timestamp);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
+       ParseTimestampWithNegativeOffset) {
+  TimestampDuration timestamp;
+  google::protobuf::Timestamp* ts = timestamp.mutable_ts();
+  ts->set_seconds(1448249855);
+  ts->set_nanos(33155000);
+
+  ow_->StartObject("")
+      ->RenderString("ts", "2015-11-22T19:47:35.033155-07:50")
+      ->EndObject();
+  CheckOutput(timestamp);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
+       TimestampWithInvalidOffset1) {
+  TimestampDuration timestamp;
+
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(_,
+                   StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
+                   StringPiece("Field 'ts', Invalid time format: "
+                               "2016-03-07T15:14:23+")));
+
+  ow_->StartObject("")->RenderString("ts", "2016-03-07T15:14:23+")->EndObject();
+  CheckOutput(timestamp);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
+       TimestampWithInvalidOffset2) {
+  TimestampDuration timestamp;
+
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(_,
+                   StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
+                   StringPiece("Field 'ts', Invalid time format: "
+                               "2016-03-07T15:14:23+08-10")));
+
+  ow_->StartObject("")
+      ->RenderString("ts", "2016-03-07T15:14:23+08-10")
+      ->EndObject();
+  CheckOutput(timestamp);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
+       TimestampWithInvalidOffset3) {
+  TimestampDuration timestamp;
+
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(_,
+                   StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
+                   StringPiece("Field 'ts', Invalid time format: "
+                               "2016-03-07T15:14:23+24:10")));
+
+  ow_->StartObject("")
+      ->RenderString("ts", "2016-03-07T15:14:23+24:10")
+      ->EndObject();
+  CheckOutput(timestamp);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
+       TimestampWithInvalidOffset4) {
+  TimestampDuration timestamp;
+
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(_,
+                   StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
+                   StringPiece("Field 'ts', Invalid time format: "
+                               "2016-03-07T15:14:23+04:60")));
+
+  ow_->StartObject("")
+      ->RenderString("ts", "2016-03-07T15:14:23+04:60")
+      ->EndObject();
+  CheckOutput(timestamp);
+}
+
 TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError1) {
   TimestampDuration timestamp;
 
@@ -937,10 +1060,10 @@
       InvalidValue(_,
                    StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
                    StringPiece("Field 'ts', Invalid time format: "
-                               "-8032-10-18T00:00:00.000Z")));
+                               "-8031-10-18T00:00:00.000Z")));
 
   ow_->StartObject("")
-      ->RenderString("ts", "-8032-10-18T00:00:00.000Z")
+      ->RenderString("ts", "-8031-10-18T00:00:00.000Z")
       ->EndObject();
   CheckOutput(timestamp);
 }
@@ -996,6 +1119,22 @@
   CheckOutput(timestamp);
 }
 
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError8) {
+  TimestampDuration timestamp;
+
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(_,
+                   StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
+                   StringPiece("Field 'ts', Invalid time format: "
+                               "0-12-31T23:59:59.000Z")));
+
+  ow_->StartObject("")
+      ->RenderString("ts", "0-12-31T23:59:59.000Z")
+      ->EndObject();
+  CheckOutput(timestamp);
+}
+
 TEST_P(ProtoStreamObjectWriterTimestampDurationTest, ParseDuration) {
   TimestampDuration duration;
   google::protobuf::Duration* dur = duration.mutable_dur();
@@ -1105,7 +1244,10 @@
 class ProtoStreamObjectWriterStructTest
     : public BaseProtoStreamObjectWriterTest {
  protected:
-  ProtoStreamObjectWriterStructTest() {
+  ProtoStreamObjectWriterStructTest() { ResetProtoWriter(); }
+
+  // Resets ProtoWriter with current set of options and other state.
+  void ResetProtoWriter() {
     vector<const Descriptor*> descriptors;
     descriptors.push_back(StructType::descriptor());
     descriptors.push_back(google::protobuf::Struct::descriptor());
@@ -1201,6 +1343,28 @@
       ->EndObject();
 }
 
+TEST_P(ProtoStreamObjectWriterStructTest, OptionStructIntAsStringsTest) {
+  StructType struct_type;
+  google::protobuf::Struct* s = struct_type.mutable_object();
+  s->mutable_fields()->operator[]("k1").set_number_value(123);
+  s->mutable_fields()->operator[]("k2").set_bool_value(true);
+  s->mutable_fields()->operator[]("k3").set_string_value("-222222222");
+  s->mutable_fields()->operator[]("k4").set_string_value("33333333");
+
+  options_.struct_integers_as_strings = true;
+  ResetProtoWriter();
+
+  ow_->StartObject("")
+      ->StartObject("object")
+      ->RenderDouble("k1", 123)
+      ->RenderBool("k2", true)
+      ->RenderInt64("k3", -222222222)
+      ->RenderUint64("k4", 33333333)
+      ->EndObject()
+      ->EndObject();
+  CheckOutput(struct_type);
+}
+
 class ProtoStreamObjectWriterMapTest : public BaseProtoStreamObjectWriterTest {
  protected:
   ProtoStreamObjectWriterMapTest()
diff --git a/src/google/protobuf/util/internal/testdata/books.proto b/src/google/protobuf/util/internal/testdata/books.proto
index 82b8176..101a2bf 100644
--- a/src/google/protobuf/util/internal/testdata/books.proto
+++ b/src/google/protobuf/util/internal/testdata/books.proto
@@ -56,6 +56,13 @@
   optional Publisher publisher = 9;
   repeated Label labels = 10;
 
+  enum Type {
+    FICTION = 1;
+    KIDS = 2;
+    ACTION_AND_ADVENTURE = 3;
+  }
+  optional Type type = 11;
+
   extensions 200 to 499;
 }
 
diff --git a/src/google/protobuf/util/internal/type_info_test_helper.cc b/src/google/protobuf/util/internal/type_info_test_helper.cc
index 1b9c515..49e18ed 100644
--- a/src/google/protobuf/util/internal/type_info_test_helper.cc
+++ b/src/google/protobuf/util/internal/type_info_test_helper.cc
@@ -102,13 +102,13 @@
 }
 
 ProtoStreamObjectWriter* TypeInfoTestHelper::NewProtoWriter(
-    const string& type_url, strings::ByteSink* output,
-    ErrorListener* listener) {
+    const string& type_url, strings::ByteSink* output, ErrorListener* listener,
+    const ProtoStreamObjectWriter::Options& options) {
   const google::protobuf::Type* type = typeinfo_->GetTypeByTypeUrl(type_url);
   switch (type_) {
     case USE_TYPE_RESOLVER: {
       return new ProtoStreamObjectWriter(type_resolver_.get(), *type, output,
-                                         listener);
+                                         listener, options);
     }
   }
   GOOGLE_LOG(FATAL) << "Can not reach here.";
diff --git a/src/google/protobuf/util/internal/type_info_test_helper.h b/src/google/protobuf/util/internal/type_info_test_helper.h
index 6916a73..1a27984 100644
--- a/src/google/protobuf/util/internal/type_info_test_helper.h
+++ b/src/google/protobuf/util/internal/type_info_test_helper.h
@@ -39,8 +39,8 @@
 
 #include <google/protobuf/io/coded_stream.h>
 #include <google/protobuf/descriptor.h>
-#include <google/protobuf/util/internal/type_info.h>
 #include <google/protobuf/util/internal/default_value_objectwriter.h>
+#include <google/protobuf/util/internal/type_info.h>
 #include <google/protobuf/util/internal/protostream_objectsource.h>
 #include <google/protobuf/util/internal/protostream_objectwriter.h>
 #include <google/protobuf/util/type_resolver.h>
@@ -77,9 +77,9 @@
   ProtoStreamObjectSource* NewProtoSource(io::CodedInputStream* coded_input,
                                           const string& type_url);
 
-  ProtoStreamObjectWriter* NewProtoWriter(const string& type_url,
-                                          strings::ByteSink* output,
-                                          ErrorListener* listener);
+  ProtoStreamObjectWriter* NewProtoWriter(
+      const string& type_url, strings::ByteSink* output,
+      ErrorListener* listener, const ProtoStreamObjectWriter::Options& options);
 
   DefaultValueObjectWriter* NewDefaultValueWriter(const string& type_url,
                                                   ObjectWriter* writer);
diff --git a/src/google/protobuf/util/internal/utility.cc b/src/google/protobuf/util/internal/utility.cc
index 1ddf248..ee7a51f 100644
--- a/src/google/protobuf/util/internal/utility.cc
+++ b/src/google/protobuf/util/internal/utility.cc
@@ -222,6 +222,7 @@
       if (!result.empty() && is_cap &&
           (!was_cap || (i + 1 < input.size() && ascii_islower(input[i + 1])))) {
         first_word = false;
+        result.push_back(input[i]);
       } else {
         result.push_back(ascii_tolower(input[i]));
         continue;
@@ -231,9 +232,13 @@
       if (ascii_islower(input[i])) {
         result.push_back(ascii_toupper(input[i]));
         continue;
+      } else {
+        result.push_back(input[i]);
+        continue;
       }
+    } else {
+      result.push_back(ascii_tolower(input[i]));
     }
-    result.push_back(input[i]);
   }
   return result;
 }
diff --git a/src/google/protobuf/util/json_util.cc b/src/google/protobuf/util/json_util.cc
index c3b8d50..2659320 100644
--- a/src/google/protobuf/util/json_util.cc
+++ b/src/google/protobuf/util/json_util.cc
@@ -102,6 +102,42 @@
                             options);
 }
 
+namespace {
+class StatusErrorListener : public converter::ErrorListener {
+ public:
+  StatusErrorListener() : status_(util::Status::OK) {}
+  virtual ~StatusErrorListener() {}
+
+  util::Status GetStatus() { return status_; }
+
+  virtual void InvalidName(const converter::LocationTrackerInterface& loc,
+                           StringPiece unknown_name, StringPiece message) {
+    status_ = util::Status(util::error::INVALID_ARGUMENT,
+                             loc.ToString() + ": " + message.ToString());
+  }
+
+  virtual void InvalidValue(const converter::LocationTrackerInterface& loc,
+                            StringPiece type_name, StringPiece value) {
+    status_ =
+        util::Status(util::error::INVALID_ARGUMENT,
+                       loc.ToString() + ": invalid value " + value.ToString() +
+                           " for type " + type_name.ToString());
+  }
+
+  virtual void MissingField(const converter::LocationTrackerInterface& loc,
+                            StringPiece missing_name) {
+    status_ = util::Status(
+        util::error::INVALID_ARGUMENT,
+        loc.ToString() + ": missing field " + missing_name.ToString());
+  }
+
+ private:
+  util::Status status_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StatusErrorListener);
+};
+}  // namespace
+
 util::Status JsonToBinaryStream(TypeResolver* resolver,
                                   const string& type_url,
                                   io::ZeroCopyInputStream* json_input,
@@ -109,7 +145,7 @@
   google::protobuf::Type type;
   RETURN_IF_ERROR(resolver->ResolveMessageType(type_url, &type));
   internal::ZeroCopyStreamByteSink sink(binary_output);
-  converter::NoopErrorListener listener;
+  StatusErrorListener listener;
   converter::ProtoStreamObjectWriter proto_writer(resolver, type, &sink,
                                                   &listener);
 
@@ -123,7 +159,7 @@
   }
   RETURN_IF_ERROR(parser.FinishParse());
 
-  return util::Status::OK;
+  return listener.GetStatus();
 }
 
 util::Status JsonToBinaryString(TypeResolver* resolver,
diff --git a/src/google/protobuf/util/json_util_test.cc b/src/google/protobuf/util/json_util_test.cc
index da68495..a4d3cc9 100644
--- a/src/google/protobuf/util/json_util_test.cc
+++ b/src/google/protobuf/util/json_util_test.cc
@@ -77,8 +77,11 @@
 
   bool FromJson(const string& json, Message* message) {
     string binary;
-    GOOGLE_CHECK_OK(JsonToBinaryString(
-        resolver_.get(), GetTypeUrl(message->GetDescriptor()), json, &binary));
+    if (!JsonToBinaryString(resolver_.get(),
+                            GetTypeUrl(message->GetDescriptor()), json, &binary)
+             .ok()) {
+      return false;
+    }
     return message->ParseFromString(binary);
   }
 
@@ -99,28 +102,36 @@
       ToJson(m, options));
 }
 
-// TODO(skarvaje): Uncomment after cl/96232915 is submitted.
-// TEST_F(JsonUtilTest, TestDefaultValues) {
-  // TestMessage m;
-  // JsonOptions options;
-  // EXPECT_EQ("{}", ToJson(m, options));
-  // options.always_print_primitive_fields = true;
-  // EXPECT_EQ(
-      // "{\"boolValue\":false,"
-      // "\"int32Value\":0,"
-      // "\"int64Value\":\"0\","
-      // "\"uint32Value\":0,"
-      // "\"uint64Value\":\"0\","
-      // "\"floatValue\":0,"
-      // "\"doubleValue\":0,"
-      // "\"stringValue\":\"\","
-      // "\"bytesValue\":\"\","
-      // // TODO(xiaofeng): The default enum value should be FOO. I believe
-      // // this is a bug in DefaultValueObjectWriter.
-      // "\"enumValue\":null"
-      // "}",
-      // ToJson(m, options));
-// }
+TEST_F(JsonUtilTest, TestDefaultValues) {
+  TestMessage m;
+  JsonOptions options;
+  EXPECT_EQ("{}", ToJson(m, options));
+  options.always_print_primitive_fields = true;
+  EXPECT_EQ(
+      "{\"boolValue\":false,"
+      "\"int32Value\":0,"
+      "\"int64Value\":\"0\","
+      "\"uint32Value\":0,"
+      "\"uint64Value\":\"0\","
+      "\"floatValue\":0,"
+      "\"doubleValue\":0,"
+      "\"stringValue\":\"\","
+      "\"bytesValue\":\"\","
+      "\"enumValue\":\"FOO\","
+      "\"repeatedBoolValue\":[],"
+      "\"repeatedInt32Value\":[],"
+      "\"repeatedInt64Value\":[],"
+      "\"repeatedUint32Value\":[],"
+      "\"repeatedUint64Value\":[],"
+      "\"repeatedFloatValue\":[],"
+      "\"repeatedDoubleValue\":[],"
+      "\"repeatedStringValue\":[],"
+      "\"repeatedBytesValue\":[],"
+      "\"repeatedEnumValue\":[],"
+      "\"repeatedMessageValue\":[]"
+      "}",
+      ToJson(m, options));
+}
 
 TEST_F(JsonUtilTest, ParseMessage) {
   // Some random message but good enough to verify that the parsing warpper
@@ -158,6 +169,15 @@
   EXPECT_EQ(message.DebugString(), other.DebugString());
 }
 
+TEST_F(JsonUtilTest, TestParseErrors) {
+  TestMessage m;
+  JsonOptions options;
+  // Parsing should fail if the field name can not be recognized.
+  EXPECT_FALSE(FromJson("{\"unknownName\":0}", &m));
+  // Parsing should fail if the value is invalid.
+  EXPECT_FALSE(FromJson("{\"int32Value\":2147483648}", &m));
+}
+
 typedef pair<char*, int> Segment;
 // A ZeroCopyOutputStream that writes to multiple buffers.
 class SegmentedZeroCopyOutputStream : public io::ZeroCopyOutputStream {
diff --git a/src/google/protobuf/util/message_differencer.cc b/src/google/protobuf/util/message_differencer.cc
index 0f879dc..b2b3242 100644
--- a/src/google/protobuf/util/message_differencer.cc
+++ b/src/google/protobuf/util/message_differencer.cc
@@ -47,6 +47,7 @@
 
 #include <google/protobuf/stubs/callback.h>
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/stringprintf.h>
 #include <google/protobuf/any.h>
 #include <google/protobuf/io/printer.h>
@@ -1021,7 +1022,7 @@
       any.GetDescriptor()->file()->pool()->FindMessageTypeByName(
           full_type_name);
   if (desc == NULL) {
-    GOOGLE_LOG(ERROR) << "Proto type '" << full_type_name << "' not found";
+    GOOGLE_DLOG(ERROR) << "Proto type '" << full_type_name << "' not found";
     return false;
   }
 
@@ -1031,7 +1032,7 @@
   data->reset(dynamic_message_factory_->GetPrototype(desc)->New());
   string serialized_value = reflection->GetString(any, value_field);
   if (!(*data)->ParseFromString(serialized_value)) {
-    GOOGLE_LOG(ERROR) << "Failed to parse value for " << full_type_name;
+    GOOGLE_DLOG(ERROR) << "Failed to parse value for " << full_type_name;
     return false;
   }
   return true;
diff --git a/src/google/protobuf/wire_format_lite.cc b/src/google/protobuf/wire_format_lite.cc
index 7f1093c..f251707 100644
--- a/src/google/protobuf/wire_format_lite.cc
+++ b/src/google/protobuf/wire_format_lite.cc
@@ -412,7 +412,7 @@
                                  io::CodedOutputStream* output) {
   // String is for UTF-8 text only
   WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
-  GOOGLE_CHECK(value.size() <= kint32max);
+  GOOGLE_CHECK_LE(value.size(), kint32max);
   output->WriteVarint32(value.size());
   output->WriteString(value);
 }
@@ -421,14 +421,14 @@
     io::CodedOutputStream* output) {
   // String is for UTF-8 text only
   WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
-  GOOGLE_CHECK(value.size() <= kint32max);
+  GOOGLE_CHECK_LE(value.size(), kint32max);
   output->WriteVarint32(value.size());
   output->WriteRawMaybeAliased(value.data(), value.size());
 }
 void WireFormatLite::WriteBytes(int field_number, const string& value,
                                 io::CodedOutputStream* output) {
   WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
-  GOOGLE_CHECK(value.size() <= kint32max);
+  GOOGLE_CHECK_LE(value.size(), kint32max);
   output->WriteVarint32(value.size());
   output->WriteString(value);
 }
@@ -436,7 +436,7 @@
     int field_number, const string& value,
     io::CodedOutputStream* output) {
   WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
-  GOOGLE_CHECK(value.size() <= kint32max);
+  GOOGLE_CHECK_LE(value.size(), kint32max);
   output->WriteVarint32(value.size());
   output->WriteRawMaybeAliased(value.data(), value.size());
 }
diff --git a/src/google/protobuf/wire_format_lite_inl.h b/src/google/protobuf/wire_format_lite_inl.h
index 79493ca..7bce21c 100644
--- a/src/google/protobuf/wire_format_lite_inl.h
+++ b/src/google/protobuf/wire_format_lite_inl.h
@@ -274,8 +274,8 @@
     // The number of bytes each type occupies on the wire.
     const int per_value_size = tag_size + sizeof(value);
 
-    int elements_available = min(values->Capacity() - values->size(),
-                                 size / per_value_size);
+    int elements_available =
+        std::min(values->Capacity() - values->size(), size / per_value_size);
     int num_read = 0;
     while (num_read < elements_available &&
            (buffer = io::CodedInputStream::ExpectTagFromArray(
@@ -367,7 +367,7 @@
     bytes_limit = input->BytesUntilLimit();
   } else {
     bytes_limit =
-        min(bytes_limit, static_cast<int64>(input->BytesUntilLimit()));
+        std::min(bytes_limit, static_cast<int64>(input->BytesUntilLimit()));
   }
   if (bytes_limit >= new_bytes) {
     // Fast-path that pre-allocates *values to the final size.
diff --git a/src/google/protobuf/wire_format_unittest.cc b/src/google/protobuf/wire_format_unittest.cc
index 15c3755..4e4add6 100644
--- a/src/google/protobuf/wire_format_unittest.cc
+++ b/src/google/protobuf/wire_format_unittest.cc
@@ -45,6 +45,7 @@
 
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
 #include <google/protobuf/stubs/stl_util.h>
diff --git a/src/google/protobuf/wrappers.pb.cc b/src/google/protobuf/wrappers.pb.cc
index 212dd21..204c802 100644
--- a/src/google/protobuf/wrappers.pb.cc
+++ b/src/google/protobuf/wrappers.pb.cc
@@ -263,10 +263,11 @@
     "e\030\001 \001(\004\"\033\n\nInt32Value\022\r\n\005value\030\001 \001(\005\"\034\n\013"
     "UInt32Value\022\r\n\005value\030\001 \001(\r\"\032\n\tBoolValue\022"
     "\r\n\005value\030\001 \001(\010\"\034\n\013StringValue\022\r\n\005value\030\001"
-    " \001(\t\"\033\n\nBytesValue\022\r\n\005value\030\001 \001(\014BS\n\023com"
-    ".google.protobufB\rWrappersProtoP\001\240\001\001\370\001\001\242"
-    "\002\003GPB\252\002\036Google.Protobuf.WellKnownTypesb\006"
-    "proto3", 406);
+    " \001(\t\"\033\n\nBytesValue\022\r\n\005value\030\001 \001(\014B\177\n\023com"
+    ".google.protobufB\rWrappersProtoP\001Z*githu"
+    "b.com/golang/protobuf/ptypes/wrappers\240\001\001"
+    "\370\001\001\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTyp"
+    "esb\006proto3", 450);
   ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
     "google/protobuf/wrappers.proto", &protobuf_RegisterTypes);
   DoubleValue::default_instance_ = new DoubleValue();
diff --git a/src/google/protobuf/wrappers.proto b/src/google/protobuf/wrappers.proto
index 040d8a2..4828ad9 100644
--- a/src/google/protobuf/wrappers.proto
+++ b/src/google/protobuf/wrappers.proto
@@ -39,6 +39,7 @@
 
 option csharp_namespace = "Google.Protobuf.WellKnownTypes";
 option cc_enable_arenas = true;
+option go_package = "github.com/golang/protobuf/ptypes/wrappers";
 option java_package = "com.google.protobuf";
 option java_outer_classname = "WrappersProto";
 option java_multiple_files = true;