When registering extensions, save the TcParse table too.

This allow starting the parse without a virtual function to _InternalParse.

PiperOrigin-RevId: 618209046
pull/16164/head
Protobuf Team Bot 8 months ago committed by Copybara-Service
parent 39f6eba7fc
commit 8e377ef4b6
  1. 14
      src/google/protobuf/compiler/cpp/message.cc
  2. 1
      src/google/protobuf/compiler/java/java_features.pb.cc
  3. 4
      src/google/protobuf/compiler/plugin.pb.cc
  4. 1
      src/google/protobuf/cpp_features.pb.cc
  5. 32
      src/google/protobuf/descriptor.pb.cc
  6. 2
      src/google/protobuf/extension_set.cc
  7. 2
      src/google/protobuf/extension_set.h
  8. 3
      src/google/protobuf/extension_set_heavy.cc
  9. 46
      src/google/protobuf/generated_message_tctable_impl.h
  10. 29
      src/google/protobuf/generated_message_tctable_lite.cc
  11. 12
      src/google/protobuf/message_lite.cc
  12. 4
      src/google/protobuf/message_lite.h

@ -3551,6 +3551,19 @@ void MessageGenerator::GenerateClassData(io::Printer* p) {
{
{"on_demand_register_arena_dtor", on_demand_register_arena_dtor},
{"pin_weak_descriptor", pin_weak_descriptor},
{"table",
[&] {
// Map entries use the dynamic parser.
if (IsMapEntryMessage(descriptor_)) {
p->Emit(R"cc(
nullptr, // tc_table
)cc");
} else {
p->Emit(R"cc(
&_table_.header,
)cc");
}
}},
{"tracker_on_get_metadata",
[&] {
if (HasTracker(descriptor_, options_)) {
@ -3571,6 +3584,7 @@ void MessageGenerator::GenerateClassData(io::Printer* p) {
PROTOBUF_CONSTINIT static const ::$proto_ns$::MessageLite::
ClassDataFull _data_ = {
{
$table$,
$on_demand_register_arena_dtor$,
PROTOBUF_FIELD_OFFSET($classname$, $cached_size$),
false,

@ -177,6 +177,7 @@ JavaFeatures::GetClassData() const {
PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::
ClassDataFull _data_ = {
{
&_table_.header,
nullptr, // OnDemandRegisterArenaDtor
PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_._cached_size_),
false,

@ -363,6 +363,7 @@ Version::GetClassData() const {
PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::
ClassDataFull _data_ = {
{
&_table_.header,
nullptr, // OnDemandRegisterArenaDtor
PROTOBUF_FIELD_OFFSET(Version, _impl_._cached_size_),
false,
@ -674,6 +675,7 @@ CodeGeneratorRequest::GetClassData() const {
PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::
ClassDataFull _data_ = {
{
&_table_.header,
nullptr, // OnDemandRegisterArenaDtor
PROTOBUF_FIELD_OFFSET(CodeGeneratorRequest, _impl_._cached_size_),
false,
@ -1021,6 +1023,7 @@ CodeGeneratorResponse_File::GetClassData() const {
PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::
ClassDataFull _data_ = {
{
&_table_.header,
nullptr, // OnDemandRegisterArenaDtor
PROTOBUF_FIELD_OFFSET(CodeGeneratorResponse_File, _impl_._cached_size_),
false,
@ -1341,6 +1344,7 @@ CodeGeneratorResponse::GetClassData() const {
PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::
ClassDataFull _data_ = {
{
&_table_.header,
nullptr, // OnDemandRegisterArenaDtor
PROTOBUF_FIELD_OFFSET(CodeGeneratorResponse, _impl_._cached_size_),
false,

@ -177,6 +177,7 @@ CppFeatures::GetClassData() const {
PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::
ClassDataFull _data_ = {
{
&_table_.header,
nullptr, // OnDemandRegisterArenaDtor
PROTOBUF_FIELD_OFFSET(CppFeatures, _impl_._cached_size_),
false,

@ -2384,6 +2384,7 @@ FileDescriptorSet::GetClassData() const {
PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::
ClassDataFull _data_ = {
{
&_table_.header,
nullptr, // OnDemandRegisterArenaDtor
PROTOBUF_FIELD_OFFSET(FileDescriptorSet, _impl_._cached_size_),
false,
@ -2617,6 +2618,7 @@ FileDescriptorProto::GetClassData() const {
PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::
ClassDataFull _data_ = {
{
&_table_.header,
nullptr, // OnDemandRegisterArenaDtor
PROTOBUF_FIELD_OFFSET(FileDescriptorProto, _impl_._cached_size_),
false,
@ -3191,6 +3193,7 @@ DescriptorProto_ExtensionRange::GetClassData() const {
PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::
ClassDataFull _data_ = {
{
&_table_.header,
nullptr, // OnDemandRegisterArenaDtor
PROTOBUF_FIELD_OFFSET(DescriptorProto_ExtensionRange, _impl_._cached_size_),
false,
@ -3453,6 +3456,7 @@ DescriptorProto_ReservedRange::GetClassData() const {
PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::
ClassDataFull _data_ = {
{
&_table_.header,
nullptr, // OnDemandRegisterArenaDtor
PROTOBUF_FIELD_OFFSET(DescriptorProto_ReservedRange, _impl_._cached_size_),
false,
@ -3711,6 +3715,7 @@ DescriptorProto::GetClassData() const {
PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::
ClassDataFull _data_ = {
{
&_table_.header,
nullptr, // OnDemandRegisterArenaDtor
PROTOBUF_FIELD_OFFSET(DescriptorProto, _impl_._cached_size_),
false,
@ -4203,6 +4208,7 @@ ExtensionRangeOptions_Declaration::GetClassData() const {
PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::
ClassDataFull _data_ = {
{
&_table_.header,
nullptr, // OnDemandRegisterArenaDtor
PROTOBUF_FIELD_OFFSET(ExtensionRangeOptions_Declaration, _impl_._cached_size_),
false,
@ -4536,6 +4542,7 @@ ExtensionRangeOptions::GetClassData() const {
PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::
ClassDataFull _data_ = {
{
&_table_.header,
nullptr, // OnDemandRegisterArenaDtor
PROTOBUF_FIELD_OFFSET(ExtensionRangeOptions, _impl_._cached_size_),
false,
@ -4887,6 +4894,7 @@ FieldDescriptorProto::GetClassData() const {
PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::
ClassDataFull _data_ = {
{
&_table_.header,
nullptr, // OnDemandRegisterArenaDtor
PROTOBUF_FIELD_OFFSET(FieldDescriptorProto, _impl_._cached_size_),
false,
@ -5389,6 +5397,7 @@ OneofDescriptorProto::GetClassData() const {
PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::
ClassDataFull _data_ = {
{
&_table_.header,
nullptr, // OnDemandRegisterArenaDtor
PROTOBUF_FIELD_OFFSET(OneofDescriptorProto, _impl_._cached_size_),
false,
@ -5630,6 +5639,7 @@ EnumDescriptorProto_EnumReservedRange::GetClassData() const {
PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::
ClassDataFull _data_ = {
{
&_table_.header,
nullptr, // OnDemandRegisterArenaDtor
PROTOBUF_FIELD_OFFSET(EnumDescriptorProto_EnumReservedRange, _impl_._cached_size_),
false,
@ -5878,6 +5888,7 @@ EnumDescriptorProto::GetClassData() const {
PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::
ClassDataFull _data_ = {
{
&_table_.header,
nullptr, // OnDemandRegisterArenaDtor
PROTOBUF_FIELD_OFFSET(EnumDescriptorProto, _impl_._cached_size_),
false,
@ -6223,6 +6234,7 @@ EnumValueDescriptorProto::GetClassData() const {
PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::
ClassDataFull _data_ = {
{
&_table_.header,
nullptr, // OnDemandRegisterArenaDtor
PROTOBUF_FIELD_OFFSET(EnumValueDescriptorProto, _impl_._cached_size_),
false,
@ -6511,6 +6523,7 @@ ServiceDescriptorProto::GetClassData() const {
PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::
ClassDataFull _data_ = {
{
&_table_.header,
nullptr, // OnDemandRegisterArenaDtor
PROTOBUF_FIELD_OFFSET(ServiceDescriptorProto, _impl_._cached_size_),
false,
@ -6815,6 +6828,7 @@ MethodDescriptorProto::GetClassData() const {
PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::
ClassDataFull _data_ = {
{
&_table_.header,
nullptr, // OnDemandRegisterArenaDtor
PROTOBUF_FIELD_OFFSET(MethodDescriptorProto, _impl_._cached_size_),
false,
@ -7226,6 +7240,7 @@ FileOptions::GetClassData() const {
PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::
ClassDataFull _data_ = {
{
&_table_.header,
nullptr, // OnDemandRegisterArenaDtor
PROTOBUF_FIELD_OFFSET(FileOptions, _impl_._cached_size_),
false,
@ -8012,6 +8027,7 @@ MessageOptions::GetClassData() const {
PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::
ClassDataFull _data_ = {
{
&_table_.header,
nullptr, // OnDemandRegisterArenaDtor
PROTOBUF_FIELD_OFFSET(MessageOptions, _impl_._cached_size_),
false,
@ -8384,6 +8400,7 @@ FieldOptions_EditionDefault::GetClassData() const {
PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::
ClassDataFull _data_ = {
{
&_table_.header,
nullptr, // OnDemandRegisterArenaDtor
PROTOBUF_FIELD_OFFSET(FieldOptions_EditionDefault, _impl_._cached_size_),
false,
@ -8645,6 +8662,7 @@ FieldOptions::GetClassData() const {
PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::
ClassDataFull _data_ = {
{
&_table_.header,
nullptr, // OnDemandRegisterArenaDtor
PROTOBUF_FIELD_OFFSET(FieldOptions, _impl_._cached_size_),
false,
@ -9179,6 +9197,7 @@ OneofOptions::GetClassData() const {
PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::
ClassDataFull _data_ = {
{
&_table_.header,
nullptr, // OnDemandRegisterArenaDtor
PROTOBUF_FIELD_OFFSET(OneofOptions, _impl_._cached_size_),
false,
@ -9455,6 +9474,7 @@ EnumOptions::GetClassData() const {
PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::
ClassDataFull _data_ = {
{
&_table_.header,
nullptr, // OnDemandRegisterArenaDtor
PROTOBUF_FIELD_OFFSET(EnumOptions, _impl_._cached_size_),
false,
@ -9805,6 +9825,7 @@ EnumValueOptions::GetClassData() const {
PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::
ClassDataFull _data_ = {
{
&_table_.header,
nullptr, // OnDemandRegisterArenaDtor
PROTOBUF_FIELD_OFFSET(EnumValueOptions, _impl_._cached_size_),
false,
@ -10131,6 +10152,7 @@ ServiceOptions::GetClassData() const {
PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::
ClassDataFull _data_ = {
{
&_table_.header,
nullptr, // OnDemandRegisterArenaDtor
PROTOBUF_FIELD_OFFSET(ServiceOptions, _impl_._cached_size_),
false,
@ -10438,6 +10460,7 @@ MethodOptions::GetClassData() const {
PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::
ClassDataFull _data_ = {
{
&_table_.header,
nullptr, // OnDemandRegisterArenaDtor
PROTOBUF_FIELD_OFFSET(MethodOptions, _impl_._cached_size_),
false,
@ -10760,6 +10783,7 @@ UninterpretedOption_NamePart::GetClassData() const {
PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::
ClassDataFull _data_ = {
{
&_table_.header,
nullptr, // OnDemandRegisterArenaDtor
PROTOBUF_FIELD_OFFSET(UninterpretedOption_NamePart, _impl_._cached_size_),
false,
@ -11020,6 +11044,7 @@ UninterpretedOption::GetClassData() const {
PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::
ClassDataFull _data_ = {
{
&_table_.header,
nullptr, // OnDemandRegisterArenaDtor
PROTOBUF_FIELD_OFFSET(UninterpretedOption, _impl_._cached_size_),
false,
@ -11405,6 +11430,7 @@ FeatureSet::GetClassData() const {
PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::
ClassDataFull _data_ = {
{
&_table_.header,
nullptr, // OnDemandRegisterArenaDtor
PROTOBUF_FIELD_OFFSET(FeatureSet, _impl_._cached_size_),
false,
@ -11756,6 +11782,7 @@ FeatureSetDefaults_FeatureSetEditionDefault::GetClassData() const {
PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::
ClassDataFull _data_ = {
{
&_table_.header,
nullptr, // OnDemandRegisterArenaDtor
PROTOBUF_FIELD_OFFSET(FeatureSetDefaults_FeatureSetEditionDefault, _impl_._cached_size_),
false,
@ -12014,6 +12041,7 @@ FeatureSetDefaults::GetClassData() const {
PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::
ClassDataFull _data_ = {
{
&_table_.header,
nullptr, // OnDemandRegisterArenaDtor
PROTOBUF_FIELD_OFFSET(FeatureSetDefaults, _impl_._cached_size_),
false,
@ -12289,6 +12317,7 @@ SourceCodeInfo_Location::GetClassData() const {
PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::
ClassDataFull _data_ = {
{
&_table_.header,
nullptr, // OnDemandRegisterArenaDtor
PROTOBUF_FIELD_OFFSET(SourceCodeInfo_Location, _impl_._cached_size_),
false,
@ -12616,6 +12645,7 @@ SourceCodeInfo::GetClassData() const {
PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::
ClassDataFull _data_ = {
{
&_table_.header,
nullptr, // OnDemandRegisterArenaDtor
PROTOBUF_FIELD_OFFSET(SourceCodeInfo, _impl_._cached_size_),
false,
@ -12829,6 +12859,7 @@ GeneratedCodeInfo_Annotation::GetClassData() const {
PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::
ClassDataFull _data_ = {
{
&_table_.header,
nullptr, // OnDemandRegisterArenaDtor
PROTOBUF_FIELD_OFFSET(GeneratedCodeInfo_Annotation, _impl_._cached_size_),
false,
@ -13148,6 +13179,7 @@ GeneratedCodeInfo::GetClassData() const {
PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::
ClassDataFull _data_ = {
{
&_table_.header,
nullptr, // OnDemandRegisterArenaDtor
PROTOBUF_FIELD_OFFSET(GeneratedCodeInfo, _impl_._cached_size_),
false,

@ -154,7 +154,7 @@ void ExtensionSet::RegisterMessageExtension(const MessageLite* extendee,
type == WireFormatLite::TYPE_GROUP);
ExtensionInfo info(extendee, number, type, is_repeated, is_packed,
verify_func, is_lazy);
info.message_info = {prototype};
info.message_info = {prototype, prototype->GetTcParseTable()};
Register(info);
}

@ -139,6 +139,8 @@ struct ExtensionInfo {
struct MessageInfo {
const MessageLite* prototype;
// The TcParse table used for this object. Never null.
const internal::TcParseTableBase* tc_table;
};
union {

@ -24,6 +24,7 @@
#include "google/protobuf/extension_set.h"
#include "google/protobuf/extension_set_inl.h"
#include "google/protobuf/generated_message_reflection.h"
#include "google/protobuf/generated_message_tctable_impl.h"
#include "google/protobuf/io/coded_stream.h"
#include "google/protobuf/message.h"
#include "google/protobuf/message_lite.h"
@ -272,6 +273,8 @@ bool DescriptorPoolExtensionFinder::Find(int number, ExtensionInfo* output) {
if (extension->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
output->message_info.prototype =
factory_->GetPrototype(extension->message_type());
output->message_info.tc_table =
output->message_info.prototype->GetTcParseTable();
ABSL_CHECK(output->message_info.prototype != nullptr)
<< "Extension factory's GetPrototype() returned nullptr; extension: "
<< extension->full_name();

@ -14,6 +14,7 @@
#include <type_traits>
#include <utility>
#include "absl/base/optimization.h"
#include "absl/log/absl_log.h"
#include "google/protobuf/extension_set.h"
#include "google/protobuf/generated_message_tctable_decl.h"
@ -377,6 +378,22 @@ class PROTOBUF_EXPORT TcParser final {
return &T::_table_.header;
}
static PROTOBUF_ALWAYS_INLINE const char* ParseMessage(
MessageLite* msg, const char* ptr, ParseContext* ctx,
const TcParseTableBase* tc_table) {
return ctx->ParseLengthDelimitedInlined(ptr, [&](const char* ptr) {
return ParseLoopInlined(msg, ptr, ctx, tc_table);
});
}
static PROTOBUF_ALWAYS_INLINE const char* ParseGroup(
MessageLite* msg, const char* ptr, ParseContext* ctx,
const TcParseTableBase* tc_table, uint32_t start_tag) {
return ctx->ParseGroupInlined(ptr, start_tag, [&](const char* ptr) {
return ParseLoopInlined(msg, ptr, ctx, tc_table);
});
}
// == ABI of the tail call functions ==
// All the tail call functions have the same signature as required by clang's
// `musttail` attribute. However, their ABIs are different.
@ -976,6 +993,35 @@ inline PROTOBUF_ALWAYS_INLINE const char* TcParser::ToParseLoop(
return ptr;
}
inline PROTOBUF_ALWAYS_INLINE const char* TcParser::ParseLoopInlined(
MessageLite* msg, const char* ptr, ParseContext* ctx,
const TcParseTableBase* table) {
// Note: TagDispatch uses a dispatch table at "&table->fast_entries".
// For fast dispatch, we'd like to have a pointer to that, but if we use
// that expression, there's no easy way to get back to "table", which we also
// need during dispatch. It turns out that "table + 1" points exactly to
// fast_entries, so we just increment table by 1 here, to get the register
// holding the value we want.
table += 1;
while (!ctx->Done(&ptr)) {
#if defined(__GNUC__)
// Note: this asm prevents the compiler (clang, specifically) from
// believing (thanks to CSE) that it needs to dedicate a registeer both
// to "table" and "&table->fast_entries".
// TODO: remove this asm
asm("" : "+r"(table));
#endif
ptr = TagDispatch(msg, ptr, ctx, TcFieldData::DefaultInit(), table - 1, 0);
if (ptr == nullptr) break;
if (ctx->LastTag() != 1) break; // Ended on terminating tag
}
table -= 1;
if (ABSL_PREDICT_FALSE(table->has_post_loop_handler)) {
return table->post_loop_handler(msg, ptr, ctx);
}
return ptr;
}
// Prints the type card as or of labels, using known higher level labels.
// Used for code generation, but also useful for debugging.
PROTOBUF_EXPORT std::string TypeCardToString(uint16_t type_card);

@ -73,35 +73,6 @@ const char* TcParser::GenericFallbackLite(PROTOBUF_TC_PARAM_DECL) {
// Core fast parsing implementation:
//////////////////////////////////////////////////////////////////////////////
inline PROTOBUF_ALWAYS_INLINE const char* TcParser::ParseLoopInlined(
MessageLite* msg, const char* ptr, ParseContext* ctx,
const TcParseTableBase* table) {
// Note: TagDispatch uses a dispatch table at "&table->fast_entries".
// For fast dispatch, we'd like to have a pointer to that, but if we use
// that expression, there's no easy way to get back to "table", which we also
// need during dispatch. It turns out that "table + 1" points exactly to
// fast_entries, so we just increment table by 1 here, to get the register
// holding the value we want.
table += 1;
while (!ctx->Done(&ptr)) {
#if defined(__GNUC__)
// Note: this asm prevents the compiler (clang, specifically) from
// believing (thanks to CSE) that it needs to dedicate a registeer both
// to "table" and "&table->fast_entries".
// TODO: remove this asm
asm("" : "+r"(table));
#endif
ptr = TagDispatch(msg, ptr, ctx, TcFieldData::DefaultInit(), table - 1, 0);
if (ptr == nullptr) break;
if (ctx->LastTag() != 1) break; // Ended on terminating tag
}
table -= 1;
if (ABSL_PREDICT_FALSE(table->has_post_loop_handler)) {
return table->post_loop_handler(msg, ptr, ctx);
}
return ptr;
}
PROTOBUF_NOINLINE const char* TcParser::ParseLoop(
MessageLite* msg, const char* ptr, ParseContext* ctx,
const TcParseTableBase* table) {

@ -46,18 +46,22 @@
namespace google {
namespace protobuf {
const char* MessageLite::_InternalParse(const char* ptr,
internal::ParseContext* ctx) {
const internal::TcParseTableBase* MessageLite::GetTcParseTable() const {
auto* data = GetClassData();
ABSL_DCHECK(data != nullptr);
auto* tc_table = data->tc_table;
if (ABSL_PREDICT_FALSE(tc_table == nullptr)) {
ABSL_DCHECK(!data->is_lite);
tc_table = data->full().descriptor_methods->get_tc_table(*this);
return data->full().descriptor_methods->get_tc_table(*this);
}
return tc_table;
}
return internal::TcParser::ParseLoop(this, ptr, ctx, tc_table);
const char* MessageLite::_InternalParse(const char* ptr,
internal::ParseContext* ctx) {
return internal::TcParser::ParseLoopInlined(this, ptr, ctx,
GetTcParseTable());
}
std::string MessageLite::GetTypeName() const {

@ -126,6 +126,7 @@ class SwapFieldHelper;
class ParseContext;
struct DescriptorTable;
class DescriptorPoolExtensionFinder;
class ExtensionSet;
class LazyField;
class RepeatedPtrFieldBase;
@ -516,6 +517,8 @@ class PROTOBUF_EXPORT MessageLite {
return static_cast<T*>(Arena::CopyConstruct<T>(arena, &from));
}
const internal::TcParseTableBase* GetTcParseTable() const;
inline explicit MessageLite(Arena* arena) : _internal_metadata_(arena) {}
// We use a secondary vtable for descriptor based methods. This way ClassData
@ -660,6 +663,7 @@ class PROTOBUF_EXPORT MessageLite {
friend class FastReflectionStringSetter;
friend class Message;
friend class Reflection;
friend class internal::DescriptorPoolExtensionFinder;
friend class internal::ExtensionSet;
friend class internal::LazyField;
friend class internal::SwapFieldHelper;

Loading…
Cancel
Save