From 4eed4eb244e851da37dc7022bd79bd5807479e2b Mon Sep 17 00:00:00 2001 From: Protobuf Team Bot Date: Tue, 12 Sep 2023 06:43:43 -0700 Subject: [PATCH] Move `GetClassData` into `MessageLite`. This table will be used to replace several virtual functions to reduce binary size and code duplication. In this same change we replace `OnDemandRegisterArenaDtor` with an entry on the table to keep the number of virtual functions in `MessageLite` the same to avoid growth in space constrained systems. We will migrate other functions in future changes. PiperOrigin-RevId: 564706001 --- src/google/protobuf/compiler/cpp/message.cc | 59 +++++++++++++-------- src/google/protobuf/compiler/plugin.pb.cc | 4 ++ src/google/protobuf/cpp_features.pb.cc | 1 + src/google/protobuf/descriptor.pb.cc | 32 +++++++++++ src/google/protobuf/message.cc | 3 -- src/google/protobuf/message.h | 19 ------- src/google/protobuf/message_lite.cc | 12 +++++ src/google/protobuf/message_lite.h | 19 ++++++- 8 files changed, 104 insertions(+), 45 deletions(-) diff --git a/src/google/protobuf/compiler/cpp/message.cc b/src/google/protobuf/compiler/cpp/message.cc index 908c9e9cb8..9767ff1a2e 100644 --- a/src/google/protobuf/compiler/cpp/message.cc +++ b/src/google/protobuf/compiler/cpp/message.cc @@ -1564,20 +1564,19 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* p) { switch (NeedsArenaDestructor()) { case ArenaDtorNeeds::kOnDemand: - format( - "private:\n" - "static void ArenaDtor(void* object);\n" - "inline void OnDemandRegisterArenaDtor(::$proto_ns$::Arena* arena) " - "override {\n" - " if (arena == nullptr || ($inlined_string_donated_array$[0] & " - "0x1u) " - "== " - "0) {\n" - " return;\n" - " }\n" - " $inlined_string_donated_array$[0] &= 0xFFFFFFFEu;\n" - " arena->OwnCustomDestructor(this, &$classname$::ArenaDtor);\n" - "}\n"); + p->Emit(R"cc( + private: + static void ArenaDtor(void* object); + static void OnDemandRegisterArenaDtor(MessageLite& msg, + ::$proto_ns$::Arena& arena) { + auto& this_ = static_cast<$classname$&>(msg); + if ((this_.$inlined_string_donated_array$[0] & 0x1u) == 0) { + return; + } + this_.$inlined_string_donated_array$[0] &= 0xFFFFFFFEu; + arena.OwnCustomDestructor(&this_, &$classname$::ArenaDtor); + } + )cc"); break; case ArenaDtorNeeds::kRequired: format( @@ -3917,14 +3916,30 @@ void MessageGenerator::GenerateMergeFrom(io::Printer* p) { // a "from" message that is the same type as the message being merged // into, rather than a generic Message. - p->Emit(R"cc( - const ::$proto_ns$::Message::ClassData $classname$::_class_data_ = { - $classname$::MergeImpl, - }; - const ::$proto_ns$::Message::ClassData* $classname$::GetClassData() const { - return &_class_data_; - } - )cc"); + p->Emit( + { + {"on_demand_register_arena_dtor", + [&] { + if (NeedsArenaDestructor() == ArenaDtorNeeds::kOnDemand) { + p->Emit(R"cc( + $classname$::OnDemandRegisterArenaDtor, + )cc"); + } else { + p->Emit(R"cc( + nullptr, // OnDemandRegisterArenaDtor + )cc"); + } + }}, + }, + R"cc( + const ::$proto_ns$::Message::ClassData $classname$::_class_data_ = { + $classname$::MergeImpl, + $on_demand_register_arena_dtor$, + }; + const ::$proto_ns$::Message::ClassData* $classname$::GetClassData() const { + return &_class_data_; + } + )cc"); } else { // Generate CheckTypeAndMergeFrom(). format( diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc index 83641bfc0e..221e150b87 100644 --- a/src/google/protobuf/compiler/plugin.pb.cc +++ b/src/google/protobuf/compiler/plugin.pb.cc @@ -543,6 +543,7 @@ const ::_pbi::TcParseTable<2, 4, 0, 47, 2> Version::_table_ = { const ::google::protobuf::Message::ClassData Version::_class_data_ = { Version::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor }; const ::google::protobuf::Message::ClassData* Version::GetClassData() const { return &_class_data_; @@ -888,6 +889,7 @@ const ::_pbi::TcParseTable<3, 5, 3, 79, 2> CodeGeneratorRequest::_table_ = { const ::google::protobuf::Message::ClassData CodeGeneratorRequest::_class_data_ = { CodeGeneratorRequest::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor }; const ::google::protobuf::Message::ClassData* CodeGeneratorRequest::GetClassData() const { return &_class_data_; @@ -1218,6 +1220,7 @@ const ::_pbi::TcParseTable<2, 4, 1, 86, 2> CodeGeneratorResponse_File::_table_ = const ::google::protobuf::Message::ClassData CodeGeneratorResponse_File::_class_data_ = { CodeGeneratorResponse_File::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor }; const ::google::protobuf::Message::ClassData* CodeGeneratorResponse_File::GetClassData() const { return &_class_data_; @@ -1491,6 +1494,7 @@ const ::_pbi::TcParseTable<2, 3, 1, 60, 2> CodeGeneratorResponse::_table_ = { const ::google::protobuf::Message::ClassData CodeGeneratorResponse::_class_data_ = { CodeGeneratorResponse::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor }; const ::google::protobuf::Message::ClassData* CodeGeneratorResponse::GetClassData() const { return &_class_data_; diff --git a/src/google/protobuf/cpp_features.pb.cc b/src/google/protobuf/cpp_features.pb.cc index e305a36cce..d09d469cc2 100644 --- a/src/google/protobuf/cpp_features.pb.cc +++ b/src/google/protobuf/cpp_features.pb.cc @@ -309,6 +309,7 @@ const ::_pbi::TcParseTable<1, 2, 1, 0, 2> CppFeatures::_table_ = { const ::google::protobuf::Message::ClassData CppFeatures::_class_data_ = { CppFeatures::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor }; const ::google::protobuf::Message::ClassData* CppFeatures::GetClassData() const { return &_class_data_; diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc index f7f236ef87..68dfc8147b 100644 --- a/src/google/protobuf/descriptor.pb.cc +++ b/src/google/protobuf/descriptor.pb.cc @@ -2481,6 +2481,7 @@ constexpr ::_pbi::TcParseTable<0, 1, 1, 0, 2> FileDescriptorSet::_table_ = { const ::google::protobuf::Message::ClassData FileDescriptorSet::_class_data_ = { FileDescriptorSet::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor }; const ::google::protobuf::Message::ClassData* FileDescriptorSet::GetClassData() const { return &_class_data_; @@ -3052,6 +3053,7 @@ constexpr ::_pbi::TcParseTable<4, 14, 7, 86, 2> FileDescriptorProto::_table_ = { const ::google::protobuf::Message::ClassData FileDescriptorProto::_class_data_ = { FileDescriptorProto::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor }; const ::google::protobuf::Message::ClassData* FileDescriptorProto::GetClassData() const { return &_class_data_; @@ -3389,6 +3391,7 @@ constexpr ::_pbi::TcParseTable<2, 3, 1, 0, 2> DescriptorProto_ExtensionRange::_t const ::google::protobuf::Message::ClassData DescriptorProto_ExtensionRange::_class_data_ = { DescriptorProto_ExtensionRange::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor }; const ::google::protobuf::Message::ClassData* DescriptorProto_ExtensionRange::GetClassData() const { return &_class_data_; @@ -3620,6 +3623,7 @@ constexpr ::_pbi::TcParseTable<1, 2, 0, 0, 2> DescriptorProto_ReservedRange::_ta const ::google::protobuf::Message::ClassData DescriptorProto_ReservedRange::_class_data_ = { DescriptorProto_ReservedRange::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor }; const ::google::protobuf::Message::ClassData* DescriptorProto_ReservedRange::GetClassData() const { return &_class_data_; @@ -4071,6 +4075,7 @@ constexpr ::_pbi::TcParseTable<4, 10, 8, 65, 2> DescriptorProto::_table_ = { const ::google::protobuf::Message::ClassData DescriptorProto::_class_data_ = { DescriptorProto::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor }; const ::google::protobuf::Message::ClassData* DescriptorProto::GetClassData() const { return &_class_data_; @@ -4439,6 +4444,7 @@ constexpr ::_pbi::TcParseTable<3, 5, 0, 71, 2> ExtensionRangeOptions_Declaration const ::google::protobuf::Message::ClassData ExtensionRangeOptions_Declaration::_class_data_ = { ExtensionRangeOptions_Declaration::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor }; const ::google::protobuf::Message::ClassData* ExtensionRangeOptions_Declaration::GetClassData() const { return &_class_data_; @@ -4763,6 +4769,7 @@ constexpr ::_pbi::TcParseTable<3, 4, 4, 0, 12> ExtensionRangeOptions::_table_ = const ::google::protobuf::Message::ClassData ExtensionRangeOptions::_class_data_ = { ExtensionRangeOptions::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor }; const ::google::protobuf::Message::ClassData* ExtensionRangeOptions::GetClassData() const { return &_class_data_; @@ -5293,6 +5300,7 @@ constexpr ::_pbi::TcParseTable<4, 11, 3, 96, 2> FieldDescriptorProto::_table_ = const ::google::protobuf::Message::ClassData FieldDescriptorProto::_class_data_ = { FieldDescriptorProto::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor }; const ::google::protobuf::Message::ClassData* FieldDescriptorProto::GetClassData() const { return &_class_data_; @@ -5592,6 +5600,7 @@ constexpr ::_pbi::TcParseTable<1, 2, 1, 49, 2> OneofDescriptorProto::_table_ = { const ::google::protobuf::Message::ClassData OneofDescriptorProto::_class_data_ = { OneofDescriptorProto::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor }; const ::google::protobuf::Message::ClassData* OneofDescriptorProto::GetClassData() const { return &_class_data_; @@ -5818,6 +5827,7 @@ constexpr ::_pbi::TcParseTable<1, 2, 0, 0, 2> EnumDescriptorProto_EnumReservedRa const ::google::protobuf::Message::ClassData EnumDescriptorProto_EnumReservedRange::_class_data_ = { EnumDescriptorProto_EnumReservedRange::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor }; const ::google::protobuf::Message::ClassData* EnumDescriptorProto_EnumReservedRange::GetClassData() const { return &_class_data_; @@ -6146,6 +6156,7 @@ constexpr ::_pbi::TcParseTable<3, 5, 3, 61, 2> EnumDescriptorProto::_table_ = { const ::google::protobuf::Message::ClassData EnumDescriptorProto::_class_data_ = { EnumDescriptorProto::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor }; const ::google::protobuf::Message::ClassData* EnumDescriptorProto::GetClassData() const { return &_class_data_; @@ -6441,6 +6452,7 @@ constexpr ::_pbi::TcParseTable<2, 3, 1, 53, 2> EnumValueDescriptorProto::_table_ const ::google::protobuf::Message::ClassData EnumValueDescriptorProto::_class_data_ = { EnumValueDescriptorProto::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor }; const ::google::protobuf::Message::ClassData* EnumValueDescriptorProto::GetClassData() const { return &_class_data_; @@ -6730,6 +6742,7 @@ constexpr ::_pbi::TcParseTable<2, 3, 2, 51, 2> ServiceDescriptorProto::_table_ = const ::google::protobuf::Message::ClassData ServiceDescriptorProto::_class_data_ = { ServiceDescriptorProto::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor }; const ::google::protobuf::Message::ClassData* ServiceDescriptorProto::GetClassData() const { return &_class_data_; @@ -7109,6 +7122,7 @@ constexpr ::_pbi::TcParseTable<3, 6, 1, 71, 2> MethodDescriptorProto::_table_ = const ::google::protobuf::Message::ClassData MethodDescriptorProto::_class_data_ = { MethodDescriptorProto::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor }; const ::google::protobuf::Message::ClassData* MethodDescriptorProto::GetClassData() const { return &_class_data_; @@ -7938,6 +7952,7 @@ constexpr ::_pbi::TcParseTable<5, 22, 3, 202, 12> FileOptions::_table_ = { const ::google::protobuf::Message::ClassData FileOptions::_class_data_ = { FileOptions::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor }; const ::google::protobuf::Message::ClassData* FileOptions::GetClassData() const { return &_class_data_; @@ -8409,6 +8424,7 @@ constexpr ::_pbi::TcParseTable<3, 7, 2, 0, 7> MessageOptions::_table_ = { const ::google::protobuf::Message::ClassData MessageOptions::_class_data_ = { MessageOptions::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor }; const ::google::protobuf::Message::ClassData* MessageOptions::GetClassData() const { return &_class_data_; @@ -8707,6 +8723,7 @@ constexpr ::_pbi::TcParseTable<2, 3, 1, 64, 2> FieldOptions_EditionDefault::_tab const ::google::protobuf::Message::ClassData FieldOptions_EditionDefault::_class_data_ = { FieldOptions_EditionDefault::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor }; const ::google::protobuf::Message::ClassData* FieldOptions_EditionDefault::GetClassData() const { return &_class_data_; @@ -9235,6 +9252,7 @@ constexpr ::_pbi::TcParseTable<4, 13, 7, 0, 7> FieldOptions::_table_ = { const ::google::protobuf::Message::ClassData FieldOptions::_class_data_ = { FieldOptions::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor }; const ::google::protobuf::Message::ClassData* FieldOptions::GetClassData() const { return &_class_data_; @@ -9535,6 +9553,7 @@ constexpr ::_pbi::TcParseTable<2, 2, 2, 0, 7> OneofOptions::_table_ = { const ::google::protobuf::Message::ClassData OneofOptions::_class_data_ = { OneofOptions::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor }; const ::google::protobuf::Message::ClassData* OneofOptions::GetClassData() const { return &_class_data_; @@ -9870,6 +9889,7 @@ constexpr ::_pbi::TcParseTable<3, 5, 2, 0, 7> EnumOptions::_table_ = { const ::google::protobuf::Message::ClassData EnumOptions::_class_data_ = { EnumOptions::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor }; const ::google::protobuf::Message::ClassData* EnumOptions::GetClassData() const { return &_class_data_; @@ -10205,6 +10225,7 @@ constexpr ::_pbi::TcParseTable<3, 4, 2, 0, 7> EnumValueOptions::_table_ = { const ::google::protobuf::Message::ClassData EnumValueOptions::_class_data_ = { EnumValueOptions::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor }; const ::google::protobuf::Message::ClassData* EnumValueOptions::GetClassData() const { return &_class_data_; @@ -10506,6 +10527,7 @@ constexpr ::_pbi::TcParseTable<2, 3, 2, 0, 12> ServiceOptions::_table_ = { const ::google::protobuf::Message::ClassData ServiceOptions::_class_data_ = { ServiceOptions::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor }; const ::google::protobuf::Message::ClassData* ServiceOptions::GetClassData() const { return &_class_data_; @@ -10840,6 +10862,7 @@ constexpr ::_pbi::TcParseTable<3, 4, 3, 0, 12> MethodOptions::_table_ = { const ::google::protobuf::Message::ClassData MethodOptions::_class_data_ = { MethodOptions::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor }; const ::google::protobuf::Message::ClassData* MethodOptions::GetClassData() const { return &_class_data_; @@ -11098,6 +11121,7 @@ constexpr ::_pbi::TcParseTable<1, 2, 0, 62, 2> UninterpretedOption_NamePart::_ta const ::google::protobuf::Message::ClassData UninterpretedOption_NamePart::_class_data_ = { UninterpretedOption_NamePart::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor }; const ::google::protobuf::Message::ClassData* UninterpretedOption_NamePart::GetClassData() const { return &_class_data_; @@ -11480,6 +11504,7 @@ constexpr ::_pbi::TcParseTable<3, 7, 1, 75, 2> UninterpretedOption::_table_ = { const ::google::protobuf::Message::ClassData UninterpretedOption::_class_data_ = { UninterpretedOption::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor }; const ::google::protobuf::Message::ClassData* UninterpretedOption::GetClassData() const { return &_class_data_; @@ -11831,6 +11856,7 @@ constexpr ::_pbi::TcParseTable<3, 5, 5, 0, 2> FeatureSet::_table_ = { const ::google::protobuf::Message::ClassData FeatureSet::_class_data_ = { FeatureSet::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor }; const ::google::protobuf::Message::ClassData* FeatureSet::GetClassData() const { return &_class_data_; @@ -12129,6 +12155,7 @@ constexpr ::_pbi::TcParseTable<2, 3, 2, 75, 2> FeatureSetDefaults_FeatureSetEdit const ::google::protobuf::Message::ClassData FeatureSetDefaults_FeatureSetEditionDefault::_class_data_ = { FeatureSetDefaults_FeatureSetEditionDefault::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor }; const ::google::protobuf::Message::ClassData* FeatureSetDefaults_FeatureSetEditionDefault::GetClassData() const { return &_class_data_; @@ -12476,6 +12503,7 @@ constexpr ::_pbi::TcParseTable<3, 5, 3, 73, 2> FeatureSetDefaults::_table_ = { const ::google::protobuf::Message::ClassData FeatureSetDefaults::_class_data_ = { FeatureSetDefaults::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor }; const ::google::protobuf::Message::ClassData* FeatureSetDefaults::GetClassData() const { return &_class_data_; @@ -12832,6 +12860,7 @@ constexpr ::_pbi::TcParseTable<3, 5, 0, 106, 2> SourceCodeInfo_Location::_table_ const ::google::protobuf::Message::ClassData SourceCodeInfo_Location::_class_data_ = { SourceCodeInfo_Location::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor }; const ::google::protobuf::Message::ClassData* SourceCodeInfo_Location::GetClassData() const { return &_class_data_; @@ -13032,6 +13061,7 @@ constexpr ::_pbi::TcParseTable<0, 1, 1, 0, 2> SourceCodeInfo::_table_ = { const ::google::protobuf::Message::ClassData SourceCodeInfo::_class_data_ = { SourceCodeInfo::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor }; const ::google::protobuf::Message::ClassData* SourceCodeInfo::GetClassData() const { return &_class_data_; @@ -13352,6 +13382,7 @@ constexpr ::_pbi::TcParseTable<3, 5, 1, 64, 2> GeneratedCodeInfo_Annotation::_ta const ::google::protobuf::Message::ClassData GeneratedCodeInfo_Annotation::_class_data_ = { GeneratedCodeInfo_Annotation::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor }; const ::google::protobuf::Message::ClassData* GeneratedCodeInfo_Annotation::GetClassData() const { return &_class_data_; @@ -13559,6 +13590,7 @@ constexpr ::_pbi::TcParseTable<0, 1, 1, 0, 2> GeneratedCodeInfo::_table_ = { const ::google::protobuf::Message::ClassData GeneratedCodeInfo::_class_data_ = { GeneratedCodeInfo::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor }; const ::google::protobuf::Message::ClassData* GeneratedCodeInfo::GetClassData() const { return &_class_data_; diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc index 52f57d2ba6..8b9cd2ef99 100644 --- a/src/google/protobuf/message.cc +++ b/src/google/protobuf/message.cc @@ -99,9 +99,6 @@ void Message::CopyFrom(const Message& from) { } } -void Message::CopyWithSourceCheck(Message& to, const Message& from) { -} - std::string Message::GetTypeName() const { return GetDescriptor()->full_name(); } diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h index 48050b6313..54473777b9 100644 --- a/src/google/protobuf/message.h +++ b/src/google/protobuf/message.h @@ -362,25 +362,6 @@ class PROTOBUF_EXPORT Message : public MessageLite { // to implement GetDescriptor() and GetReflection() above. virtual Metadata GetMetadata() const = 0; - struct ClassData { - // Note: The order of arguments (to, then from) is chosen so that the ABI - // of this function is the same as the MergeFrom method. That is, the - // hidden "this" parameter comes first. - void (*merge_to_from)(Message& to, const Message& from_msg); - }; - // GetClassData() returns a pointer to a ClassData struct which - // exists in global memory and is unique to each subclass. This uniqueness - // property is used in order to quickly determine whether two messages are - // of the same type. - // TODO(jorg): change to pure virtual - virtual const ClassData* GetClassData() const { return nullptr; } - - // CopyWithSourceCheck calls Clear() and then MergeFrom(), and in debug - // builds, checks that calling Clear() on the destination message doesn't - // alter the source. It assumes the messages are known to be of the same - // type, and thus uses GetClassData(). - static void CopyWithSourceCheck(Message& to, const Message& from); - inline explicit Message(Arena* arena) : MessageLite(arena) {} size_t ComputeUnknownFieldsSize(size_t total_size, internal::CachedSize* cached_size) const; diff --git a/src/google/protobuf/message_lite.cc b/src/google/protobuf/message_lite.cc index c854d963d3..4505222763 100644 --- a/src/google/protobuf/message_lite.cc +++ b/src/google/protobuf/message_lite.cc @@ -44,6 +44,18 @@ namespace google { namespace protobuf { +void MessageLite::OnDemandRegisterArenaDtor(Arena* arena) { + if (arena == nullptr) return; + auto* data = GetClassData(); + if (data != nullptr && data->on_demand_register_arena_dtor != nullptr) { + data->on_demand_register_arena_dtor(*this, *arena); + } +} + +const MessageLite::ClassData* MessageLite::GetClassData() const { + return nullptr; +} + std::string MessageLite::InitializationErrorString() const { return "(cannot determine missing fields for lite message)"; } diff --git a/src/google/protobuf/message_lite.h b/src/google/protobuf/message_lite.h index 82abf5bb53..a30c65dfe9 100644 --- a/src/google/protobuf/message_lite.h +++ b/src/google/protobuf/message_lite.h @@ -492,7 +492,7 @@ class PROTOBUF_EXPORT MessageLite { return nullptr; } - virtual void OnDemandRegisterArenaDtor(Arena* /*arena*/) {} + void OnDemandRegisterArenaDtor(Arena* arena); protected: // Message implementations require access to internally visible API. @@ -525,6 +525,23 @@ class PROTOBUF_EXPORT MessageLite { // messages, etc), or owning incoming objects (e.g., set allocated). Arena* GetArenaForAllocation() const { return _internal_metadata_.arena(); } + struct ClassData { + // Note: The order of arguments in the functions is chosen so that it has + // the same ABI as the member function that calls them. Eg the `this` + // pointer becomes the first argument in the free function. + void (*merge_to_from)(Message& to, const Message& from_msg); + void (*on_demand_register_arena_dtor)(MessageLite& msg, Arena& arena); + }; + + // GetClassData() returns a pointer to a ClassData struct which + // exists in global memory and is unique to each subclass. This uniqueness + // property is used in order to quickly determine whether two messages are + // of the same type. + // + // This is a work in progress. Currently only SPEED messages return an + // instance. In the future all message types will return one. + virtual const ClassData* GetClassData() const; + internal::InternalMetadata _internal_metadata_; // The default implementation means there is no cached size and ByteSize