Use faster merge-from in several places in codegen

Emit calls to `MessageLite::MergeFromWithClassData()` or compile-time resolved `ClassData::merge_to_from()` instead of `MergeFrom()` and `CheckTypeAndMergeFrom()` in codegen wherever possible.

PiperOrigin-RevId: 797006178
diff --git a/src/google/protobuf/compiler/cpp/field_generators/message_field.cc b/src/google/protobuf/compiler/cpp/field_generators/message_field.cc
index f4acb9c..44f7a6b 100644
--- a/src/google/protobuf/compiler/cpp/field_generators/message_field.cc
+++ b/src/google/protobuf/compiler/cpp/field_generators/message_field.cc
@@ -335,7 +335,9 @@
           if (_this->$field_$ == nullptr) {
             _this->$field_$ = from.$field_$->New(arena);
           }
-          _this->$field_$->CheckTypeAndMergeFrom(*from.$field_$);
+          static const auto merge_to_from =
+              ::google::protobuf::internal::GetClassData(*_this->$field_$)->merge_to_from;
+          merge_to_from(*_this->$field_$, *from.$field_$);
         )cc");
   } else if (should_split()) {
     p->Emit(
@@ -354,7 +356,9 @@
       if (_this->$field_$ == nullptr) {
         _this->$field_$ = $superclass$::CopyConstruct(arena, *from.$field_$);
       } else {
-        _this->$field_$->MergeFrom(*from.$field_$);
+        static const auto merge_to_from =
+            ::google::protobuf::internal::GetClassData(*_this->$field_$)->merge_to_from;
+        merge_to_from(*_this->$field_$, *from.$field_$);
       }
     )cc");
   }
diff --git a/src/google/protobuf/compiler/cpp/helpers.cc b/src/google/protobuf/compiler/cpp/helpers.cc
index 358ef61..9b9b793 100644
--- a/src/google/protobuf/compiler/cpp/helpers.cc
+++ b/src/google/protobuf/compiler/cpp/helpers.cc
@@ -88,8 +88,8 @@
   static constexpr const char* kMessageKnownMethods[] = {
       "GetDescriptor", "GetReflection",   "default_instance",
       "Swap",          "UnsafeArenaSwap", "New",
-      "CopyFrom",      "MergeFrom",       "IsInitialized",
-      "GetMetadata",   "Clear",
+      "CopyFrom",      "MergeFrom",       "MergeFromWithClassData",
+      "IsInitialized", "GetMetadata",     "Clear",
   };
   static const auto* const methods = new absl::flat_hash_set<absl::string_view>(
       std::begin(kMessageKnownMethods), std::end(kMessageKnownMethods));
diff --git a/src/google/protobuf/compiler/cpp/message.cc b/src/google/protobuf/compiler/cpp/message.cc
index 8b2b1ea..2ca278d 100644
--- a/src/google/protobuf/compiler/cpp/message.cc
+++ b/src/google/protobuf/compiler/cpp/message.cc
@@ -3542,7 +3542,7 @@
           //~ Force alignment
           $pb$::Arena* $nullable$ arena, const $classname$& from)
           : $classname$(arena) {
-        MergeFrom(from);
+        MessageTraits<$classname$>::class_data()->merge_to_from(*this, from);
       }
     )cc");
   } else if (CanUseTrivialCopy()) {
diff --git a/src/google/protobuf/message_lite.h b/src/google/protobuf/message_lite.h
index 25264ef..2670763f 100644
--- a/src/google/protobuf/message_lite.h
+++ b/src/google/protobuf/message_lite.h
@@ -76,6 +76,7 @@
 
 namespace compiler {
 namespace cpp {
+class MessageGenerator;
 class MessageTableTester;
 }  // namespace cpp
 }  // namespace compiler
@@ -1105,6 +1106,7 @@
   friend class Message;
   friend class Reflection;
   friend class TypeId;
+  friend class compiler::cpp::MessageGenerator;
   friend class compiler::cpp::MessageTableTester;
   friend class internal::DescriptorPoolExtensionFinder;
   friend class internal::ExtensionSet;
diff --git a/src/google/protobuf/reflection_ops_unittest.cc b/src/google/protobuf/reflection_ops_unittest.cc
index fee690d..3ffd54e 100644
--- a/src/google/protobuf/reflection_ops_unittest.cc
+++ b/src/google/protobuf/reflection_ops_unittest.cc
@@ -11,6 +11,7 @@
 
 #include "google/protobuf/reflection_ops.h"
 
+#include <cstddef>
 #include <cstdint>
 #include <string>
 #include <utility>