From 6ef984af4b0c63c1c33127a12dcfc8e6359f0c9e Mon Sep 17 00:00:00 2001 From: Feng Xiao Date: Mon, 10 Nov 2014 17:34:54 -0800 Subject: Down-integrate from internal code base. --- src/google/protobuf/dynamic_message.cc | 79 ++++++++++++++++++++++++---------- 1 file changed, 57 insertions(+), 22 deletions(-) (limited to 'src/google/protobuf/dynamic_message.cc') diff --git a/src/google/protobuf/dynamic_message.cc b/src/google/protobuf/dynamic_message.cc index 4cca9869..db1dd4d3 100644 --- a/src/google/protobuf/dynamic_message.cc +++ b/src/google/protobuf/dynamic_message.cc @@ -72,6 +72,7 @@ #include #include #include +#include #include #include #include @@ -85,6 +86,8 @@ using internal::ExtensionSet; using internal::GeneratedMessageReflection; +using internal::ArenaStringPtr; + // =================================================================== // Some helper tables and functions... @@ -131,7 +134,7 @@ int FieldSpaceUsed(const FieldDescriptor* field) { switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: - return sizeof(string*); + return sizeof(ArenaStringPtr); } break; } @@ -162,7 +165,7 @@ int OneofFieldSpaceUsed(const FieldDescriptor* field) { switch (field->options().ctype()) { default: case FieldOptions::STRING: - return sizeof(string*); + return sizeof(ArenaStringPtr); } break; } @@ -236,6 +239,8 @@ class DynamicMessage : public Message { // implements Message ---------------------------------------------- Message* New() const; + Message* New(::google::protobuf::Arena* arena) const; + ::google::protobuf::Arena* GetArena() const { return NULL; }; int GetCachedSize() const; void SetCachedSize(int size) const; @@ -245,6 +250,8 @@ class DynamicMessage : public Message { private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage); + DynamicMessage(const TypeInfo* type_info, ::google::protobuf::Arena* arena); + void SharedCtor(); inline bool is_prototype() const { return type_info_->prototype == this || @@ -261,7 +268,6 @@ class DynamicMessage : public Message { } const TypeInfo* type_info_; - // TODO(kenton): Make this an atomic when C++ supports it. mutable int cached_byte_size_; }; @@ -269,6 +275,17 @@ class DynamicMessage : public Message { DynamicMessage::DynamicMessage(const TypeInfo* type_info) : type_info_(type_info), cached_byte_size_(0) { + SharedCtor(); +} + +DynamicMessage::DynamicMessage(const TypeInfo* type_info, + ::google::protobuf::Arena* arena) + : type_info_(type_info), + cached_byte_size_(0) { + SharedCtor(); +} + +void DynamicMessage::SharedCtor() { // We need to call constructors for various fields manually and set // default values where appropriate. We use placement new to call // constructors. If you haven't heard of placement new, I suggest Googling @@ -330,15 +347,17 @@ DynamicMessage::DynamicMessage(const TypeInfo* type_info) default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: if (!field->is_repeated()) { + const string* default_value; if (is_prototype()) { - new(field_ptr) const string*(&field->default_value_string()); + default_value = &field->default_value_string(); } else { - string* default_value = - *reinterpret_cast( + default_value = + &(reinterpret_cast( type_info_->prototype->OffsetToPointer( - type_info_->offsets[i])); - new(field_ptr) string*(default_value); + type_info_->offsets[i]))->Get(NULL)); } + ArenaStringPtr* asp = new(field_ptr) ArenaStringPtr(); + asp->UnsafeSetDefault(default_value); } else { new(field_ptr) RepeatedPtrField(); } @@ -390,9 +409,15 @@ DynamicMessage::~DynamicMessage() { if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { switch (field->options().ctype()) { default: - case FieldOptions::STRING: - delete *reinterpret_cast(field_ptr); + case FieldOptions::STRING: { + const ::std::string* default_value = + &(reinterpret_cast( + type_info_->prototype->OffsetToPointer( + type_info_->offsets[i]))->Get(NULL)); + reinterpret_cast(field_ptr)->Destroy(default_value, + NULL); break; + } } } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { delete *reinterpret_cast(field_ptr); @@ -440,10 +465,12 @@ DynamicMessage::~DynamicMessage() { switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: { - string* ptr = *reinterpret_cast(field_ptr); - if (ptr != &field->default_value_string()) { - delete ptr; - } + const ::std::string* default_value = + &(reinterpret_cast( + type_info_->prototype->OffsetToPointer( + type_info_->offsets[i]))->Get(NULL)); + reinterpret_cast(field_ptr)->Destroy(default_value, + NULL); break; } } @@ -492,6 +519,16 @@ Message* DynamicMessage::New() const { return new(new_base) DynamicMessage(type_info_); } +Message* DynamicMessage::New(::google::protobuf::Arena* arena) const { + if (arena != NULL) { + Message* message = New(); + arena->Own(message); + return message; + } else { + return New(); + } +} + int DynamicMessage::GetCachedSize() const { return cached_byte_size_; } @@ -672,7 +709,8 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock( type_info->oneof_case_offset, type_info->pool, this, - type_info->size)); + type_info->size, + -1 /* arena_offset */)); } else { type_info->reflection.reset( new GeneratedMessageReflection( @@ -684,7 +722,8 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock( type_info->extensions_offset, type_info->pool, this, - type_info->size)); + type_info->size, + -1 /* arena_offset */)); } // Cross link prototypes. prototype->CrossLinkPrototypes(); @@ -723,12 +762,8 @@ void DynamicMessageFactory::ConstructDefaultOneofInstance( switch (field->options().ctype()) { default: case FieldOptions::STRING: - if (field->has_default_value()) { - new(field_ptr) const string*(&field->default_value_string()); - } else { - new(field_ptr) string*( - const_cast(&internal::GetEmptyString())); - } + ArenaStringPtr* asp = new (field_ptr) ArenaStringPtr(); + asp->UnsafeSetDefault(&field->default_value_string()); break; } break; -- cgit v1.2.3