From 34b34beb1aae0c697d62378418367e537bf1f8ba Mon Sep 17 00:00:00 2001 From: Samuel Benzaquen Date: Tue, 16 Jun 2026 10:56:54 -0700 Subject: [PATCH] Move `unknown_field_set.h` to `protobuf_lite` to allow direct usage from the parser without a virtual dispatch. Move the minimal set of function from `unknown_field_set.cc` to `unknown_field_set_lite.cc` Change the parser fallback function to separate the extensions case from the unknown field case. This makes both cases faster. PiperOrigin-RevId: 933183605 --- src/google/protobuf/BUILD.bazel | 2 + .../compiler/csharp/c_sharp_features.pb.cc | 2 +- .../compiler/java/java_features.pb.cc | 4 +- src/google/protobuf/compiler/plugin.pb.cc | 8 +- src/google/protobuf/cpp_features.pb.cc | 2 +- src/google/protobuf/cpp_file_options.pb.cc | 2 +- src/google/protobuf/descriptor.pb.cc | 46 +++---- .../generated_message_tctable_full.cc | 8 +- .../protobuf/generated_message_tctable_gen.cc | 5 +- .../protobuf/generated_message_tctable_impl.h | 65 +++------ .../generated_message_tctable_lite.cc | 62 +++++++-- .../protobuf/json_enumvalue_options.pb.cc | 2 +- src/google/protobuf/message.cc | 2 - src/google/protobuf/message_lite.cc | 4 + src/google/protobuf/unknown_field_set.cc | 104 -------------- src/google/protobuf/unknown_field_set_lite.cc | 128 ++++++++++++++++++ 16 files changed, 239 insertions(+), 207 deletions(-) create mode 100644 src/google/protobuf/unknown_field_set_lite.cc diff --git a/src/google/protobuf/BUILD.bazel b/src/google/protobuf/BUILD.bazel index 9b25d1ad23d14..f155ca84857b9 100644 --- a/src/google/protobuf/BUILD.bazel +++ b/src/google/protobuf/BUILD.bazel @@ -712,6 +712,7 @@ cc_library( "raw_ptr.cc", "repeated_field.cc", "repeated_ptr_field.cc", + "unknown_field_set_lite.cc", "wire_format_lite.cc", ], # TODO Fix ODR violations across BUILD.bazel files. @@ -747,6 +748,7 @@ cc_library( "runtime_version.h", "serial_arena.h", "thread_safe_arena.h", + "unknown_field_set.h", "wire_format_lite.h", ], copts = COPTS + select({ diff --git a/src/google/protobuf/compiler/csharp/c_sharp_features.pb.cc b/src/google/protobuf/compiler/csharp/c_sharp_features.pb.cc index 263400808dd52..6a6686982bf69 100755 --- a/src/google/protobuf/compiler/csharp/c_sharp_features.pb.cc +++ b/src/google/protobuf/compiler/csharp/c_sharp_features.pb.cc @@ -56,7 +56,7 @@ constexpr CSharpFeatures::ParseTableT_ CSharpFeatures::InternalGenerateParseTabl offsetof(ParseTableT_, field_names), // no aux_entries class_data, nullptr, // post_loop_handler - ::_pbi::TcParser::GenericFallback, // fallback + ::_pbi::TcParser::MpUnknownFields, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE ::_pbi::TcParser::GetTable<::pb::CSharpFeatures>(), // to_prefetch #endif // PROTOBUF_PREFETCH_PARSE_TABLE diff --git a/src/google/protobuf/compiler/java/java_features.pb.cc b/src/google/protobuf/compiler/java/java_features.pb.cc index 158c66406ebbe..542f784144638 100644 --- a/src/google/protobuf/compiler/java/java_features.pb.cc +++ b/src/google/protobuf/compiler/java/java_features.pb.cc @@ -56,7 +56,7 @@ constexpr JavaFeatures_NestInFileClassFeature::ParseTableT_ JavaFeatures_NestInF offsetof(ParseTableT_, field_names), // no aux_entries class_data, nullptr, // post_loop_handler - ::_pbi::TcParser::GenericFallback, // fallback + ::_pbi::TcParser::MpUnknownFields, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE ::_pbi::TcParser::GetTable<::pb::JavaFeatures_NestInFileClassFeature>(), // to_prefetch #endif // PROTOBUF_PREFETCH_PARSE_TABLE @@ -182,7 +182,7 @@ constexpr JavaFeatures::ParseTableT_ JavaFeatures::InternalGenerateParseTable_(c offsetof(ParseTableT_, aux_entries), class_data, nullptr, // post_loop_handler - ::_pbi::TcParser::GenericFallback, // fallback + ::_pbi::TcParser::MpUnknownFields, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE ::_pbi::TcParser::GetTable<::pb::JavaFeatures>(), // to_prefetch #endif // PROTOBUF_PREFETCH_PARSE_TABLE diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc index 6b979944e22b9..a7b4f668bff10 100644 --- a/src/google/protobuf/compiler/plugin.pb.cc +++ b/src/google/protobuf/compiler/plugin.pb.cc @@ -64,7 +64,7 @@ constexpr Version::ParseTableT_ Version::InternalGenerateParseTable_(const ::_pb offsetof(ParseTableT_, field_names), // no aux_entries class_data, nullptr, // post_loop_handler - ::_pbi::TcParser::GenericFallback, // fallback + ::_pbi::TcParser::MpUnknownFields, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE ::_pbi::TcParser::GetTable<::google::protobuf::compiler::Version>(), // to_prefetch #endif // PROTOBUF_PREFETCH_PARSE_TABLE @@ -227,7 +227,7 @@ constexpr CodeGeneratorResponse_File::ParseTableT_ CodeGeneratorResponse_File::I offsetof(ParseTableT_, aux_entries), class_data, nullptr, // post_loop_handler - ::_pbi::TcParser::GenericFallback, // fallback + ::_pbi::TcParser::MpUnknownFields, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE ::_pbi::TcParser::GetTable<::google::protobuf::compiler::CodeGeneratorResponse_File>(), // to_prefetch #endif // PROTOBUF_PREFETCH_PARSE_TABLE @@ -400,7 +400,7 @@ constexpr CodeGeneratorResponse::ParseTableT_ CodeGeneratorResponse::InternalGen offsetof(ParseTableT_, aux_entries), class_data, nullptr, // post_loop_handler - ::_pbi::TcParser::GenericFallback, // fallback + ::_pbi::TcParser::MpUnknownFields, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE ::_pbi::TcParser::GetTable<::google::protobuf::compiler::CodeGeneratorResponse>(), // to_prefetch #endif // PROTOBUF_PREFETCH_PARSE_TABLE @@ -583,7 +583,7 @@ constexpr CodeGeneratorRequest::ParseTableT_ CodeGeneratorRequest::InternalGener offsetof(ParseTableT_, aux_entries), class_data, nullptr, // post_loop_handler - ::_pbi::TcParser::GenericFallback, // fallback + ::_pbi::TcParser::MpUnknownFields, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE ::_pbi::TcParser::GetTable<::google::protobuf::compiler::CodeGeneratorRequest>(), // to_prefetch #endif // PROTOBUF_PREFETCH_PARSE_TABLE diff --git a/src/google/protobuf/cpp_features.pb.cc b/src/google/protobuf/cpp_features.pb.cc index 9aa7a9814d1c8..9659bac7d9808 100644 --- a/src/google/protobuf/cpp_features.pb.cc +++ b/src/google/protobuf/cpp_features.pb.cc @@ -56,7 +56,7 @@ constexpr CppFeatures::ParseTableT_ CppFeatures::InternalGenerateParseTable_(con offsetof(ParseTableT_, aux_entries), class_data, nullptr, // post_loop_handler - ::_pbi::TcParser::GenericFallback, // fallback + ::_pbi::TcParser::MpUnknownFields, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE ::_pbi::TcParser::GetTable<::pb::CppFeatures>(), // to_prefetch #endif // PROTOBUF_PREFETCH_PARSE_TABLE diff --git a/src/google/protobuf/cpp_file_options.pb.cc b/src/google/protobuf/cpp_file_options.pb.cc index 92862c7312a6d..f349dd8dcd042 100644 --- a/src/google/protobuf/cpp_file_options.pb.cc +++ b/src/google/protobuf/cpp_file_options.pb.cc @@ -57,7 +57,7 @@ constexpr CppFileOptions::ParseTableT_ CppFileOptions::InternalGenerateParseTabl offsetof(ParseTableT_, field_names), // no aux_entries class_data, nullptr, // post_loop_handler - ::_pbi::TcParser::GenericFallback, // fallback + ::_pbi::TcParser::MpUnknownFields, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE ::_pbi::TcParser::GetTable<::pb::file::CppFileOptions>(), // to_prefetch #endif // PROTOBUF_PREFETCH_PARSE_TABLE diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc index 5d523b50479e8..b4ba33f6266d4 100644 --- a/src/google/protobuf/descriptor.pb.cc +++ b/src/google/protobuf/descriptor.pb.cc @@ -128,7 +128,7 @@ constexpr UninterpretedOption_NamePart::ParseTableT_ UninterpretedOption_NamePar offsetof(ParseTableT_, field_names), // no aux_entries class_data, nullptr, // post_loop_handler - ::_pbi::TcParser::GenericFallback, // fallback + ::_pbi::TcParser::MpUnknownFields, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE ::_pbi::TcParser::GetTable<::google::protobuf::UninterpretedOption_NamePart>(), // to_prefetch #endif // PROTOBUF_PREFETCH_PARSE_TABLE @@ -283,7 +283,7 @@ constexpr SourceCodeInfo_Location::ParseTableT_ SourceCodeInfo_Location::Interna offsetof(ParseTableT_, field_names), // no aux_entries class_data, nullptr, // post_loop_handler - ::_pbi::TcParser::GenericFallback, // fallback + ::_pbi::TcParser::MpUnknownFields, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE ::_pbi::TcParser::GetTable<::google::protobuf::SourceCodeInfo_Location>(), // to_prefetch #endif // PROTOBUF_PREFETCH_PARSE_TABLE @@ -476,7 +476,7 @@ constexpr GeneratedCodeInfo_Annotation::ParseTableT_ GeneratedCodeInfo_Annotatio offsetof(ParseTableT_, aux_entries), class_data, nullptr, // post_loop_handler - ::_pbi::TcParser::GenericFallback, // fallback + ::_pbi::TcParser::MpUnknownFields, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE ::_pbi::TcParser::GetTable<::google::protobuf::GeneratedCodeInfo_Annotation>(), // to_prefetch #endif // PROTOBUF_PREFETCH_PARSE_TABLE @@ -661,7 +661,7 @@ constexpr FieldOptions_FeatureSupport::ParseTableT_ FieldOptions_FeatureSupport: offsetof(ParseTableT_, aux_entries), class_data, nullptr, // post_loop_handler - ::_pbi::TcParser::GenericFallback, // fallback + ::_pbi::TcParser::MpUnknownFields, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE ::_pbi::TcParser::GetTable<::google::protobuf::FieldOptions_FeatureSupport>(), // to_prefetch #endif // PROTOBUF_PREFETCH_PARSE_TABLE @@ -846,7 +846,7 @@ constexpr FieldOptions_EditionDefault::ParseTableT_ FieldOptions_EditionDefault: offsetof(ParseTableT_, aux_entries), class_data, nullptr, // post_loop_handler - ::_pbi::TcParser::GenericFallback, // fallback + ::_pbi::TcParser::MpUnknownFields, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE ::_pbi::TcParser::GetTable<::google::protobuf::FieldOptions_EditionDefault>(), // to_prefetch #endif // PROTOBUF_PREFETCH_PARSE_TABLE @@ -1001,7 +1001,7 @@ constexpr FeatureSet_VisibilityFeature::ParseTableT_ FeatureSet_VisibilityFeatur offsetof(ParseTableT_, field_names), // no aux_entries class_data, nullptr, // post_loop_handler - ::_pbi::TcParser::GenericFallback, // fallback + ::_pbi::TcParser::MpUnknownFields, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE ::_pbi::TcParser::GetTable<::google::protobuf::FeatureSet_VisibilityFeature>(), // to_prefetch #endif // PROTOBUF_PREFETCH_PARSE_TABLE @@ -1131,7 +1131,7 @@ constexpr FeatureSet_ProtoLimitsFeature::ParseTableT_ FeatureSet_ProtoLimitsFeat offsetof(ParseTableT_, field_names), // no aux_entries class_data, nullptr, // post_loop_handler - ::_pbi::TcParser::GenericFallback, // fallback + ::_pbi::TcParser::MpUnknownFields, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE ::_pbi::TcParser::GetTable<::google::protobuf::FeatureSet_ProtoLimitsFeature>(), // to_prefetch #endif // PROTOBUF_PREFETCH_PARSE_TABLE @@ -1482,7 +1482,7 @@ constexpr ExtensionRangeOptions_Declaration::ParseTableT_ ExtensionRangeOptions_ offsetof(ParseTableT_, field_names), // no aux_entries class_data, nullptr, // post_loop_handler - ::_pbi::TcParser::GenericFallback, // fallback + ::_pbi::TcParser::MpUnknownFields, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE ::_pbi::TcParser::GetTable<::google::protobuf::ExtensionRangeOptions_Declaration>(), // to_prefetch #endif // PROTOBUF_PREFETCH_PARSE_TABLE @@ -1663,7 +1663,7 @@ constexpr EnumDescriptorProto_EnumReservedRange::ParseTableT_ EnumDescriptorProt offsetof(ParseTableT_, field_names), // no aux_entries class_data, nullptr, // post_loop_handler - ::_pbi::TcParser::GenericFallback, // fallback + ::_pbi::TcParser::MpUnknownFields, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE ::_pbi::TcParser::GetTable<::google::protobuf::EnumDescriptorProto_EnumReservedRange>(), // to_prefetch #endif // PROTOBUF_PREFETCH_PARSE_TABLE @@ -1816,7 +1816,7 @@ constexpr DescriptorProto_ReservedRange::ParseTableT_ DescriptorProto_ReservedRa offsetof(ParseTableT_, field_names), // no aux_entries class_data, nullptr, // post_loop_handler - ::_pbi::TcParser::GenericFallback, // fallback + ::_pbi::TcParser::MpUnknownFields, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE ::_pbi::TcParser::GetTable<::google::protobuf::DescriptorProto_ReservedRange>(), // to_prefetch #endif // PROTOBUF_PREFETCH_PARSE_TABLE @@ -1969,7 +1969,7 @@ constexpr UninterpretedOption::ParseTableT_ UninterpretedOption::InternalGenerat offsetof(ParseTableT_, aux_entries), class_data, nullptr, // post_loop_handler - ::_pbi::TcParser::GenericFallback, // fallback + ::_pbi::TcParser::MpUnknownFields, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE ::_pbi::TcParser::GetTable<::google::protobuf::UninterpretedOption>(), // to_prefetch #endif // PROTOBUF_PREFETCH_PARSE_TABLE @@ -2330,7 +2330,7 @@ constexpr GeneratedCodeInfo::ParseTableT_ GeneratedCodeInfo::InternalGeneratePar offsetof(ParseTableT_, aux_entries), class_data, nullptr, // post_loop_handler - ::_pbi::TcParser::GenericFallback, // fallback + ::_pbi::TcParser::MpUnknownFields, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE ::_pbi::TcParser::GetTable<::google::protobuf::GeneratedCodeInfo>(), // to_prefetch #endif // PROTOBUF_PREFETCH_PARSE_TABLE @@ -2486,7 +2486,7 @@ constexpr FeatureSetDefaults_FeatureSetEditionDefault::ParseTableT_ FeatureSetDe offsetof(ParseTableT_, aux_entries), class_data, nullptr, // post_loop_handler - ::_pbi::TcParser::GenericFallback, // fallback + ::_pbi::TcParser::MpUnknownFields, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE ::_pbi::TcParser::GetTable<::google::protobuf::FeatureSetDefaults_FeatureSetEditionDefault>(), // to_prefetch #endif // PROTOBUF_PREFETCH_PARSE_TABLE @@ -3993,7 +3993,7 @@ constexpr FeatureSetDefaults::ParseTableT_ FeatureSetDefaults::InternalGenerateP offsetof(ParseTableT_, aux_entries), class_data, nullptr, // post_loop_handler - ::_pbi::TcParser::GenericFallback, // fallback + ::_pbi::TcParser::MpUnknownFields, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE ::_pbi::TcParser::GetTable<::google::protobuf::FeatureSetDefaults>(), // to_prefetch #endif // PROTOBUF_PREFETCH_PARSE_TABLE @@ -4748,7 +4748,7 @@ constexpr OneofDescriptorProto::ParseTableT_ OneofDescriptorProto::InternalGener offsetof(ParseTableT_, aux_entries), class_data, nullptr, // post_loop_handler - ::_pbi::TcParser::GenericFallback, // fallback + ::_pbi::TcParser::MpUnknownFields, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE ::_pbi::TcParser::GetTable<::google::protobuf::OneofDescriptorProto>(), // to_prefetch #endif // PROTOBUF_PREFETCH_PARSE_TABLE @@ -4909,7 +4909,7 @@ constexpr MethodDescriptorProto::ParseTableT_ MethodDescriptorProto::InternalGen offsetof(ParseTableT_, aux_entries), class_data, nullptr, // post_loop_handler - ::_pbi::TcParser::GenericFallback, // fallback + ::_pbi::TcParser::MpUnknownFields, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE ::_pbi::TcParser::GetTable<::google::protobuf::MethodDescriptorProto>(), // to_prefetch #endif // PROTOBUF_PREFETCH_PARSE_TABLE @@ -5104,7 +5104,7 @@ constexpr FieldDescriptorProto::ParseTableT_ FieldDescriptorProto::InternalGener offsetof(ParseTableT_, aux_entries), class_data, nullptr, // post_loop_handler - ::_pbi::TcParser::GenericFallback, // fallback + ::_pbi::TcParser::MpUnknownFields, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE ::_pbi::TcParser::GetTable<::google::protobuf::FieldDescriptorProto>(), // to_prefetch #endif // PROTOBUF_PREFETCH_PARSE_TABLE @@ -5340,7 +5340,7 @@ constexpr EnumValueDescriptorProto::ParseTableT_ EnumValueDescriptorProto::Inter offsetof(ParseTableT_, aux_entries), class_data, nullptr, // post_loop_handler - ::_pbi::TcParser::GenericFallback, // fallback + ::_pbi::TcParser::MpUnknownFields, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE ::_pbi::TcParser::GetTable<::google::protobuf::EnumValueDescriptorProto>(), // to_prefetch #endif // PROTOBUF_PREFETCH_PARSE_TABLE @@ -5509,7 +5509,7 @@ constexpr DescriptorProto_ExtensionRange::ParseTableT_ DescriptorProto_Extension offsetof(ParseTableT_, aux_entries), class_data, nullptr, // post_loop_handler - ::_pbi::TcParser::GenericFallback, // fallback + ::_pbi::TcParser::MpUnknownFields, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE ::_pbi::TcParser::GetTable<::google::protobuf::DescriptorProto_ExtensionRange>(), // to_prefetch #endif // PROTOBUF_PREFETCH_PARSE_TABLE @@ -5676,7 +5676,7 @@ constexpr ServiceDescriptorProto::ParseTableT_ ServiceDescriptorProto::InternalG offsetof(ParseTableT_, aux_entries), class_data, nullptr, // post_loop_handler - ::_pbi::TcParser::GenericFallback, // fallback + ::_pbi::TcParser::MpUnknownFields, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE ::_pbi::TcParser::GetTable<::google::protobuf::ServiceDescriptorProto>(), // to_prefetch #endif // PROTOBUF_PREFETCH_PARSE_TABLE @@ -5854,7 +5854,7 @@ constexpr EnumDescriptorProto::ParseTableT_ EnumDescriptorProto::InternalGenerat offsetof(ParseTableT_, aux_entries), class_data, nullptr, // post_loop_handler - ::_pbi::TcParser::GenericFallback, // fallback + ::_pbi::TcParser::MpUnknownFields, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE ::_pbi::TcParser::GetTable<::google::protobuf::EnumDescriptorProto>(), // to_prefetch #endif // PROTOBUF_PREFETCH_PARSE_TABLE @@ -6068,7 +6068,7 @@ constexpr DescriptorProto::ParseTableT_ DescriptorProto::InternalGenerateParseTa offsetof(ParseTableT_, aux_entries), class_data, nullptr, // post_loop_handler - ::_pbi::TcParser::GenericFallback, // fallback + ::_pbi::TcParser::MpUnknownFields, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE ::_pbi::TcParser::GetTable<::google::protobuf::DescriptorProto>(), // to_prefetch #endif // PROTOBUF_PREFETCH_PARSE_TABLE @@ -6365,7 +6365,7 @@ constexpr FileDescriptorProto::ParseTableT_ FileDescriptorProto::InternalGenerat offsetof(ParseTableT_, aux_entries), class_data, nullptr, // post_loop_handler - ::_pbi::TcParser::GenericFallback, // fallback + ::_pbi::TcParser::MpUnknownFields, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE ::_pbi::TcParser::GetTable<::google::protobuf::FileDescriptorProto>(), // to_prefetch #endif // PROTOBUF_PREFETCH_PARSE_TABLE diff --git a/src/google/protobuf/generated_message_tctable_full.cc b/src/google/protobuf/generated_message_tctable_full.cc index 363a80221b7de..842fcaa3fdcd3 100644 --- a/src/google/protobuf/generated_message_tctable_full.cc +++ b/src/google/protobuf/generated_message_tctable_full.cc @@ -48,16 +48,10 @@ namespace protobuf { namespace internal { const char* TcParser::GenericFallback(PROTOBUF_TC_PARAM_DECL) { - PROTOBUF_MUSTTAIL return GenericFallbackImpl( - PROTOBUF_TC_PARAM_PASS); + PROTOBUF_MUSTTAIL return GenericFallbackImpl(PROTOBUF_TC_PARAM_PASS); } const char* TcParser::ReflectionFallback(PROTOBUF_TC_PARAM_DECL) { - bool must_fallback_to_generic = (ptr == nullptr); - if (ABSL_PREDICT_FALSE(must_fallback_to_generic)) { - PROTOBUF_MUSTTAIL return GenericFallback(PROTOBUF_TC_PARAM_PASS); - } - SyncHasbits(msg, hasbits, table); uint32_t tag = data.tag(); if (tag == 0 || (tag & 7) == WireFormatLite::WIRETYPE_END_GROUP) { diff --git a/src/google/protobuf/generated_message_tctable_gen.cc b/src/google/protobuf/generated_message_tctable_gen.cc index 804ff1db62c25..cf75ee00a89fb 100644 --- a/src/google/protobuf/generated_message_tctable_gen.cc +++ b/src/google/protobuf/generated_message_tctable_gen.cc @@ -868,7 +868,10 @@ TailCallTableInfo::TailCallTableInfo( // Reflection and weak messages have the reflection fallback : !message_options.uses_codegen || HasWeakFields(descriptor) ? TcParseFunction::kReflectionFallback - // Codegen messages have lite and non-lite version + // Messages without extensions fallback directly to MpUnknownFields + : descriptor->extension_range_count() == 0 + ? TcParseFunction::kMpUnknownFields + // Codegen messages with extensions have lite and non-lite version : message_options.is_lite ? TcParseFunction::kGenericFallbackLite : TcParseFunction::kGenericFallback; diff --git a/src/google/protobuf/generated_message_tctable_impl.h b/src/google/protobuf/generated_message_tctable_impl.h index 567cf4ca44a10..7939361e090b3 100644 --- a/src/google/protobuf/generated_message_tctable_impl.h +++ b/src/google/protobuf/generated_message_tctable_impl.h @@ -369,7 +369,8 @@ inline void AlignFail(std::integral_constant, PROTOBUF_TC_PARSE_FUNCTION_X(GenericFallback) \ PROTOBUF_TC_PARSE_FUNCTION_X(GenericFallbackLite) \ PROTOBUF_TC_PARSE_FUNCTION_X(ReflectionFallback) \ - PROTOBUF_TC_PARSE_FUNCTION_X(DiscardEverythingFallback) + PROTOBUF_TC_PARSE_FUNCTION_X(DiscardEverythingFallback) \ + PROTOBUF_TC_PARSE_FUNCTION_X(MpUnknownFields) #define PROTOBUF_TC_PARSE_FUNCTION_X(value) k##value, enum class TcParseFunction : uint8_t { kNone, PROTOBUF_TC_PARSE_FUNCTION_LIST }; @@ -432,6 +433,8 @@ class PROTOBUF_EXPORT TcParser final { // even when this is enabled. PROTOBUF_CC static const char* DiscardEverythingFallback( PROTOBUF_TC_PARAM_DECL); + // Fallback handler for parsing unknown fields directly. + PROTOBUF_CC static const char* MpUnknownFields(PROTOBUF_TC_PARAM_DECL); // These follow the "fast" function ABI but implement the whole loop for // message_set_wire_format types. @@ -951,39 +954,16 @@ class PROTOBUF_EXPORT TcParser final { class ScopedArenaSwap; - struct UnknownFieldOps { - void (*write_varint)(MessageLite* msg, int number, int value); - void (*write_length_delimited)(MessageLite* msg, int number, - absl::string_view value); - }; - - static const UnknownFieldOps& GetUnknownFieldOps( - const TcParseTableBase* table); - - template - static void WriteVarintToUnknown(MessageLite* msg, int number, int value) { - internal::WriteVarint( - number, value, - msg->_internal_metadata_.mutable_unknown_fields()); - } - template - static void WriteLengthDelimitedToUnknown(MessageLite* msg, int number, - absl::string_view value) { - internal::WriteLengthDelimited( - number, value, - msg->_internal_metadata_.mutable_unknown_fields()); - } + static void WriteVarintToUnknown(MessageLite* msg, + const ClassData* class_data, int number, + int value); + static void WriteLengthDelimitedToUnknown(MessageLite* msg, + const ClassData* class_data, + int number, + absl::string_view value); - template + template PROTOBUF_CC static const char* GenericFallbackImpl(PROTOBUF_TC_PARAM_DECL) { - if (ABSL_PREDICT_FALSE(ptr == nullptr)) { - // This is the ABI used by GetUnknownFieldOps(). Return the vtable. - static constexpr UnknownFieldOps kOps = { - WriteVarintToUnknown, - WriteLengthDelimitedToUnknown}; - return reinterpret_cast(&kOps); - } - SyncHasbits(msg, hasbits, table); uint32_t tag = data.tag(); if ((tag & 7) == WireFormatLite::WIRETYPE_END_GROUP || tag == 0) { @@ -991,22 +971,11 @@ class PROTOBUF_EXPORT TcParser final { return ptr; } - if (table->extension_offset != 0) { - // We don't need to check the extension ranges. If it is not an extension - // it will be handled just like if it was an unknown extension: sent to - // the unknown field set. - return RefAt(msg, table->extension_offset) - .ParseField( - tag, ptr, - static_cast(table->default_instance()), - &msg->_internal_metadata_, ctx); - } else { - // Otherwise, we directly put it on the unknown field set. - return UnknownFieldParse( - tag, - msg->_internal_metadata_.mutable_unknown_fields(), - ptr, ctx); - } + ABSL_DCHECK(table->extension_offset != 0); + return RefAt(msg, table->extension_offset) + .ParseField(tag, ptr, + static_cast(table->default_instance()), + &msg->_internal_metadata_, ctx); } template diff --git a/src/google/protobuf/generated_message_tctable_lite.cc b/src/google/protobuf/generated_message_tctable_lite.cc index 7e69489028791..88ea1bdcc6678 100644 --- a/src/google/protobuf/generated_message_tctable_lite.cc +++ b/src/google/protobuf/generated_message_tctable_lite.cc @@ -41,6 +41,7 @@ #include "google/protobuf/repeated_field.h" #include "google/protobuf/repeated_ptr_field.h" #include "google/protobuf/serial_arena.h" +#include "google/protobuf/unknown_field_set.h" #include "google/protobuf/varint_shuffle.h" #include "google/protobuf/wire_format_lite.h" #include "utf8_validity.h" @@ -72,7 +73,7 @@ using FieldEntry = TcParseTableBase::FieldEntry; #endif const char* TcParser::GenericFallbackLite(PROTOBUF_TC_PARAM_DECL) { - PROTOBUF_MUSTTAIL return GenericFallbackImpl( + PROTOBUF_MUSTTAIL return GenericFallbackImpl( PROTOBUF_TC_PARAM_PASS); } @@ -1464,22 +1465,59 @@ PROTOBUF_ALWAYS_INLINE const char* TcParser::RepeatedEnum( PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_NO_DATA_PASS); } -const TcParser::UnknownFieldOps& TcParser::GetUnknownFieldOps( - const TcParseTableBase* table) { - // Call the fallback function in a special mode to only act as a - // way to return the ops. - // Hiding the unknown fields vtable behind the fallback function avoids adding - // more pointers in TcParseTableBase, and the extra runtime jumps are not - // relevant because unknown fields are rare. - const char* ptr = table->fallback(nullptr, nullptr, nullptr, {}, nullptr, 0); - return *reinterpret_cast(ptr); +void TcParser::WriteVarintToUnknown(MessageLite* msg, + const ClassData* class_data, int number, + int value) { + if (class_data->is_lite) { + internal::WriteVarint( + number, value, + msg->_internal_metadata_.mutable_unknown_fields()); + } else { + internal::WriteVarint( + number, value, + msg->_internal_metadata_.mutable_unknown_fields()); + } +} + +void TcParser::WriteLengthDelimitedToUnknown(MessageLite* msg, + const ClassData* class_data, + int number, + absl::string_view value) { + if (class_data->is_lite) { + internal::WriteLengthDelimited( + number, value, + msg->_internal_metadata_.mutable_unknown_fields()); + } else { + internal::WriteLengthDelimited( + number, value, + msg->_internal_metadata_.mutable_unknown_fields()); + } +} + +const char* TcParser::MpUnknownFields(PROTOBUF_TC_PARAM_DECL) { + SyncHasbits(msg, hasbits, table); + uint32_t tag = data.tag(); + if (ABSL_PREDICT_FALSE((tag & 7) == WireFormatLite::WIRETYPE_END_GROUP || + tag == 0)) { + ctx->SetLastTag(tag); + return ptr; + } + if (table->class_data->is_lite) { + return UnknownFieldParse( + tag, msg->_internal_metadata_.mutable_unknown_fields(), + ptr, ctx); + } else { + return UnknownFieldParse( + tag, msg->_internal_metadata_.mutable_unknown_fields(), + ptr, ctx); + } } PROTOBUF_NOINLINE void TcParser::AddUnknownEnum(MessageLite* msg, const TcParseTableBase* table, uint32_t tag, int32_t enum_value) { - GetUnknownFieldOps(table).write_varint(msg, tag >> 3, enum_value); + WriteVarintToUnknown(msg, table->class_data, tag >> 3, enum_value); } template @@ -2913,7 +2951,7 @@ void TcParser::WriteMapEntryAsUnknown(MessageLite* msg, ABSL_DCHECK(map_info.value_is_validated_enum); WireFormatLite::WriteInt32(2, *map.GetValue(node), &coded_output); } - GetUnknownFieldOps(table).write_length_delimited(msg, tag >> 3, serialized); + WriteLengthDelimitedToUnknown(msg, table->class_data, tag >> 3, serialized); if (arena == nullptr) { map.DeleteNode(node); diff --git a/src/google/protobuf/json_enumvalue_options.pb.cc b/src/google/protobuf/json_enumvalue_options.pb.cc index aad2455411f97..178132d2518a2 100644 --- a/src/google/protobuf/json_enumvalue_options.pb.cc +++ b/src/google/protobuf/json_enumvalue_options.pb.cc @@ -57,7 +57,7 @@ constexpr JsonEnumValueOptions::ParseTableT_ JsonEnumValueOptions::InternalGener offsetof(ParseTableT_, field_names), // no aux_entries class_data, nullptr, // post_loop_handler - ::_pbi::TcParser::GenericFallback, // fallback + ::_pbi::TcParser::MpUnknownFields, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE ::_pbi::TcParser::GetTable<::pb::enumvalue::JsonEnumValueOptions>(), // to_prefetch #endif // PROTOBUF_PREFETCH_PARSE_TABLE diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc index 5e9cef9895d24..610ab16db0e26 100644 --- a/src/google/protobuf/message.cc +++ b/src/google/protobuf/message.cc @@ -738,8 +738,6 @@ template void InternalMetadata::DoMergeFrom( const UnknownFieldSet& other); template void InternalMetadata::DoSwap(UnknownFieldSet* other); template void InternalMetadata::DeleteOutOfLineHelper(); -template UnknownFieldSet* -InternalMetadata::mutable_unknown_fields_slow(); } // namespace internal diff --git a/src/google/protobuf/message_lite.cc b/src/google/protobuf/message_lite.cc index 378e84997d7f4..783de041430cd 100644 --- a/src/google/protobuf/message_lite.cc +++ b/src/google/protobuf/message_lite.cc @@ -39,6 +39,7 @@ #include "google/protobuf/metadata_lite.h" #include "google/protobuf/parse_context.h" #include "google/protobuf/port.h" +#include "google/protobuf/unknown_field_set.h" // Must be included last. @@ -758,6 +759,9 @@ void InternalMetadata::DoSwap(std::string* other) { mutable_unknown_fields()->swap(*other); } +template UnknownFieldSet* +InternalMetadata::mutable_unknown_fields_slow(); + } // namespace internal std::string ShortFormat(const MessageLite& message_lite) { diff --git a/src/google/protobuf/unknown_field_set.cc b/src/google/protobuf/unknown_field_set.cc index 9da9b0c22f24c..2e8fe2aa7bd34 100644 --- a/src/google/protobuf/unknown_field_set.cc +++ b/src/google/protobuf/unknown_field_set.cc @@ -35,18 +35,6 @@ namespace google { namespace protobuf { -void UnknownFieldSet::ClearFallback() { - auto& fields = this->fields(); - ABSL_DCHECK(!fields.empty()); - if (arena() == nullptr) { - int n = fields.size(); - do { - fields[--n].Delete(); - } while (n > 0); - } - fields.Clear(); -} - void UnknownFieldSet::MergeFrom(const UnknownFieldSet& other) { int other_field_count = other.field_count(); if (other_field_count > 0) { @@ -108,26 +96,7 @@ size_t UnknownFieldSet::SpaceUsedLong() const { return sizeof(*this) + SpaceUsedExcludingSelf(); } -void UnknownFieldSet::AddVarint(int number, uint64_t value) { - auto& field = *fields().Add(); - field.number_ = number; - field.SetType(UnknownField::TYPE_VARINT); - field.data_.varint = value; -} - -void UnknownFieldSet::AddFixed32(int number, uint32_t value) { - auto& field = *fields().Add(); - field.number_ = number; - field.SetType(UnknownField::TYPE_FIXED32); - field.data_.fixed32 = value; -} -void UnknownFieldSet::AddFixed64(int number, uint64_t value) { - auto& field = *fields().Add(); - field.number_ = number; - field.SetType(UnknownField::TYPE_FIXED64); - field.data_.fixed64 = value; -} void UnknownFieldSet::AddLengthDelimited(int number, const absl::Cord& value) { absl::CopyCordToString(value, AddLengthDelimited(number)); @@ -143,21 +112,7 @@ void UnknownFieldSet::AddLengthDelimited(int number, std::string&& value) { } template void UnknownFieldSet::AddLengthDelimited(int, std::string&&); -std::string* UnknownFieldSet::AddLengthDelimited(int number) { - auto& field = *fields().Add(); - field.number_ = number; - field.SetType(UnknownField::TYPE_LENGTH_DELIMITED); - field.data_.string_value = Arena::Create(arena()); - return field.data_.string_value; -} -UnknownFieldSet* UnknownFieldSet::AddGroup(int number) { - auto& field = *fields().Add(); - field.number_ = number; - field.SetType(UnknownField::TYPE_GROUP); - field.data_.group = Arena::Create(arena()); - return field.data_.group; -} void UnknownFieldSet::AddField(const UnknownField& field) { fields().Add(field.DeepCopy(arena())); @@ -248,19 +203,6 @@ bool UnknownFieldSet::SerializeToCord(absl::Cord* output) const { return true; } -void UnknownField::Delete() { - switch (type()) { - case UnknownField::TYPE_LENGTH_DELIMITED: - delete data_.string_value; - break; - case UnknownField::TYPE_GROUP: - delete data_.group; - break; - default: - break; - } -} - UnknownField UnknownField::DeepCopy(Arena* arena) const { UnknownField copy = *this; switch (type()) { @@ -298,53 +240,7 @@ uint8_t* UnknownField::InternalSerializeLengthDelimitedNoTag( return target; } -namespace internal { - -class UnknownFieldParserHelper { - public: - explicit UnknownFieldParserHelper(UnknownFieldSet* unknown) - : unknown_(unknown) {} - - void AddVarint(uint32_t num, uint64_t value) { - unknown_->AddVarint(num, value); - } - void AddFixed64(uint32_t num, uint64_t value) { - unknown_->AddFixed64(num, value); - } - const char* ParseLengthDelimited(uint32_t num, const char* ptr, - ParseContext* ctx) { - std::string* s = unknown_->AddLengthDelimited(num); - int size = ReadSize(&ptr); - GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); - return ctx->ReadString(ptr, size, s); - } - const char* ParseGroup(uint32_t num, const char* ptr, ParseContext* ctx) { - return ctx->ParseGroupInlined(ptr, num * 8 + 3, [&](const char* ptr) { - UnknownFieldParserHelper child(unknown_->AddGroup(num)); - return WireFormatParser(child, ptr, ctx); - }); - } - void AddFixed32(uint32_t num, uint32_t value) { - unknown_->AddFixed32(num, value); - } - - private: - UnknownFieldSet* unknown_; -}; - -const char* UnknownGroupParse(UnknownFieldSet* unknown, const char* ptr, - ParseContext* ctx) { - UnknownFieldParserHelper field_parser(unknown); - return WireFormatParser(field_parser, ptr, ctx); -} - -const char* UnknownFieldParse(uint64_t tag, UnknownFieldSet* unknown, - const char* ptr, ParseContext* ctx) { - UnknownFieldParserHelper field_parser(unknown); - return FieldParser(tag, field_parser, ptr, ctx); -} -} // namespace internal } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/unknown_field_set_lite.cc b/src/google/protobuf/unknown_field_set_lite.cc new file mode 100644 index 0000000000000..400ef625c0089 --- /dev/null +++ b/src/google/protobuf/unknown_field_set_lite.cc @@ -0,0 +1,128 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd + +#include +#include + +#include "absl/log/absl_check.h" +#include "google/protobuf/arena.h" +#include "google/protobuf/parse_context.h" +#include "google/protobuf/unknown_field_set.h" + +// Must be included last. +#include "google/protobuf/port_def.inc" + +namespace google { +namespace protobuf { + +void UnknownField::Delete() { + switch (type()) { + case UnknownField::TYPE_LENGTH_DELIMITED: + delete data_.string_value; + break; + case UnknownField::TYPE_GROUP: + delete data_.group; + break; + default: + break; + } +} + +void UnknownFieldSet::ClearFallback() { + auto& fields = this->fields(); + ABSL_DCHECK(!fields.empty()); + if (arena() == nullptr) { + int n = fields.size(); + do { + fields[--n].Delete(); + } while (n > 0); + } + fields.Clear(); +} + +void UnknownFieldSet::AddVarint(int number, uint64_t value) { + auto& field = *fields().Add(); + field.number_ = number; + field.SetType(UnknownField::TYPE_VARINT); + field.data_.varint = value; +} + +void UnknownFieldSet::AddFixed32(int number, uint32_t value) { + auto& field = *fields().Add(); + field.number_ = number; + field.SetType(UnknownField::TYPE_FIXED32); + field.data_.fixed32 = value; +} + +void UnknownFieldSet::AddFixed64(int number, uint64_t value) { + auto& field = *fields().Add(); + field.number_ = number; + field.SetType(UnknownField::TYPE_FIXED64); + field.data_.fixed64 = value; +} + +std::string* UnknownFieldSet::AddLengthDelimited(int number) { + auto& field = *fields().Add(); + field.number_ = number; + field.SetType(UnknownField::TYPE_LENGTH_DELIMITED); + field.data_.string_value = Arena::Create(arena()); + return field.data_.string_value; +} + +UnknownFieldSet* UnknownFieldSet::AddGroup(int number) { + auto& field = *fields().Add(); + field.number_ = number; + field.SetType(UnknownField::TYPE_GROUP); + field.data_.group = Arena::Create(arena()); + return field.data_.group; +} + +namespace internal { + +class UnknownFieldParserHelper { + public: + explicit UnknownFieldParserHelper(UnknownFieldSet* unknown) + : unknown_(unknown) {} + + void AddVarint(uint32_t num, uint64_t value) { + unknown_->AddVarint(num, value); + } + void AddFixed64(uint32_t num, uint64_t value) { + unknown_->AddFixed64(num, value); + } + const char* ParseLengthDelimited(uint32_t num, const char* ptr, + ParseContext* ctx) { + std::string* s = unknown_->AddLengthDelimited(num); + int size = ReadSize(&ptr); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + return ctx->ReadString(ptr, size, s); + } + const char* ParseGroup(uint32_t num, const char* ptr, ParseContext* ctx) { + return ctx->ParseGroupInlined(ptr, num * 8 + 3, [&](const char* ptr) { + UnknownFieldParserHelper child(unknown_->AddGroup(num)); + return WireFormatParser(child, ptr, ctx); + }); + } + void AddFixed32(uint32_t num, uint32_t value) { + unknown_->AddFixed32(num, value); + } + + private: + UnknownFieldSet* unknown_; +}; + +const char* UnknownFieldParse(uint64_t tag, UnknownFieldSet* unknown, + const char* ptr, ParseContext* ctx) { + UnknownFieldParserHelper field_parser(unknown); + return FieldParser(tag, field_parser, ptr, ctx); +} + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include "google/protobuf/port_undef.inc"