From 09354db1434859a31a3c81abebcc4018d42f2715 Mon Sep 17 00:00:00 2001 From: Jisi Liu Date: Tue, 18 Jul 2017 15:38:30 -0700 Subject: Merge from Google internal for 3.4 release --- .../protobuf/generated_message_reflection.cc | 83 +++++++++++++++------- 1 file changed, 58 insertions(+), 25 deletions(-) (limited to 'src/google/protobuf/generated_message_reflection.cc') diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc index 9aebd901..263d52ab 100644 --- a/src/google/protobuf/generated_message_reflection.cc +++ b/src/google/protobuf/generated_message_reflection.cc @@ -44,7 +44,7 @@ #include #include #include -// #include "google/protobuf/bridge/compatibility_mode_support.h" +#include #define GOOGLE_PROTOBUF_HAS_ONEOF @@ -197,32 +197,14 @@ GeneratedMessageReflection::GeneratedMessageReflection( GeneratedMessageReflection::~GeneratedMessageReflection() {} -namespace { -UnknownFieldSet* empty_unknown_field_set_ = NULL; -GOOGLE_PROTOBUF_DECLARE_ONCE(empty_unknown_field_set_once_); - -void DeleteEmptyUnknownFieldSet() { - delete empty_unknown_field_set_; - empty_unknown_field_set_ = NULL; -} - -void InitEmptyUnknownFieldSet() { - empty_unknown_field_set_ = new UnknownFieldSet; - internal::OnShutdown(&DeleteEmptyUnknownFieldSet); -} - -const UnknownFieldSet& GetEmptyUnknownFieldSet() { - ::google::protobuf::GoogleOnceInit(&empty_unknown_field_set_once_, &InitEmptyUnknownFieldSet); - return *empty_unknown_field_set_; -} -} // namespace - const UnknownFieldSet& GeneratedMessageReflection::GetUnknownFields( const Message& message) const { - if (descriptor_->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) { + if (descriptor_->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 && + !GetProto3PreserveUnknownsDefault()) { // We have to ensure that any mutations made to the return value of - // MutableUnknownFields() are not reflected here. - return GetEmptyUnknownFieldSet(); + // MutableUnknownFields() are not reflected here when Proto3 defaults to + // discard unknowns. + return *UnknownFieldSet::default_instance(); } else { return GetInternalMetadataWithArena(message).unknown_fields(); } @@ -1020,7 +1002,7 @@ void GeneratedMessageReflection::ListFields( schema_.HasHasbits() ? GetHasBits(message) : NULL; const uint32* const has_bits_indices = schema_.has_bit_indices_; const uint32* const oneof_case_array = - &GetConstRefAtOffset(message, schema_.oneof_case_offset_); + GetConstPointerAtOffset(&message, schema_.oneof_case_offset_); output->reserve(descriptor_->field_count()); for (int i = 0; i <= last_non_weak_field_index_; i++) { const FieldDescriptor* field = descriptor_->field(i); @@ -2288,6 +2270,8 @@ class AssignDescriptorsHelper { file_level_enum_descriptors_++; } + const Metadata* GetCurrentMetadataPtr() const { return file_level_metadata_; } + private: MessageFactory* factory_; Metadata* file_level_metadata_; @@ -2297,6 +2281,41 @@ class AssignDescriptorsHelper { const uint32* offsets_; }; +// We have the routines that assign descriptors and build reflection +// automatically delete the allocated reflection. MetadataOwner owns +// all the allocated reflection instances. +struct MetadataOwner { + void AddArray(const Metadata* begin, const Metadata* end) { + MutexLock lock(&mu_); + metadata_arrays_.push_back(std::make_pair(begin, end)); + } + + static MetadataOwner* Instance() { + static MetadataOwner* res = new MetadataOwner; + return res; + } + + private: + // Use the constructor to register the shutdown code. Because c++ makes sure + // this called only once. + MetadataOwner() { OnShutdown(&DeleteMetadata); } + ~MetadataOwner() { + for (int i = 0; i < metadata_arrays_.size(); i++) { + for (const Metadata* m = metadata_arrays_[i].first; + m < metadata_arrays_[i].second; m++) { + delete m->reflection; + } + } + } + + static void DeleteMetadata() { + delete Instance(); + } + + Mutex mu_; + std::vector > metadata_arrays_; +}; + } // namespace void AssignDescriptors( @@ -2329,6 +2348,8 @@ void AssignDescriptors( file_level_service_descriptors[i] = file->service(i); } } + MetadataOwner::Instance()->AddArray( + file_level_metadata, helper.GetCurrentMetadataPtr()); } void RegisterAllTypesInternal(const Metadata* file_level_metadata, int size) { @@ -2349,6 +2370,18 @@ void RegisterAllTypes(const Metadata* file_level_metadata, int size) { RegisterAllTypesInternal(file_level_metadata, size); } +void UnknownFieldSetSerializer(const uint8* base, uint32 offset, uint32 tag, + uint32 has_offset, + ::google::protobuf::io::CodedOutputStream* output) { + const void* ptr = base + offset; + const InternalMetadataWithArena* metadata = + static_cast(ptr); + if (metadata->have_unknown_fields()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + metadata->unknown_fields(), output); + } +} + } // namespace internal } // namespace protobuf } // namespace google -- cgit v1.2.3