From d4f2d48101b1aba771b3ac4c09b3a38c3591e0bd Mon Sep 17 00:00:00 2001 From: Martijn Vels Date: Mon, 24 Jul 2023 11:56:41 -0700 Subject: [PATCH] Precompute the most common field properties in FieldGeneratorBase This is a cleanup that is intended to reduce the noise in current and planned protocol compiler code, and improve readability of the code. PiperOrigin-RevId: 550631662 --- src/google/protobuf/compiler/cpp/field.cc | 39 +++++++- src/google/protobuf/compiler/cpp/field.h | 62 +++++++++++- .../cpp/field_generators/cord_field.cc | 27 +++--- .../cpp/field_generators/enum_field.cc | 40 ++++---- .../cpp/field_generators/map_field.cc | 6 +- .../cpp/field_generators/message_field.cc | 60 +++++------- .../cpp/field_generators/primitive_field.cc | 42 ++++---- .../cpp/field_generators/string_field.cc | 95 +++++++++---------- 8 files changed, 226 insertions(+), 145 deletions(-) diff --git a/src/google/protobuf/compiler/cpp/field.cc b/src/google/protobuf/compiler/cpp/field.cc index ef8e28c89d..21e104e4cb 100644 --- a/src/google/protobuf/compiler/cpp/field.cc +++ b/src/google/protobuf/compiler/cpp/field.cc @@ -117,6 +117,43 @@ std::vector FieldVars(const FieldDescriptor* field, const Options& opts) { return vars; } +FieldGeneratorBase::FieldGeneratorBase(const FieldDescriptor* descriptor, + const Options& options, + MessageSCCAnalyzer* scc) + : descriptor_(descriptor), options_(options) { + should_split_ = ShouldSplit(descriptor, options); + is_oneof_ = descriptor->real_containing_oneof() != nullptr; + switch (descriptor->cpp_type()) { + case FieldDescriptor::CPPTYPE_ENUM: + case FieldDescriptor::CPPTYPE_INT32: + case FieldDescriptor::CPPTYPE_INT64: + case FieldDescriptor::CPPTYPE_UINT32: + case FieldDescriptor::CPPTYPE_UINT64: + case FieldDescriptor::CPPTYPE_FLOAT: + case FieldDescriptor::CPPTYPE_DOUBLE: + case FieldDescriptor::CPPTYPE_BOOL: + is_trivial_ = !(descriptor->is_repeated() || descriptor->is_map()); + has_trivial_value_ = is_trivial_; + break; + case FieldDescriptor::CPPTYPE_STRING: + is_string_ = true; + string_type_ = descriptor->options().ctype(); + is_inlined_ = IsStringInlined(descriptor, options); + is_bytes_ = descriptor->type() == FieldDescriptor::TYPE_BYTES; + break; + case FieldDescriptor::CPPTYPE_MESSAGE: + is_message_ = true; + is_group_ = descriptor->type() == FieldDescriptor::TYPE_GROUP; + is_foreign_ = IsCrossFileMessage(descriptor); + is_lazy_ = IsLazy(descriptor, options, scc); + is_weak_ = IsImplicitWeakField(descriptor, options, scc); + if (!(descriptor->is_repeated() || descriptor->is_map())) { + has_trivial_value_ = !is_lazy_; + } + break; + } +} + void FieldGeneratorBase::GenerateAggregateInitializer(io::Printer* p) const { if (ShouldSplit(descriptor_, options_)) { p->Emit(R"cc( @@ -144,7 +181,7 @@ void FieldGeneratorBase::GenerateCopyAggregateInitializer( } void FieldGeneratorBase::GenerateCopyConstructorCode(io::Printer* p) const { - if (ShouldSplit(descriptor_, options_)) { + if (should_split()) { // There is no copy constructor for the `Split` struct, so we need to copy // the value here. Formatter format(p, variables_); diff --git a/src/google/protobuf/compiler/cpp/field.h b/src/google/protobuf/compiler/cpp/field.h index 96d751dd8b..928b9fc9fd 100644 --- a/src/google/protobuf/compiler/cpp/field.h +++ b/src/google/protobuf/compiler/cpp/field.h @@ -62,14 +62,57 @@ namespace cpp { // matter of clean composability. class FieldGeneratorBase { public: - FieldGeneratorBase(const FieldDescriptor* descriptor, const Options& options) - : descriptor_(descriptor), options_(options) {} + FieldGeneratorBase(const FieldDescriptor* descriptor, const Options& options, + MessageSCCAnalyzer* scc_analyzer); FieldGeneratorBase(const FieldGeneratorBase&) = delete; FieldGeneratorBase& operator=(const FieldGeneratorBase&) = delete; virtual ~FieldGeneratorBase() = 0; + // Returns true if this field should be placed in the cold 'Split' section. + bool should_split() const { return should_split_; } + + // Returns true if this field is trivial. (int, float, double, enum, bool) + bool is_trivial() const { return is_trivial_; } + + // Returns true if the field value itself is trivial, i.e., the field is + // trivial, or a (raw) pointer value to a singular, non lazy message. + bool has_trivial_value() const { return has_trivial_value_; } + + // Returns true if the field is a singular or repeated message. + // This includes group message types. To explicitly check if a message + // type is a group type, use the `is_group()` function, + bool is_message() const { return is_message_; } + + // Returns true if the field is a group message field (TYPE_GROUP). + bool is_group() const { return is_group_; } + + // Returns true if the field is a weak message + bool is_weak() const { return is_weak_; } + + // Returns true if the field is a lazy message. + bool is_lazy() const { return is_lazy_; } + + // Returns true if the field is a foreign message field. + bool is_foreign() const { return is_foreign_; } + + // Returns true if the field is a string field. + bool is_string() const { return is_string_; } + + // Returns true if the field API uses bytes (void) instead of chars. + bool is_bytes() const { return is_bytes_; } + + // Returns the public API string type for string fields. + FieldOptions::CType string_type() const { return string_type_; } + + // Returns true if this field is part of a oneof field. + bool is_oneof() const { return is_oneof_; } + + // Returns true if the field should be inlined instead of dynamically + // allocated. Applies to string and message value. + bool is_inlined() const { return is_inlined_; } + virtual std::vector MakeVars() const { return {}; } virtual void GeneratePrivateMembers(io::Printer* p) const = 0; @@ -131,6 +174,21 @@ class FieldGeneratorBase { const FieldDescriptor* descriptor_; const Options& options_; absl::flat_hash_map variables_; + + private: + bool should_split_ = false; + bool is_trivial_ = false; + bool has_trivial_value_ = false; + bool is_message_ = false; + bool is_group_ = false; + bool is_string_ = false; + bool is_bytes_ = false; + bool is_inlined_ = false; + bool is_foreign_ = false; + bool is_lazy_ = false; + bool is_weak_ = false; + bool is_oneof_ = false; + FieldOptions::CType string_type_ = FieldOptions::STRING; }; inline FieldGeneratorBase::~FieldGeneratorBase() = default; diff --git a/src/google/protobuf/compiler/cpp/field_generators/cord_field.cc b/src/google/protobuf/compiler/cpp/field_generators/cord_field.cc index 84ce257e97..c788788ccc 100644 --- a/src/google/protobuf/compiler/cpp/field_generators/cord_field.cc +++ b/src/google/protobuf/compiler/cpp/field_generators/cord_field.cc @@ -77,7 +77,8 @@ void SetCordVariables( class CordFieldGenerator : public FieldGeneratorBase { public: - CordFieldGenerator(const FieldDescriptor* descriptor, const Options& options); + CordFieldGenerator(const FieldDescriptor* descriptor, const Options& options, + MessageSCCAnalyzer* scc); ~CordFieldGenerator() override = default; void GeneratePrivateMembers(io::Printer* printer) const override; @@ -103,7 +104,7 @@ class CordFieldGenerator : public FieldGeneratorBase { class CordOneofFieldGenerator : public CordFieldGenerator { public: CordOneofFieldGenerator(const FieldDescriptor* descriptor, - const Options& options); + const Options& options, MessageSCCAnalyzer* scc); ~CordOneofFieldGenerator() override = default; void GeneratePrivateMembers(io::Printer* printer) const override; @@ -123,8 +124,9 @@ class CordOneofFieldGenerator : public CordFieldGenerator { CordFieldGenerator::CordFieldGenerator(const FieldDescriptor* descriptor, - const Options& options) - : FieldGeneratorBase(descriptor, options) { + const Options& options, + MessageSCCAnalyzer* scc) + : FieldGeneratorBase(descriptor, options, scc) { SetCordVariables(descriptor, &variables_, options); } @@ -215,7 +217,7 @@ void CordFieldGenerator::GenerateSwappingCode(io::Printer* printer) const { } void CordFieldGenerator::GenerateConstructorCode(io::Printer* printer) const { - ABSL_CHECK(!ShouldSplit(descriptor_, options_)); + ABSL_CHECK(!should_split()); Formatter format(printer, variables_); if (!descriptor_->default_value_string().empty()) { format("$field$ = ::absl::string_view($default$, $default_length$);\n"); @@ -224,7 +226,7 @@ void CordFieldGenerator::GenerateConstructorCode(io::Printer* printer) const { void CordFieldGenerator::GenerateDestructorCode(io::Printer* printer) const { Formatter format(printer, variables_); - if (ShouldSplit(descriptor_, options_)) { + if (should_split()) { // A cord field in the `Split` struct is automatically destroyed when the // split pointer is deleted and should not be explicitly destroyed here. return; @@ -270,7 +272,7 @@ void CordFieldGenerator::GenerateConstexprAggregateInitializer( )cc"); } else { p->Emit( - {{"Split", ShouldSplit(descriptor_, options_) ? "Split::" : ""}}, + {{"Split", should_split() ? "Split::" : ""}}, R"cc( /*decltype($field$)*/ {::absl::strings_internal::MakeStringConstant( $classname$::Impl_::$Split$_default_$name$_func_{})}, @@ -279,7 +281,7 @@ void CordFieldGenerator::GenerateConstexprAggregateInitializer( } void CordFieldGenerator::GenerateAggregateInitializer(io::Printer* p) const { - if (ShouldSplit(descriptor_, options_)) { + if (should_split()) { p->Emit(R"cc( decltype(Impl_::Split::$name$_){}, )cc"); @@ -293,8 +295,9 @@ void CordFieldGenerator::GenerateAggregateInitializer(io::Printer* p) const { // =================================================================== CordOneofFieldGenerator::CordOneofFieldGenerator( - const FieldDescriptor* descriptor, const Options& options) - : CordFieldGenerator(descriptor, options) {} + const FieldDescriptor* descriptor, const Options& options, + MessageSCCAnalyzer* scc) + : CordFieldGenerator(descriptor, options, scc) {} void CordOneofFieldGenerator::GeneratePrivateMembers( io::Printer* printer) const { @@ -410,14 +413,14 @@ void CordOneofFieldGenerator::GenerateArenaDestructorCode( std::unique_ptr MakeSingularCordGenerator( const FieldDescriptor* desc, const Options& options, MessageSCCAnalyzer* scc) { - return absl::make_unique(desc, options); + return absl::make_unique(desc, options, scc); } std::unique_ptr MakeOneofCordGenerator( const FieldDescriptor* desc, const Options& options, MessageSCCAnalyzer* scc) { - return absl::make_unique(desc, options); + return absl::make_unique(desc, options, scc); } } // namespace cpp diff --git a/src/google/protobuf/compiler/cpp/field_generators/enum_field.cc b/src/google/protobuf/compiler/cpp/field_generators/enum_field.cc index 990fbbce0e..e36952a8db 100644 --- a/src/google/protobuf/compiler/cpp/field_generators/enum_field.cc +++ b/src/google/protobuf/compiler/cpp/field_generators/enum_field.cc @@ -75,11 +75,9 @@ std::vector Vars(const FieldDescriptor* field, const Options& opts) { class SingularEnum : public FieldGeneratorBase { public: - SingularEnum(const FieldDescriptor* field, const Options& opts) - : FieldGeneratorBase(field, opts), - field_(field), - opts_(&opts), - is_oneof_(field->real_containing_oneof() != nullptr) {} + SingularEnum(const FieldDescriptor* field, const Options& opts, + MessageSCCAnalyzer* scc) + : FieldGeneratorBase(field, opts, scc), field_(field), opts_(&opts) {} ~SingularEnum() override = default; std::vector MakeVars() const override { return Vars(field_, *opts_); } @@ -103,7 +101,7 @@ class SingularEnum : public FieldGeneratorBase { } void GenerateSwappingCode(io::Printer* p) const override { - if (is_oneof_) return; + if (is_oneof()) return; p->Emit(R"cc( swap($field_$, other->$field_$); @@ -111,7 +109,7 @@ class SingularEnum : public FieldGeneratorBase { } void GenerateConstructorCode(io::Printer* p) const override { - if (!is_oneof_) return; + if (!is_oneof()) return; p->Emit(R"cc( $ns$::_$Msg$_default_instance_.$field_$ = $kDefault$; )cc"); @@ -145,7 +143,7 @@ class SingularEnum : public FieldGeneratorBase { } void GenerateAggregateInitializer(io::Printer* p) const override { - if (ShouldSplit(descriptor_, options_)) { + if (should_split()) { p->Emit(R"cc( decltype(Impl_::Split::$name$_){$kDefault$}, )cc"); @@ -168,7 +166,6 @@ class SingularEnum : public FieldGeneratorBase { private: const FieldDescriptor* field_; const Options* opts_; - bool is_oneof_; }; void SingularEnum::GenerateAccessorDeclarations(io::Printer* p) const { @@ -202,7 +199,7 @@ void SingularEnum::GenerateInlineAccessorDefinitions(io::Printer* p) const { } )cc"); - if (is_oneof_) { + if (is_oneof()) { p->Emit(R"cc( inline $Enum$ $Msg$::_internal_$name$() const { if ($has_field$) { @@ -237,19 +234,20 @@ void SingularEnum::GenerateInlineAccessorDefinitions(io::Printer* p) const { class RepeatedEnum : public FieldGeneratorBase { public: - RepeatedEnum(const FieldDescriptor* field, const Options& opts) - : FieldGeneratorBase(field, opts), + RepeatedEnum(const FieldDescriptor* field, const Options& opts, + MessageSCCAnalyzer* scc) + : FieldGeneratorBase(field, opts, scc), field_(field), opts_(&opts), has_cached_size_(field_->is_packed() && HasGeneratedMethods(field_->file(), opts) && - !ShouldSplit(descriptor_, options_)) {} + !should_split()) {} ~RepeatedEnum() override = default; std::vector MakeVars() const override { return Vars(field_, *opts_); } void GeneratePrivateMembers(io::Printer* p) const override { - if (ShouldSplit(descriptor_, options_)) { + if (should_split()) { p->Emit(R"cc( $pbi$::RawPtr<$pb$::RepeatedField> $name$_; )cc"); @@ -280,7 +278,7 @@ class RepeatedEnum : public FieldGeneratorBase { _this->_internal_mutable_$name$()->MergeFrom(from._internal_$name$()); )cc"); }; - if (!ShouldSplit(descriptor_, options_)) { + if (!should_split()) { body(); } else { p->Emit({{"body", body}}, R"cc( @@ -292,14 +290,14 @@ class RepeatedEnum : public FieldGeneratorBase { } void GenerateSwappingCode(io::Printer* p) const override { - ABSL_CHECK(!ShouldSplit(descriptor_, options_)); + ABSL_CHECK(!should_split()); p->Emit(R"cc( $field_$.InternalSwap(&other->$field_$); )cc"); } void GenerateDestructorCode(io::Printer* p) const override { - if (ShouldSplit(descriptor_, options_)) { + if (should_split()) { p->Emit(R"cc( $field_$.DeleteIfNotDefault(); )cc"); @@ -347,7 +345,7 @@ class RepeatedEnum : public FieldGeneratorBase { } void GenerateCopyConstructorCode(io::Printer* p) const override { - if (ShouldSplit(descriptor_, options_)) { + if (should_split()) { p->Emit(R"cc( if (!from._internal_$name$().empty()) { _internal_mutable_$name$()->MergeFrom(from._internal_$name$()); @@ -425,7 +423,7 @@ void RepeatedEnum::GenerateInlineAccessorDefinitions(io::Printer* p) const { return _internal_mutable_$name$(); } )cc"); - if (ShouldSplit(descriptor_, options_)) { + if (should_split()) { p->Emit(R"cc( inline const $pb$::RepeatedField& $Msg$::_internal_$name$() const { $TsanDetectConcurrentRead$; @@ -544,13 +542,13 @@ void RepeatedEnum::GenerateByteSize(io::Printer* p) const { std::unique_ptr MakeSinguarEnumGenerator( const FieldDescriptor* desc, const Options& options, MessageSCCAnalyzer* scc) { - return absl::make_unique(desc, options); + return absl::make_unique(desc, options, scc); } std::unique_ptr MakeRepeatedEnumGenerator( const FieldDescriptor* desc, const Options& options, MessageSCCAnalyzer* scc) { - return absl::make_unique(desc, options); + return absl::make_unique(desc, options, scc); } } // namespace cpp diff --git a/src/google/protobuf/compiler/cpp/field_generators/map_field.cc b/src/google/protobuf/compiler/cpp/field_generators/map_field.cc index c11fb4e5c9..b92ace7f58 100644 --- a/src/google/protobuf/compiler/cpp/field_generators/map_field.cc +++ b/src/google/protobuf/compiler/cpp/field_generators/map_field.cc @@ -80,7 +80,7 @@ class Map : public FieldGeneratorBase { public: Map(const FieldDescriptor* field, const Options& opts, MessageSCCAnalyzer* scc) - : FieldGeneratorBase(field, opts), + : FieldGeneratorBase(field, opts, scc), field_(field), key_(field->message_type()->map_key()), val_(field->message_type()->map_value()), @@ -141,7 +141,7 @@ class Map : public FieldGeneratorBase { } void GenerateAggregateInitializer(io::Printer* p) const override { - if (ShouldSplit(field_, *opts_)) { + if (should_split()) { p->Emit(R"cc( /* decltype($Msg$::Split::$name$_) */ { $pbi$::ArenaInitialized(), @@ -158,7 +158,7 @@ class Map : public FieldGeneratorBase { void GenerateConstructorCode(io::Printer* p) const override {} void GenerateDestructorCode(io::Printer* p) const override { - if (ShouldSplit(field_, *opts_)) { + if (should_split()) { p->Emit(R"cc( $cached_split_ptr$->$name$_.~$MapField$(); )cc"); 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 f2e0c861aa..e270970804 100644 --- a/src/google/protobuf/compiler/cpp/field_generators/message_field.cc +++ b/src/google/protobuf/compiler/cpp/field_generators/message_field.cc @@ -99,19 +99,16 @@ class SingularMessage : public FieldGeneratorBase { public: SingularMessage(const FieldDescriptor* field, const Options& opts, MessageSCCAnalyzer* scc) - : FieldGeneratorBase(field, opts), + : FieldGeneratorBase(field, opts, scc), field_(field), opts_(&opts), - weak_(IsImplicitWeakField(field, opts, scc)), has_required_(scc->HasRequiredFields(field->message_type())), - has_hasbit_(HasHasbit(field)), - is_oneof_(field_->real_containing_oneof() != nullptr), - is_foreign_(IsCrossFileMessage(field)) {} + has_hasbit_(HasHasbit(field)) {} ~SingularMessage() override = default; std::vector MakeVars() const override { - return Vars(field_, *opts_, weak_); + return Vars(field_, *opts_, is_weak()); } void GeneratePrivateMembers(io::Printer* p) const override { @@ -145,11 +142,8 @@ class SingularMessage : public FieldGeneratorBase { const FieldDescriptor* field_; const Options* opts_; - bool weak_; bool has_required_; bool has_hasbit_; - bool is_oneof_; - bool is_foreign_; }; void SingularMessage::GenerateAccessorDeclarations(io::Printer* p) const { @@ -310,7 +304,7 @@ void SingularMessage::GenerateInlineAccessorDefinitions(io::Printer* p) const { void SingularMessage::GenerateInternalAccessorDeclarations( io::Printer* p) const { - if (!weak_) { + if (!is_weak()) { p->Emit(R"cc( static const $Submsg$& $name$(const $Msg$* msg); )cc"); @@ -329,7 +323,7 @@ void SingularMessage::GenerateInternalAccessorDefinitions( // practice, the linker is then not able to throw them out making implicit // weak dependencies not work at all. - if (!weak_) { + if (!is_weak()) { // This inline accessor directly returns member field and is used in // Serialize such that AFDO profile correctly captures access information to // message fields under serialize. @@ -355,7 +349,7 @@ void SingularMessage::GenerateInternalAccessorDefinitions( }}, {"is_already_set", [&] { - if (!is_oneof_) { + if (!is_oneof()) { p->Emit("msg->$field_$ == nullptr"); } else { p->Emit("msg->$not_has_field$"); @@ -363,7 +357,7 @@ void SingularMessage::GenerateInternalAccessorDefinitions( }}, {"clear_oneof", [&] { - if (!is_oneof_) return; + if (!is_oneof()) return; p->Emit(R"cc( msg->clear_$oneof_name$(); msg->set_has_$name$(); @@ -420,7 +414,7 @@ void SingularMessage::GenerateMessageClearingCode(io::Printer* p) const { } void SingularMessage::GenerateMergingCode(io::Printer* p) const { - if (weak_) { + if (is_weak()) { p->Emit( "_Internal::mutable_$name$(_this)->CheckTypeAndMergeFrom(\n" " _Internal::$name$(&from));\n"); @@ -444,7 +438,7 @@ void SingularMessage::GenerateDestructorCode(io::Printer* p) const { // care when handling them. p->Emit("if (this != internal_default_instance()) "); } - if (ShouldSplit(field_, *opts_)) { + if (should_split()) { p->Emit("delete $cached_split_ptr$->$name$_;\n"); return; } @@ -469,7 +463,7 @@ void SingularMessage::GenerateCopyConstructorCode(io::Printer* p) const { void SingularMessage::GenerateSerializeWithCachedSizesToArray( io::Printer* p) const { - if (field_->type() == FieldDescriptor::TYPE_MESSAGE) { + if (!is_group()) { p->Emit( "target = $pbi$::WireFormatLite::\n" " InternalWrite$declared_type$($number$, _Internal::$name$(this),\n" @@ -520,7 +514,7 @@ void SingularMessage::GenerateCopyAggregateInitializer(io::Printer* p) const { } void SingularMessage::GenerateAggregateInitializer(io::Printer* p) const { - if (ShouldSplit(field_, *opts_)) { + if (should_split()) { p->Emit(R"cc( decltype(Impl_::Split::$name$_){nullptr}, )cc"); @@ -638,7 +632,7 @@ void OneofMessage::GenerateInlineAccessorDefinitions(io::Printer* p) const { " clear_$oneof_name$();\n" " if ($name$) {\n" " set_has_$name$();\n"); - if (weak_) { + if (is_weak()) { p->Emit( " $field_$ = " "reinterpret_cast<$pb$::MessageLite*>($name$);\n"); @@ -656,7 +650,7 @@ void OneofMessage::GenerateInlineAccessorDefinitions(io::Printer* p) const { " if ($not_has_field$) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n"); - if (weak_) { + if (is_weak()) { p->Emit( " $field_$ = " "reinterpret_cast<$pb$::MessageLite*>(CreateMaybeMessage< " @@ -716,17 +710,15 @@ class RepeatedMessage : public FieldGeneratorBase { public: RepeatedMessage(const FieldDescriptor* field, const Options& opts, MessageSCCAnalyzer* scc) - : FieldGeneratorBase(field, opts), + : FieldGeneratorBase(field, opts, scc), field_(field), opts_(&opts), - weak_(IsImplicitWeakField(field, opts, scc)), - split_(ShouldSplit(field, opts)), has_required_(scc->HasRequiredFields(field->message_type())) {} ~RepeatedMessage() override = default; std::vector MakeVars() const override { - return Vars(field_, *opts_, weak_); + return Vars(field_, *opts_, is_weak()); } void GeneratePrivateMembers(io::Printer* p) const override; @@ -745,13 +737,11 @@ class RepeatedMessage : public FieldGeneratorBase { private: const FieldDescriptor* field_; const Options* opts_; - bool weak_; - bool split_; bool has_required_; }; void RepeatedMessage::GeneratePrivateMembers(io::Printer* p) const { - if (split_) { + if (should_split()) { p->Emit(R"cc( $pbi$::RawPtr<$pb$::$Weak$RepeatedPtrField<$Submsg$>> $name$_; )cc"); @@ -772,7 +762,7 @@ void RepeatedMessage::GenerateAccessorDeclarations(io::Printer* p) const { "private:\n" "const $pb$::RepeatedPtrField<$Submsg$>& _internal_$name$() const;\n" "$pb$::RepeatedPtrField<$Submsg$>* _internal_mutable_$name$();\n"); - if (weak_) { + if (is_weak()) { format( "const $pb$::WeakRepeatedPtrField<$Submsg$>& _internal_weak_$name$() " "const;\n" @@ -839,7 +829,7 @@ void RepeatedMessage::GenerateInlineAccessorDefinitions(io::Printer* p) const { " return _internal_$name$();\n" "}\n"); - if (split_) { + if (should_split()) { p->Emit(R"cc( inline const $pb$::$Weak$RepeatedPtrField<$Submsg$>& $Msg$::_internal$_weak$_$name$() const { @@ -872,7 +862,7 @@ void RepeatedMessage::GenerateInlineAccessorDefinitions(io::Printer* p) const { } )cc"); } - if (weak_) { + if (is_weak()) { p->Emit(R"cc( inline const $pb$::RepeatedPtrField<$Submsg$>& $Msg$::_internal_$name$() const { @@ -898,7 +888,7 @@ void RepeatedMessage::GenerateMergingCode(io::Printer* p) const { from._internal$_weak$_$name$()); )cc"); }; - if (!split_) { + if (!should_split()) { body(); } else { p->Emit({{"body", body}}, R"cc( @@ -910,7 +900,7 @@ void RepeatedMessage::GenerateMergingCode(io::Printer* p) const { } void RepeatedMessage::GenerateSwappingCode(io::Printer* p) const { - ABSL_CHECK(!split_); + ABSL_CHECK(!should_split()); p->Emit(R"cc( $field_$.InternalSwap(&other->$field_$); )cc"); @@ -923,7 +913,7 @@ void RepeatedMessage::GenerateConstructorCode(io::Printer* p) const { void RepeatedMessage::GenerateCopyConstructorCode(io::Printer* p) const { // TODO(b/291633281): For split repeated fields we might want to use type // erasure to reduce binary size costs. - if (split_) { + if (should_split()) { p->Emit(R"cc( if (!from._internal$_weak$_$name$().empty()) { _internal_mutable$_weak$_$name$()->MergeFrom(from._internal$_weak$_$name$()); @@ -933,7 +923,7 @@ void RepeatedMessage::GenerateCopyConstructorCode(io::Printer* p) const { } void RepeatedMessage::GenerateDestructorCode(io::Printer* p) const { - if (split_) { + if (should_split()) { p->Emit(R"cc( $field_$.DeleteIfNotDefault(); )cc"); @@ -944,7 +934,7 @@ void RepeatedMessage::GenerateDestructorCode(io::Printer* p) const { void RepeatedMessage::GenerateSerializeWithCachedSizesToArray( io::Printer* p) const { - if (weak_) { + if (is_weak()) { p->Emit( "for (auto it = this->$field_$.pointer_begin(),\n" " end = this->$field_$.pointer_end(); it < end; ++it) {\n"); @@ -996,7 +986,7 @@ void RepeatedMessage::GenerateByteSize(io::Printer* p) const { void RepeatedMessage::GenerateIsInitialized(io::Printer* p) const { if (!has_required_) return; - if (weak_) { + if (is_weak()) { p->Emit( "if (!$pbi$::AllAreInitializedWeak($field_$.weak))\n" " return false;\n"); diff --git a/src/google/protobuf/compiler/cpp/field_generators/primitive_field.cc b/src/google/protobuf/compiler/cpp/field_generators/primitive_field.cc index 50b94220cf..6fcda0110d 100644 --- a/src/google/protobuf/compiler/cpp/field_generators/primitive_field.cc +++ b/src/google/protobuf/compiler/cpp/field_generators/primitive_field.cc @@ -110,11 +110,9 @@ std::vector Vars(const FieldDescriptor* field, const Options& options) { class SingularPrimitive final : public FieldGeneratorBase { public: - SingularPrimitive(const FieldDescriptor* field, const Options& opts) - : FieldGeneratorBase(field, opts), - field_(field), - opts_(&opts), - is_oneof_(field_->real_containing_oneof() != nullptr) {} + SingularPrimitive(const FieldDescriptor* field, const Options& opts, + MessageSCCAnalyzer* scc) + : FieldGeneratorBase(field, opts, scc), field_(field), opts_(&opts) {} ~SingularPrimitive() override = default; std::vector MakeVars() const override { return Vars(field_, *opts_); } @@ -138,7 +136,7 @@ class SingularPrimitive final : public FieldGeneratorBase { } void GenerateSwappingCode(io::Printer* p) const override { - if (is_oneof_) { + if (is_oneof()) { // Don't print any swapping code. Swapping the union will swap this field. return; } @@ -150,7 +148,7 @@ class SingularPrimitive final : public FieldGeneratorBase { } void GenerateConstructorCode(io::Printer* p) const override { - if (!is_oneof_) { + if (!is_oneof()) { return; } @@ -191,7 +189,6 @@ class SingularPrimitive final : public FieldGeneratorBase { private: const FieldDescriptor* field_; const Options* opts_; - bool is_oneof_; }; void SingularPrimitive::GenerateAccessorDeclarations(io::Printer* p) const { @@ -226,7 +223,7 @@ void SingularPrimitive::GenerateInlineAccessorDefinitions( } )cc"); - if (is_oneof_) { + if (is_oneof()) { p->Emit(R"cc( inline $Type$ $Msg$::_internal_$name$() const { if ($has_field$) { @@ -309,8 +306,9 @@ void SingularPrimitive::GenerateByteSize(io::Printer* p) const { class RepeatedPrimitive final : public FieldGeneratorBase { public: - RepeatedPrimitive(const FieldDescriptor* field, const Options& opts) - : FieldGeneratorBase(field, opts), field_(field), opts_(&opts) {} + RepeatedPrimitive(const FieldDescriptor* field, const Options& opts, + MessageSCCAnalyzer* scc) + : FieldGeneratorBase(field, opts, scc), field_(field), opts_(&opts) {} ~RepeatedPrimitive() override = default; std::vector MakeVars() const override { return Vars(field_, *opts_); } @@ -329,7 +327,7 @@ class RepeatedPrimitive final : public FieldGeneratorBase { _this->_internal_mutable_$name$()->MergeFrom(from._internal_$name$()); )cc"); }; - if (!ShouldSplit(descriptor_, options_)) { + if (!should_split()) { body(); } else { p->Emit({{"body", body}}, R"cc( @@ -341,14 +339,14 @@ class RepeatedPrimitive final : public FieldGeneratorBase { } void GenerateSwappingCode(io::Printer* p) const override { - ABSL_CHECK(!ShouldSplit(descriptor_, options_)); + ABSL_CHECK(!should_split()); p->Emit(R"cc( $field_$.InternalSwap(&other->$field_$); )cc"); } void GenerateDestructorCode(io::Printer* p) const override { - if (ShouldSplit(descriptor_, options_)) { + if (should_split()) { p->Emit(R"cc( $field_$.DeleteIfNotDefault(); )cc"); @@ -362,7 +360,7 @@ class RepeatedPrimitive final : public FieldGeneratorBase { void GenerateConstructorCode(io::Printer* p) const override {} void GenerateCopyConstructorCode(io::Printer* p) const override { - if (ShouldSplit(descriptor_, options_)) { + if (should_split()) { p->Emit(R"cc( if (!from._internal_$name$().empty()) { _internal_mutable_$name$()->MergeFrom(from._internal_$name$()); @@ -379,7 +377,7 @@ class RepeatedPrimitive final : public FieldGeneratorBase { } void GenerateAggregateInitializer(io::Printer* p) const override { - ABSL_CHECK(!ShouldSplit(descriptor_, options_)); + ABSL_CHECK(!should_split()); p->Emit(R"cc( decltype($field_$){arena}, )cc"); @@ -387,7 +385,7 @@ class RepeatedPrimitive final : public FieldGeneratorBase { } void GenerateCopyAggregateInitializer(io::Printer* p) const override { - ABSL_CHECK(!ShouldSplit(descriptor_, options_)); + ABSL_CHECK(!should_split()); p->Emit(R"cc( decltype($field_$){from.$field_$}, )cc"); @@ -405,7 +403,7 @@ class RepeatedPrimitive final : public FieldGeneratorBase { bool is_packed_varint = field_->is_packed() && !FixedSize(field_->type()).has_value(); return is_packed_varint && HasGeneratedMethods(field_->file(), *opts_) && - !ShouldSplit(descriptor_, options_); + !should_split(); } void GenerateCacheSizeInitializer(io::Printer* p) const { @@ -422,7 +420,7 @@ class RepeatedPrimitive final : public FieldGeneratorBase { }; void RepeatedPrimitive::GeneratePrivateMembers(io::Printer* p) const { - if (ShouldSplit(descriptor_, options_)) { + if (should_split()) { p->Emit(R"cc( $pbi$::RawPtr<$pb$::RepeatedField<$Type$>> $name$_; )cc"); @@ -494,7 +492,7 @@ void RepeatedPrimitive::GenerateInlineAccessorDefinitions( } )cc"); - if (ShouldSplit(descriptor_, options_)) { + if (should_split()) { p->Emit(R"cc( inline const $pb$::RepeatedField<$Type$>& $Msg$::_internal_$name$() const { @@ -632,13 +630,13 @@ void RepeatedPrimitive::GenerateByteSize(io::Printer* p) const { std::unique_ptr MakeSinguarPrimitiveGenerator( const FieldDescriptor* desc, const Options& options, MessageSCCAnalyzer* scc) { - return absl::make_unique(desc, options); + return absl::make_unique(desc, options, scc); } std::unique_ptr MakeRepeatedPrimitiveGenerator( const FieldDescriptor* desc, const Options& options, MessageSCCAnalyzer* scc) { - return absl::make_unique(desc, options); + return absl::make_unique(desc, options, scc); } } // namespace cpp diff --git a/src/google/protobuf/compiler/cpp/field_generators/string_field.cc b/src/google/protobuf/compiler/cpp/field_generators/string_field.cc index 2ae6593c6c..f5525bd522 100644 --- a/src/google/protobuf/compiler/cpp/field_generators/string_field.cc +++ b/src/google/protobuf/compiler/cpp/field_generators/string_field.cc @@ -65,7 +65,7 @@ std::vector Vars(const FieldDescriptor* field, const Options& opts) { "::", MakeDefaultFieldName(field)); bool empty_default = field->default_value_string().empty(); - bool is_bytes = field->type() == FieldDescriptor::TYPE_BYTES; + bool bytes = field->type() == FieldDescriptor::TYPE_BYTES; return { {"kDefault", DefaultValue(opts, field)}, @@ -82,35 +82,33 @@ std::vector Vars(const FieldDescriptor* field, const Options& opts) { Sub{"lazy_args", !empty_default ? absl::StrCat(lazy_var, ",") : ""} .WithSuffix(","), - {"byte", is_bytes ? "void" : "char"}, - {"Set", is_bytes ? "SetBytes" : "Set"}, + {"byte", bytes ? "void" : "char"}, + {"Set", bytes ? "SetBytes" : "Set"}, }; } class SingularString : public FieldGeneratorBase { public: - SingularString(const FieldDescriptor* field, const Options& opts) - : FieldGeneratorBase(field, opts), - field_(field), - opts_(&opts), - is_oneof_(field->real_containing_oneof() != nullptr), - inlined_(IsStringInlined(field, opts)) {} + SingularString(const FieldDescriptor* field, const Options& opts, + MessageSCCAnalyzer* scc) + : FieldGeneratorBase(field, opts, scc), field_(field), opts_(&opts) {} ~SingularString() override = default; std::vector MakeVars() const override { return Vars(field_, *opts_); } - bool IsInlined() const override { return inlined_; } + bool IsInlined() const override { return is_inlined(); } ArenaDtorNeeds NeedsArenaDestructor() const override { - return inlined_ ? ArenaDtorNeeds::kOnDemand : ArenaDtorNeeds::kNone; + return is_inlined() ? ArenaDtorNeeds::kOnDemand : ArenaDtorNeeds::kNone; } void GeneratePrivateMembers(io::Printer* p) const override { // Skips the automatic destruction if inlined; rather calls it explicitly if // allocating arena is null. - p->Emit({{"Str", inlined_ ? "InlinedStringField" : "ArenaStringPtr"}}, R"cc( - $pbi$::$Str$ $name$_; - )cc"); + p->Emit({{"Str", is_inlined() ? "InlinedStringField" : "ArenaStringPtr"}}, + R"cc( + $pbi$::$Str$ $name$_; + )cc"); } void GenerateMergingCode(io::Printer* p) const override { @@ -120,7 +118,7 @@ class SingularString : public FieldGeneratorBase { } void GenerateArenaDestructorCode(io::Printer* p) const override { - if (!inlined_) return; + if (!is_inlined()) return; p->Emit(R"cc( if (!_this->_internal_$name$_donated()) { @@ -172,8 +170,6 @@ class SingularString : public FieldGeneratorBase { const FieldDescriptor* field_; const Options* opts_; - bool is_oneof_; - bool inlined_; }; void SingularString::GenerateStaticMembers(io::Printer* p) const { @@ -182,7 +178,7 @@ void SingularString::GenerateStaticMembers(io::Printer* p) const { static const $pbi$::LazyString $default_variable_name$; )cc"); } - if (inlined_) { + if (is_inlined()) { // `_init_inline_xxx` is used for initializing default instances. p->Emit(R"cc( static std::true_type _init_inline_$name$_; @@ -231,7 +227,7 @@ void SingularString::GenerateAccessorDeclarations(io::Printer* p) const { p->Emit( {{"donated", [&] { - if (!inlined_) return; + if (!is_inlined()) return; p->Emit(R"cc( inline PROTOBUF_ALWAYS_INLINE bool _internal_$name$_donated() const; )cc"); @@ -288,7 +284,7 @@ void ArgsForSetter(io::Printer* p, bool inlined) { } void SingularString::ReleaseImpl(io::Printer* p) const { - if (is_oneof_) { + if (is_oneof()) { p->Emit(R"cc( if ($not_has_field$) { return nullptr; @@ -306,7 +302,7 @@ void SingularString::ReleaseImpl(io::Printer* p) const { return; } - if (inlined_) { + if (is_inlined()) { p->Emit(R"cc( if (($has_hasbit$) == 0) { return nullptr; @@ -342,7 +338,7 @@ void SingularString::ReleaseImpl(io::Printer* p) const { } void SingularString::SetAllocatedImpl(io::Printer* p) const { - if (is_oneof_) { + if (is_oneof()) { p->Emit(R"cc( if (has_$oneof_name$()) { clear_$oneof_name$(); @@ -365,7 +361,7 @@ void SingularString::SetAllocatedImpl(io::Printer* p) const { )cc"); } - if (inlined_) { + if (is_inlined()) { // Currently, string fields with default value can't be inlined. p->Emit(R"cc( $field_$.SetAllocated(nullptr, value, $set_args$); @@ -393,18 +389,18 @@ void SingularString::GenerateInlineAccessorDefinitions(io::Printer* p) const { { {"if_IsDefault", [&] { - if (EmptyDefault() || is_oneof_) return; + if (EmptyDefault() || is_oneof()) return; p->Emit(R"cc( if ($field_$.IsDefault()) { return $default_variable_field$.get(); } )cc"); }}, - {"update_hasbit", [&] { UpdateHasbitSet(p, is_oneof_); }}, - {"set_args", [&] { ArgsForSetter(p, inlined_); }}, + {"update_hasbit", [&] { UpdateHasbitSet(p, is_oneof()); }}, + {"set_args", [&] { ArgsForSetter(p, is_inlined()); }}, {"check_hasbit", [&] { - if (!is_oneof_) return; + if (!is_oneof()) return; p->Emit(R"cc( if ($not_has_field$) { return $kDefaultStr$; @@ -473,7 +469,7 @@ void SingularString::GenerateInlineAccessorDefinitions(io::Printer* p) const { } )cc"); - if (inlined_) { + if (is_inlined()) { p->Emit(R"cc( inline bool $Msg$::_internal_$name$_donated() const { return $inlined_string_donated$; @@ -483,7 +479,7 @@ void SingularString::GenerateInlineAccessorDefinitions(io::Printer* p) const { } void SingularString::GenerateClearingCode(io::Printer* p) const { - if (is_oneof_) { + if (is_oneof()) { p->Emit(R"cc( $field_$.Destroy(); )cc"); @@ -497,14 +493,14 @@ void SingularString::GenerateClearingCode(io::Printer* p) const { return; } - ABSL_DCHECK(!inlined_); + ABSL_DCHECK(!is_inlined()); p->Emit(R"cc( $field_$.ClearToDefault($lazy_var$, GetArenaForAllocation()); )cc"); } void SingularString::GenerateMessageClearingCode(io::Printer* p) const { - if (is_oneof_) { + if (is_oneof()) { p->Emit(R"cc( $field_$.Destroy(); )cc"); @@ -520,7 +516,7 @@ void SingularString::GenerateMessageClearingCode(io::Printer* p) const { // will have checked that this field is set. If so, we can avoid redundant // checks against the default variable. - if (inlined_ && HasHasbit(field_)) { + if (is_inlined() && HasHasbit(field_)) { // Calling mutable_$name$() gives us a string reference and sets the has bit // for $name$ (in proto2). We may get here when the string field is inlined // but the string's contents have not been changed by the user, so we cannot @@ -551,12 +547,12 @@ void SingularString::GenerateMessageClearingCode(io::Printer* p) const { } void SingularString::GenerateSwappingCode(io::Printer* p) const { - if (is_oneof_) { + if (is_oneof()) { // Don't print any swapping code. Swapping the union will swap this field. return; } - if (!inlined_) { + if (!is_inlined()) { p->Emit(R"cc( ::_pbi::ArenaStringPtr::InternalSwap(&$field_$, lhs_arena, &other->$field_$, rhs_arena); @@ -577,8 +573,8 @@ void SingularString::GenerateSwappingCode(io::Printer* p) const { } void SingularString::GenerateConstructorCode(io::Printer* p) const { - if ((inlined_ && EmptyDefault()) || is_oneof_) return; - ABSL_DCHECK(!inlined_); + if ((is_inlined() && EmptyDefault()) || is_oneof()) return; + ABSL_DCHECK(!is_inlined()); p->Emit(R"cc( $field_$.InitDefault(); @@ -596,7 +592,7 @@ void SingularString::GenerateConstructorCode(io::Printer* p) const { void SingularString::GenerateCopyConstructorCode(io::Printer* p) const { GenerateConstructorCode(p); - if (inlined_) { + if (is_inlined()) { p->Emit(R"cc( new (&_this->$field_$)::_pbi::InlinedStringField; )cc"); @@ -613,7 +609,7 @@ void SingularString::GenerateCopyConstructorCode(io::Printer* p) const { }}, {"set_args", [&] { - if (!inlined_) { + if (!is_inlined()) { p->Emit("_this->GetArenaForAllocation()"); } else { p->Emit( @@ -630,17 +626,17 @@ void SingularString::GenerateCopyConstructorCode(io::Printer* p) const { } void SingularString::GenerateDestructorCode(io::Printer* p) const { - if (inlined_) { + if (is_inlined()) { // Explicitly calls ~InlinedStringField as its automatic call is disabled. // Destructor has been implicitly skipped as a union. - ABSL_DCHECK(!ShouldSplit(field_, *opts_)); + ABSL_DCHECK(!should_split()); p->Emit(R"cc( $field_$.~InlinedStringField(); )cc"); return; } - if (ShouldSplit(field_, *opts_)) { + if (should_split()) { p->Emit(R"cc( $cached_split_ptr$->$name$_.Destroy(); )cc"); @@ -669,7 +665,7 @@ void SingularString::GenerateSerializeWithCachedSizesToArray( void SingularString::GenerateConstexprAggregateInitializer( io::Printer* p) const { - if (inlined_) { + if (is_inlined()) { p->Emit(R"cc( /*decltype($field_$)*/ {nullptr, false}, )cc"); @@ -684,12 +680,12 @@ void SingularString::GenerateConstexprAggregateInitializer( } void SingularString::GenerateAggregateInitializer(io::Printer* p) const { - if (ShouldSplit(field_, options_)) { - ABSL_CHECK(!inlined_); + if (should_split()) { + ABSL_CHECK(!is_inlined()); p->Emit(R"cc( decltype(Impl_::Split::$name$_){}, )cc"); - } else if (!inlined_) { + } else if (!is_inlined()) { p->Emit(R"cc( decltype($field_$){}, )cc"); @@ -702,8 +698,9 @@ void SingularString::GenerateAggregateInitializer(io::Printer* p) const { class RepeatedString : public FieldGeneratorBase { public: - RepeatedString(const FieldDescriptor* field, const Options& opts) - : FieldGeneratorBase(field, opts), field_(field), opts_(&opts) {} + RepeatedString(const FieldDescriptor* field, const Options& opts, + MessageSCCAnalyzer* scc) + : FieldGeneratorBase(field, opts, scc), field_(field), opts_(&opts) {} ~RepeatedString() override = default; std::vector MakeVars() const override { return Vars(field_, *opts_); } @@ -991,13 +988,13 @@ void RepeatedString::GenerateSerializeWithCachedSizesToArray( std::unique_ptr MakeSinguarStringGenerator( const FieldDescriptor* desc, const Options& options, MessageSCCAnalyzer* scc) { - return absl::make_unique(desc, options); + return absl::make_unique(desc, options, scc); } std::unique_ptr MakeRepeatedStringGenerator( const FieldDescriptor* desc, const Options& options, MessageSCCAnalyzer* scc) { - return absl::make_unique(desc, options); + return absl::make_unique(desc, options, scc); } } // namespace cpp