Skip write of `_cached_size_` when the value to write is `0` and the value was

already `0`.
This prevents writes to empty messages, and it is required for moving default
instances to `rodata`.

PiperOrigin-RevId: 655593321
pull/17588/head
Protobuf Team Bot 4 months ago committed by Copybara-Service
parent e618b282d4
commit 29b755fffd
  1. 19
      src/google/protobuf/message_lite.h
  2. 14
      src/google/protobuf/wire_format_lite.cc

@ -88,6 +88,7 @@ class PROTOBUF_EXPORT CachedSize {
constexpr CachedSize() noexcept : atom_(Scalar{}) {}
// NOLINTNEXTLINE(google-explicit-constructor)
constexpr CachedSize(Scalar desired) noexcept : atom_(desired) {}
#if PROTOBUF_BUILTIN_ATOMIC
constexpr CachedSize(const CachedSize& other) = default;
@ -96,6 +97,15 @@ class PROTOBUF_EXPORT CachedSize {
}
void Set(Scalar desired) const noexcept {
// Avoid writing the value when it is zero. This prevents writing to gloabl
// default instances, which might be in readonly memory.
if (ABSL_PREDICT_FALSE(desired == 0)) {
if (Get() == 0) return;
}
__atomic_store_n(&atom_, desired, __ATOMIC_RELAXED);
}
void SetNonZero(Scalar desired) const noexcept {
__atomic_store_n(&atom_, desired, __ATOMIC_RELAXED);
}
#else
@ -110,6 +120,15 @@ class PROTOBUF_EXPORT CachedSize {
}
void Set(Scalar desired) const noexcept {
// Avoid writing the value when it is zero. This prevents writing to gloabl
// default instances, which might be in readonly memory.
if (ABSL_PREDICT_FALSE(desired == 0)) {
if (Get() == 0) return;
}
atom_.store(desired, std::memory_order_relaxed);
}
void SetNonZero(Scalar desired) const noexcept {
atom_.store(desired, std::memory_order_relaxed);
}
#endif

@ -840,7 +840,7 @@ size_t WireFormatLite::Int32SizeWithPackedTagSize(
}
size_t res;
PROTOBUF_ALWAYS_INLINE_CALL res = Int32Size(value);
cached_size.Set(ToCachedSize(res));
cached_size.SetNonZero(ToCachedSize(res));
return tag_size + res + Int32Size(static_cast<int32_t>(res));
}
size_t WireFormatLite::Int64SizeWithPackedTagSize(
@ -852,7 +852,7 @@ size_t WireFormatLite::Int64SizeWithPackedTagSize(
}
size_t res;
PROTOBUF_ALWAYS_INLINE_CALL res = Int64Size(value);
cached_size.Set(ToCachedSize(res));
cached_size.SetNonZero(ToCachedSize(res));
return tag_size + res + Int32Size(static_cast<int32_t>(res));
}
size_t WireFormatLite::UInt32SizeWithPackedTagSize(
@ -864,7 +864,7 @@ size_t WireFormatLite::UInt32SizeWithPackedTagSize(
}
size_t res;
PROTOBUF_ALWAYS_INLINE_CALL res = UInt32Size(value);
cached_size.Set(ToCachedSize(res));
cached_size.SetNonZero(ToCachedSize(res));
return tag_size + res + Int32Size(static_cast<int32_t>(res));
}
size_t WireFormatLite::UInt64SizeWithPackedTagSize(
@ -876,7 +876,7 @@ size_t WireFormatLite::UInt64SizeWithPackedTagSize(
}
size_t res;
PROTOBUF_ALWAYS_INLINE_CALL res = UInt64Size(value);
cached_size.Set(ToCachedSize(res));
cached_size.SetNonZero(ToCachedSize(res));
return tag_size + res + Int32Size(static_cast<int32_t>(res));
}
size_t WireFormatLite::SInt32SizeWithPackedTagSize(
@ -888,7 +888,7 @@ size_t WireFormatLite::SInt32SizeWithPackedTagSize(
}
size_t res;
PROTOBUF_ALWAYS_INLINE_CALL res = SInt32Size(value);
cached_size.Set(ToCachedSize(res));
cached_size.SetNonZero(ToCachedSize(res));
return tag_size + res + Int32Size(static_cast<int32_t>(res));
}
size_t WireFormatLite::SInt64SizeWithPackedTagSize(
@ -900,7 +900,7 @@ size_t WireFormatLite::SInt64SizeWithPackedTagSize(
}
size_t res;
PROTOBUF_ALWAYS_INLINE_CALL res = SInt64Size(value);
cached_size.Set(ToCachedSize(res));
cached_size.SetNonZero(ToCachedSize(res));
return tag_size + res + Int32Size(static_cast<int32_t>(res));
}
size_t WireFormatLite::EnumSizeWithPackedTagSize(
@ -912,7 +912,7 @@ size_t WireFormatLite::EnumSizeWithPackedTagSize(
}
size_t res;
PROTOBUF_ALWAYS_INLINE_CALL res = EnumSize(value);
cached_size.Set(ToCachedSize(res));
cached_size.SetNonZero(ToCachedSize(res));
return tag_size + res + Int32Size(static_cast<int32_t>(res));
}

Loading…
Cancel
Save