From 5a76e633ea9b5adb215e93fdc11e1c0c08b3fc74 Mon Sep 17 00:00:00 2001 From: Adam Cozzette Date: Thu, 17 Nov 2016 16:48:38 -0800 Subject: Integrated internal changes from Google --- src/google/protobuf/metadata.h | 108 +++++++++++++++++++++++++++++++++-------- 1 file changed, 88 insertions(+), 20 deletions(-) (limited to 'src/google/protobuf/metadata.h') diff --git a/src/google/protobuf/metadata.h b/src/google/protobuf/metadata.h index 6e3eef63..f9257534 100644 --- a/src/google/protobuf/metadata.h +++ b/src/google/protobuf/metadata.h @@ -40,6 +40,8 @@ #include #include +#include +#include #include namespace google { @@ -56,30 +58,30 @@ namespace internal { // The tagged pointer uses the LSB to disambiguate cases, and uses bit 0 == 0 to // indicate an arena pointer and bit 0 == 1 to indicate a UFS+Arena-container // pointer. -class LIBPROTOBUF_EXPORT InternalMetadataWithArena { +template +class InternalMetadataWithArenaBase { public: - InternalMetadataWithArena() : ptr_(NULL) {} - explicit InternalMetadataWithArena(Arena* arena) - : ptr_ (arena) {} + InternalMetadataWithArenaBase() : ptr_(NULL) {} + explicit InternalMetadataWithArenaBase(Arena* arena) : ptr_(arena) {} - ~InternalMetadataWithArena() { + ~InternalMetadataWithArenaBase() { if (have_unknown_fields() && arena() == NULL) { delete PtrValue(); } ptr_ = NULL; } - GOOGLE_ATTRIBUTE_ALWAYS_INLINE const UnknownFieldSet& unknown_fields() const { + GOOGLE_ATTRIBUTE_ALWAYS_INLINE const T& unknown_fields() const { if (GOOGLE_PREDICT_FALSE(have_unknown_fields())) { - return PtrValue()->unknown_fields_; + return PtrValue()->unknown_fields; } else { - return *UnknownFieldSet::default_instance(); + return Derived::default_instance(); } } - GOOGLE_ATTRIBUTE_ALWAYS_INLINE UnknownFieldSet* mutable_unknown_fields() { + GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* mutable_unknown_fields() { if (GOOGLE_PREDICT_TRUE(have_unknown_fields())) { - return &PtrValue()->unknown_fields_; + return &PtrValue()->unknown_fields; } else { return mutable_unknown_fields_slow(); } @@ -87,7 +89,7 @@ class LIBPROTOBUF_EXPORT InternalMetadataWithArena { GOOGLE_ATTRIBUTE_ALWAYS_INLINE Arena* arena() const { if (GOOGLE_PREDICT_FALSE(have_unknown_fields())) { - return PtrValue()->arena_; + return PtrValue()->arena; } else { return PtrValue(); } @@ -97,7 +99,7 @@ class LIBPROTOBUF_EXPORT InternalMetadataWithArena { return PtrTag() == kTagContainer; } - GOOGLE_ATTRIBUTE_ALWAYS_INLINE void Swap(InternalMetadataWithArena* other) { + GOOGLE_ATTRIBUTE_ALWAYS_INLINE void Swap(Derived* other) { // Semantics here are that we swap only the unknown fields, not the arena // pointer. We cannot simply swap ptr_ with other->ptr_ because we need to // maintain our own arena ptr. Also, our ptr_ and other's ptr_ may be in @@ -105,7 +107,19 @@ class LIBPROTOBUF_EXPORT InternalMetadataWithArena { // cannot simply swap ptr_ and then restore the arena pointers. We reuse // UFS's swap implementation instead. if (have_unknown_fields() || other->have_unknown_fields()) { - mutable_unknown_fields()->Swap(other->mutable_unknown_fields()); + static_cast(this)->DoSwap(other->mutable_unknown_fields()); + } + } + + GOOGLE_ATTRIBUTE_ALWAYS_INLINE void MergeFrom(const Derived& other) { + if (other.have_unknown_fields()) { + static_cast(this)->DoMergeFrom(other.unknown_fields()); + } + } + + GOOGLE_ATTRIBUTE_ALWAYS_INLINE void Clear() { + if (have_unknown_fields()) { + static_cast(this)->DoClear(); } } @@ -131,24 +145,78 @@ class LIBPROTOBUF_EXPORT InternalMetadataWithArena { return reinterpret_cast(ptr_) & kPtrTagMask; } - template T* PtrValue() const { - return reinterpret_cast( + template U* PtrValue() const { + return reinterpret_cast( reinterpret_cast(ptr_) & kPtrValueMask); } // If ptr_'s tag is kTagContainer, it points to an instance of this struct. struct Container { - UnknownFieldSet unknown_fields_; - Arena* arena_; + T unknown_fields; + Arena* arena; }; - GOOGLE_ATTRIBUTE_NOINLINE UnknownFieldSet* mutable_unknown_fields_slow() { + GOOGLE_ATTRIBUTE_NOINLINE T* mutable_unknown_fields_slow() { Arena* my_arena = arena(); Container* container = Arena::Create(my_arena); ptr_ = reinterpret_cast( reinterpret_cast(container) | kTagContainer); - container->arena_ = my_arena; - return &(container->unknown_fields_); + container->arena = my_arena; + return &(container->unknown_fields); + } +}; + +class InternalMetadataWithArena + : public InternalMetadataWithArenaBase { + public: + InternalMetadataWithArena() {} + explicit InternalMetadataWithArena(Arena* arena) + : InternalMetadataWithArenaBase(arena) {} + + void DoSwap(UnknownFieldSet* other) { + mutable_unknown_fields()->Swap(other); + } + + void DoMergeFrom(const UnknownFieldSet& other) { + mutable_unknown_fields()->MergeFrom(other); + } + + void DoClear() { + mutable_unknown_fields()->Clear(); + } + + static const UnknownFieldSet& default_instance() { + return *UnknownFieldSet::default_instance(); + } +}; + +// We store unknown fields as a string right now, because there is currently no +// good interface for reading unknown fields into an ArenaString. We may want +// to revisit this to allow unknown fields to be parsed onto the Arena. +class InternalMetadataWithArenaLite + : public InternalMetadataWithArenaBase { + public: + InternalMetadataWithArenaLite() {} + + explicit InternalMetadataWithArenaLite(Arena* arena) + : InternalMetadataWithArenaBase(arena) {} + + void DoSwap(string* other) { + mutable_unknown_fields()->swap(*other); + } + + void DoMergeFrom(const string& other) { + mutable_unknown_fields()->append(other); + } + + void DoClear() { + mutable_unknown_fields()->clear(); + } + + static const string& default_instance() { + return GetEmptyStringAlreadyInited(); } }; -- cgit v1.2.3