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>