Improve the way we mask the bits for `_internal_metadata_`.
For the arena, no need to mask anything.
For the container, we use arithmetic instead of masks. The arithmetic is smaller and can be merged with another operation.
PiperOrigin-RevId: 847830188
diff --git a/src/google/protobuf/metadata_lite.h b/src/google/protobuf/metadata_lite.h
index 6425863..df190d3 100644
--- a/src/google/protobuf/metadata_lite.h
+++ b/src/google/protobuf/metadata_lite.h
@@ -11,6 +11,7 @@
#include <string>
#include "absl/base/optimization.h"
+#include "absl/log/absl_check.h"
#include "google/protobuf/arena.h"
#include "google/protobuf/port.h"
@@ -145,7 +146,19 @@
template <typename U>
U* PtrValue() const {
- return reinterpret_cast<U*>(ptr_ & kPtrValueMask);
+ if constexpr (std::is_same_v<U, Arena>) {
+ // No mask to remove.
+ ABSL_DCHECK_EQ(ptr_ & kPtrTagMask, 0);
+ return reinterpret_cast<U*>(ptr_);
+ } else {
+ static_assert(kPtrTagMask == 1);
+ ABSL_DCHECK_EQ(ptr_ & kPtrTagMask, kPtrTagMask);
+ // We can remove the mask via -1, which is smaller asm and can be merged
+ // with other arithmetic operations.
+ // Eg PtrValue<Container>()->unknown_fields can merge the offset into the
+ // mask removal.
+ return reinterpret_cast<U*>(ptr_ - kPtrTagMask);
+ }
}
// If ptr_'s tag is kTagContainer, it points to an instance of this struct.