From bcd9905c581d76b026ff00a27b8646d89bbc6fc6 Mon Sep 17 00:00:00 2001 From: Protobuf Team Bot Date: Mon, 15 Jul 2024 13:12:47 -0700 Subject: [PATCH] Automated rollback of commit 3849bc6983d3c1180f49bc6e24dd164736129875. PiperOrigin-RevId: 652577976 --- .../cpp/field_generators/string_field.cc | 9 ++++-- src/google/protobuf/compiler/cpp/file.cc | 23 +++++++++++++- src/google/protobuf/compiler/cpp/helpers.cc | 6 ++-- src/google/protobuf/compiler/cpp/helpers.h | 3 +- src/google/protobuf/inlined_string_field.h | 30 +++++++++---------- 5 files changed, 47 insertions(+), 24 deletions(-) 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 ed1168e281..fcca9dfc33 100644 --- a/src/google/protobuf/compiler/cpp/field_generators/string_field.cc +++ b/src/google/protobuf/compiler/cpp/field_generators/string_field.cc @@ -173,8 +173,7 @@ class SingularString : public FieldGeneratorBase { } void GenerateOneofCopyConstruct(io::Printer* p) const override { - ABSL_CHECK(!is_inlined()); - if (EmptyDefault()) { + if (is_inlined() || EmptyDefault()) { p->Emit("new (&$field$) decltype($field$){arena, from.$field$};\n"); } else { p->Emit( @@ -210,6 +209,12 @@ void SingularString::GenerateStaticMembers(io::Printer* p) const { static const $pbi$::LazyString $default_variable_name$; )cc"); } + if (is_inlined()) { + // `_init_inline_xxx` is used for initializing default instances. + p->Emit(R"cc( + static std::true_type _init_inline_$name$_; + )cc"); + } } void SingularString::GenerateAccessorDeclarations(io::Printer* p) const { diff --git a/src/google/protobuf/compiler/cpp/file.cc b/src/google/protobuf/compiler/cpp/file.cc index a7a0fc940b..246e09fa09 100644 --- a/src/google/protobuf/compiler/cpp/file.cc +++ b/src/google/protobuf/compiler/cpp/file.cc @@ -665,6 +665,27 @@ void FileGenerator::GenerateSourceDefaultInstance(int idx, io::Printer* p) { )cc"); } + for (int i = 0; i < generator->descriptor()->field_count(); ++i) { + const FieldDescriptor* field = generator->descriptor()->field(i); + if (!IsStringInlined(field, options_)) { + continue; + } + + // Force the initialization of the inlined string in the default instance. + p->Emit( + { + {"class", ClassName(generator->descriptor())}, + {"field", FieldName(field)}, + {"default", DefaultInstanceName(generator->descriptor(), options_)}, + {"member", FieldMemberName(field, ShouldSplit(field, options_))}, + }, + R"cc( + PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 std::true_type + $class$::Impl_::_init_inline_$field$_ = + ($default$._instance.$member$.Init(), std::true_type{}); + )cc"); + } + if (options_.lite_implicit_weak_fields) { p->Emit( { @@ -1579,7 +1600,7 @@ void FileGenerator::GenerateLibraryIncludes(io::Printer* p) { IncludeFile("third_party/protobuf/io/coded_stream.h", p); IncludeFile("third_party/protobuf/arena.h", p); IncludeFile("third_party/protobuf/arenastring.h", p); - if (IsStringInliningEnabled(file_, options_)) { + if (IsStringInliningEnabled(options_)) { IncludeFile("third_party/protobuf/inlined_string_field.h", p); } if (HasSimpleBaseClasses(file_, options_)) { diff --git a/src/google/protobuf/compiler/cpp/helpers.cc b/src/google/protobuf/compiler/cpp/helpers.cc index 32e3285c83..c6a6c56f45 100644 --- a/src/google/protobuf/compiler/cpp/helpers.cc +++ b/src/google/protobuf/compiler/cpp/helpers.cc @@ -935,10 +935,8 @@ float GetPresenceProbability(const FieldDescriptor* field, return 1.f; } -bool IsStringInliningEnabled(const FileDescriptor* file, - const Options& options) { - return GetOptimizeFor(file, options) == FileOptions::SPEED && - (options.force_inline_string || IsProfileDriven(options)); +bool IsStringInliningEnabled(const Options& options) { + return options.force_inline_string || IsProfileDriven(options); } bool CanStringBeInlined(const FieldDescriptor* field) { diff --git a/src/google/protobuf/compiler/cpp/helpers.h b/src/google/protobuf/compiler/cpp/helpers.h index 17f5b3181b..95c2b6b953 100644 --- a/src/google/protobuf/compiler/cpp/helpers.h +++ b/src/google/protobuf/compiler/cpp/helpers.h @@ -355,8 +355,7 @@ bool IsLikelyPresent(const FieldDescriptor* field, const Options& options); float GetPresenceProbability(const FieldDescriptor* field, const Options& options); -bool IsStringInliningEnabled(const FileDescriptor* file, - const Options& options); +bool IsStringInliningEnabled(const Options& options); // Returns true if the provided field is a singular string and can be inlined. bool CanStringBeInlined(const FieldDescriptor* field); diff --git a/src/google/protobuf/inlined_string_field.h b/src/google/protobuf/inlined_string_field.h index 38dae8d8a7..d894acb7ec 100644 --- a/src/google/protobuf/inlined_string_field.h +++ b/src/google/protobuf/inlined_string_field.h @@ -85,18 +85,16 @@ namespace internal { // For more details of the donating states transitions, go/pd-inlined-string. class PROTOBUF_EXPORT InlinedStringField { public: - InlinedStringField() : str_() {} + InlinedStringField() { Init(); } InlinedStringField(const InlinedStringField&) = delete; InlinedStringField& operator=(const InlinedStringField&) = delete; + inline void Init() { new (get_mutable()) std::string(); } // Add the dummy parameter just to make InlinedStringField(nullptr) // unambiguous. - // We have to hide this constructor from builds that do not support it. They - // won't use it in their codegen, but they might include the header. -#if defined(__cpp_lib_constexpr_string) && __cpp_lib_constexpr_string >= 201907L constexpr InlinedStringField( const ExplicitlyConstructed* /*default_value*/, - bool /*dummy*/) {} -#endif + bool /*dummy*/) + : value_{} {} explicit InlinedStringField(const std::string& default_value); explicit InlinedStringField(Arena* arena); InlinedStringField(Arena* arena, const InlinedStringField& rhs); @@ -348,9 +346,7 @@ class PROTOBUF_EXPORT InlinedStringField { PROTOBUF_NDEBUG_INLINE std::string* get_mutable(); PROTOBUF_NDEBUG_INLINE const std::string* get_const() const; - union { - std::string str_; - }; + alignas(std::string) char value_[sizeof(std::string)]; std::string* MutableSlow(::google::protobuf::Arena* arena, bool donated, uint32_t* donating_states, uint32_t mask, @@ -363,14 +359,18 @@ class PROTOBUF_EXPORT InlinedStringField { typedef void DestructorSkippable_; }; -inline std::string* InlinedStringField::get_mutable() { return &str_; } +inline std::string* InlinedStringField::get_mutable() { + return reinterpret_cast(&value_); +} inline const std::string* InlinedStringField::get_const() const { - return &str_; + return reinterpret_cast(&value_); } -inline InlinedStringField::InlinedStringField(const std::string& default_value) - : str_(default_value) {} +inline InlinedStringField::InlinedStringField( + const std::string& default_value) { + new (get_mutable()) std::string(default_value); +} #ifdef GOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE @@ -386,12 +386,12 @@ inline void InternalRegisterArenaDtor(Arena* arena, void* object, } #endif // GOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE -inline InlinedStringField::InlinedStringField(Arena* /*arena*/) : str_() {} +inline InlinedStringField::InlinedStringField(Arena* /*arena*/) { Init(); } inline InlinedStringField::InlinedStringField(Arena* arena, const InlinedStringField& rhs) { const std::string& src = *rhs.get_const(); - ::new (static_cast(&str_)) std::string(src); + new (value_) std::string(src); } inline const std::string& InlinedStringField::GetNoArena() const {