dynamic_message.cc
Go to the documentation of this file.
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 // Author: kenton@google.com (Kenton Varda)
32 // Based on original Protocol Buffers design by
33 // Sanjay Ghemawat, Jeff Dean, and others.
34 //
35 // DynamicMessage is implemented by constructing a data structure which
36 // has roughly the same memory layout as a generated message would have.
37 // Then, we use Reflection to implement our reflection interface. All
38 // the other operations we need to implement (e.g. parsing, copying,
39 // etc.) are already implemented in terms of Reflection, so the rest is
40 // easy.
41 //
42 // The up side of this strategy is that it's very efficient. We don't
43 // need to use hash_maps or generic representations of fields. The
44 // down side is that this is a low-level memory management hack which
45 // can be tricky to get right.
46 //
47 // As mentioned in the header, we only expose a DynamicMessageFactory
48 // publicly, not the DynamicMessage class itself. This is because
49 // GenericMessageReflection wants to have a pointer to a "default"
50 // copy of the class, with all fields initialized to their default
51 // values. We only want to construct one of these per message type,
52 // so DynamicMessageFactory stores a cache of default messages for
53 // each type it sees (each unique Descriptor pointer). The code
54 // refers to the "default" copy of the class as the "prototype".
55 //
56 // Note on memory allocation: This module often calls "operator new()"
57 // to allocate untyped memory, rather than calling something like
58 // "new uint8[]". This is because "operator new()" means "Give me some
59 // space which I can use as I please." while "new uint8[]" means "Give
60 // me an array of 8-bit integers.". In practice, the later may return
61 // a pointer that is not aligned correctly for general use. I believe
62 // Item 8 of "More Effective C++" discusses this in more detail, though
63 // I don't have the book on me right now so I'm not sure.
64 
65 #include <algorithm>
66 #include <memory>
67 #include <unordered_map>
68 
70 
84 
85 namespace google {
86 namespace protobuf {
87 
88 using internal::DynamicMapField;
89 using internal::ExtensionSet;
90 using internal::InternalMetadataWithArena;
91 using internal::MapField;
92 
93 
94 using internal::ArenaStringPtr;
95 
96 // ===================================================================
97 // Some helper tables and functions...
98 
99 namespace {
100 
101 bool IsMapFieldInApi(const FieldDescriptor* field) { return field->is_map(); }
102 
103 // Compute the byte size of the in-memory representation of the field.
104 int FieldSpaceUsed(const FieldDescriptor* field) {
105  typedef FieldDescriptor FD; // avoid line wrapping
106  if (field->label() == FD::LABEL_REPEATED) {
107  switch (field->cpp_type()) {
108  case FD::CPPTYPE_INT32:
109  return sizeof(RepeatedField<int32>);
110  case FD::CPPTYPE_INT64:
111  return sizeof(RepeatedField<int64>);
112  case FD::CPPTYPE_UINT32:
113  return sizeof(RepeatedField<uint32>);
114  case FD::CPPTYPE_UINT64:
115  return sizeof(RepeatedField<uint64>);
116  case FD::CPPTYPE_DOUBLE:
117  return sizeof(RepeatedField<double>);
118  case FD::CPPTYPE_FLOAT:
119  return sizeof(RepeatedField<float>);
120  case FD::CPPTYPE_BOOL:
121  return sizeof(RepeatedField<bool>);
122  case FD::CPPTYPE_ENUM:
123  return sizeof(RepeatedField<int>);
124  case FD::CPPTYPE_MESSAGE:
125  if (IsMapFieldInApi(field)) {
126  return sizeof(DynamicMapField);
127  } else {
128  return sizeof(RepeatedPtrField<Message>);
129  }
130 
131  case FD::CPPTYPE_STRING:
132  switch (field->options().ctype()) {
133  default: // TODO(kenton): Support other string reps.
135  return sizeof(RepeatedPtrField<std::string>);
136  }
137  break;
138  }
139  } else {
140  switch (field->cpp_type()) {
141  case FD::CPPTYPE_INT32:
142  return sizeof(int32);
143  case FD::CPPTYPE_INT64:
144  return sizeof(int64);
145  case FD::CPPTYPE_UINT32:
146  return sizeof(uint32);
147  case FD::CPPTYPE_UINT64:
148  return sizeof(uint64);
149  case FD::CPPTYPE_DOUBLE:
150  return sizeof(double);
151  case FD::CPPTYPE_FLOAT:
152  return sizeof(float);
153  case FD::CPPTYPE_BOOL:
154  return sizeof(bool);
155  case FD::CPPTYPE_ENUM:
156  return sizeof(int);
157 
158  case FD::CPPTYPE_MESSAGE:
159  return sizeof(Message*);
160 
161  case FD::CPPTYPE_STRING:
162  switch (field->options().ctype()) {
163  default: // TODO(kenton): Support other string reps.
165  return sizeof(ArenaStringPtr);
166  }
167  break;
168  }
169  }
170 
171  GOOGLE_LOG(DFATAL) << "Can't get here.";
172  return 0;
173 }
174 
175 // Compute the byte size of in-memory representation of the oneof fields
176 // in default oneof instance.
177 int OneofFieldSpaceUsed(const FieldDescriptor* field) {
178  typedef FieldDescriptor FD; // avoid line wrapping
179  switch (field->cpp_type()) {
180  case FD::CPPTYPE_INT32:
181  return sizeof(int32);
182  case FD::CPPTYPE_INT64:
183  return sizeof(int64);
184  case FD::CPPTYPE_UINT32:
185  return sizeof(uint32);
186  case FD::CPPTYPE_UINT64:
187  return sizeof(uint64);
188  case FD::CPPTYPE_DOUBLE:
189  return sizeof(double);
190  case FD::CPPTYPE_FLOAT:
191  return sizeof(float);
192  case FD::CPPTYPE_BOOL:
193  return sizeof(bool);
194  case FD::CPPTYPE_ENUM:
195  return sizeof(int);
196 
197  case FD::CPPTYPE_MESSAGE:
198  return sizeof(Message*);
199 
200  case FD::CPPTYPE_STRING:
201  switch (field->options().ctype()) {
202  default:
204  return sizeof(ArenaStringPtr);
205  }
206  break;
207  }
208 
209  GOOGLE_LOG(DFATAL) << "Can't get here.";
210  return 0;
211 }
212 
213 inline int DivideRoundingUp(int i, int j) { return (i + (j - 1)) / j; }
214 
215 static const int kSafeAlignment = sizeof(uint64);
216 static const int kMaxOneofUnionSize = sizeof(uint64);
217 
218 inline int AlignTo(int offset, int alignment) {
219  return DivideRoundingUp(offset, alignment) * alignment;
220 }
221 
222 // Rounds the given byte offset up to the next offset aligned such that any
223 // type may be stored at it.
224 inline int AlignOffset(int offset) { return AlignTo(offset, kSafeAlignment); }
225 
226 #define bitsizeof(T) (sizeof(T) * 8)
227 
228 } // namespace
229 
230 // ===================================================================
231 
232 class DynamicMessage : public Message {
233  public:
234  struct TypeInfo {
235  int size;
240 
241  // Not owned by the TypeInfo.
242  DynamicMessageFactory* factory; // The factory that created this object.
243  const DescriptorPool* pool; // The factory's DescriptorPool.
244  const Descriptor* type; // Type of this DynamicMessage.
245 
246  // Warning: The order in which the following pointers are defined is
247  // important (the prototype must be deleted *before* the offsets).
248  std::unique_ptr<uint32[]> offsets;
249  std::unique_ptr<uint32[]> has_bits_indices;
250  std::unique_ptr<const Reflection> reflection;
251  // Don't use a unique_ptr to hold the prototype: the destructor for
252  // DynamicMessage needs to know whether it is the prototype, and does so by
253  // looking back at this field. This would assume details about the
254  // implementation of unique_ptr.
256  int weak_field_map_offset; // The offset for the weak_field_map;
257 
259 
260  ~TypeInfo() { delete prototype; }
261  };
262 
263  DynamicMessage(const TypeInfo* type_info);
264 
265  // This should only be used by GetPrototypeNoLock() to avoid dead lock.
266  DynamicMessage(TypeInfo* type_info, bool lock_factory);
267 
268  ~DynamicMessage();
269 
270  // Called on the prototype after construction to initialize message fields.
271  void CrossLinkPrototypes();
272 
273  // implements Message ----------------------------------------------
274 
275  Message* New() const override;
276  Message* New(Arena* arena) const override;
277  Arena* GetArena() const override { return arena_; }
278 
279  int GetCachedSize() const override;
280  void SetCachedSize(int size) const override;
281 
282  Metadata GetMetadata() const override;
283 
284  // We actually allocate more memory than sizeof(*this) when this
285  // class's memory is allocated via the global operator new. Thus, we need to
286  // manually call the global operator delete. Calling the destructor is taken
287  // care of for us. This makes DynamicMessage compatible with -fsized-delete.
288  // It doesn't work for MSVC though.
289 #ifndef _MSC_VER
290  static void operator delete(void* ptr) { ::operator delete(ptr); }
291 #endif // !_MSC_VER
292 
293  private:
294  DynamicMessage(const TypeInfo* type_info, Arena* arena);
295 
296  void SharedCtor(bool lock_factory);
297 
298  inline bool is_prototype() const {
299  return type_info_->prototype == this ||
300  // If type_info_->prototype is NULL, then we must be constructing
301  // the prototype now, which means we must be the prototype.
303  }
304 
305  inline void* OffsetToPointer(int offset) {
306  return reinterpret_cast<uint8*>(this) + offset;
307  }
308  inline const void* OffsetToPointer(int offset) const {
309  return reinterpret_cast<const uint8*>(this) + offset;
310  }
311 
313  Arena* const arena_;
314  mutable std::atomic<int> cached_byte_size_;
316 };
317 
319  : type_info_(type_info), arena_(NULL), cached_byte_size_(0) {
320  SharedCtor(true);
321 }
322 
323 DynamicMessage::DynamicMessage(const TypeInfo* type_info, Arena* arena)
324  : type_info_(type_info), arena_(arena), cached_byte_size_(0) {
325  SharedCtor(true);
326 }
327 
328 DynamicMessage::DynamicMessage(TypeInfo* type_info, bool lock_factory)
329  : type_info_(type_info), arena_(NULL), cached_byte_size_(0) {
330  // The prototype in type_info has to be set before creating the prototype
331  // instance on memory. e.g., message Foo { map<int32, Foo> a = 1; }. When
332  // creating prototype for Foo, prototype of the map entry will also be
333  // created, which needs the address of the prototype of Foo (the value in
334  // map). To break the cyclic dependency, we have to assign the address of
335  // prototype into type_info first.
336  type_info->prototype = this;
337  SharedCtor(lock_factory);
338 }
339 
340 void DynamicMessage::SharedCtor(bool lock_factory) {
341  // We need to call constructors for various fields manually and set
342  // default values where appropriate. We use placement new to call
343  // constructors. If you haven't heard of placement new, I suggest Googling
344  // it now. We use placement new even for primitive types that don't have
345  // constructors for consistency. (In theory, placement new should be used
346  // any time you are trying to convert untyped memory to typed memory, though
347  // in practice that's not strictly necessary for types that don't have a
348  // constructor.)
349 
351  // Initialize oneof cases.
352  for (int i = 0; i < descriptor->oneof_decl_count(); ++i) {
354  uint32(0);
355  }
356 
359 
360  if (type_info_->extensions_offset != -1) {
362  }
363  for (int i = 0; i < descriptor->field_count(); i++) {
364  const FieldDescriptor* field = descriptor->field(i);
365  void* field_ptr = OffsetToPointer(type_info_->offsets[i]);
366  if (field->containing_oneof()) {
367  continue;
368  }
369  switch (field->cpp_type()) {
370 #define HANDLE_TYPE(CPPTYPE, TYPE) \
371  case FieldDescriptor::CPPTYPE_##CPPTYPE: \
372  if (!field->is_repeated()) { \
373  new (field_ptr) TYPE(field->default_value_##TYPE()); \
374  } else { \
375  new (field_ptr) RepeatedField<TYPE>(arena_); \
376  } \
377  break;
378 
379  HANDLE_TYPE(INT32, int32);
380  HANDLE_TYPE(INT64, int64);
381  HANDLE_TYPE(UINT32, uint32);
382  HANDLE_TYPE(UINT64, uint64);
383  HANDLE_TYPE(DOUBLE, double);
384  HANDLE_TYPE(FLOAT, float);
385  HANDLE_TYPE(BOOL, bool);
386 #undef HANDLE_TYPE
387 
389  if (!field->is_repeated()) {
390  new (field_ptr) int(field->default_value_enum()->number());
391  } else {
392  new (field_ptr) RepeatedField<int>(arena_);
393  }
394  break;
395 
397  switch (field->options().ctype()) {
398  default: // TODO(kenton): Support other string reps.
400  if (!field->is_repeated()) {
401  const std::string* default_value;
402  if (is_prototype()) {
403  default_value = &field->default_value_string();
404  } else {
405  default_value = &(reinterpret_cast<const ArenaStringPtr*>(
407  type_info_->offsets[i]))
408  ->Get());
409  }
410  ArenaStringPtr* asp = new (field_ptr) ArenaStringPtr();
412  } else {
413  new (field_ptr) RepeatedPtrField<std::string>(arena_);
414  }
415  break;
416  }
417  break;
418 
420  if (!field->is_repeated()) {
421  new (field_ptr) Message*(NULL);
422  } else {
423  if (IsMapFieldInApi(field)) {
424  // We need to lock in most cases to avoid data racing. Only not lock
425  // when the constructor is called inside GetPrototype(), in which
426  // case we have already locked the factory.
427  if (lock_factory) {
428  if (arena_ != NULL) {
429  new (field_ptr) DynamicMapField(
430  type_info_->factory->GetPrototype(field->message_type()),
431  arena_);
432  } else {
433  new (field_ptr) DynamicMapField(
434  type_info_->factory->GetPrototype(field->message_type()));
435  }
436  } else {
437  if (arena_ != NULL) {
438  new (field_ptr)
440  field->message_type()),
441  arena_);
442  } else {
443  new (field_ptr)
445  field->message_type()));
446  }
447  }
448  } else {
449  new (field_ptr) RepeatedPtrField<Message>(arena_);
450  }
451  }
452  break;
453  }
454  }
455  }
456 }
457 
460 
461  reinterpret_cast<InternalMetadataWithArena*>(
464 
465  if (type_info_->extensions_offset != -1) {
466  reinterpret_cast<ExtensionSet*>(
468  ->~ExtensionSet();
469  }
470 
471  // We need to manually run the destructors for repeated fields and strings,
472  // just as we ran their constructors in the DynamicMessage constructor.
473  // We also need to manually delete oneof fields if it is set and is string
474  // or message.
475  // Additionally, if any singular embedded messages have been allocated, we
476  // need to delete them, UNLESS we are the prototype message of this type,
477  // in which case any embedded messages are other prototypes and shouldn't
478  // be touched.
479  for (int i = 0; i < descriptor->field_count(); i++) {
480  const FieldDescriptor* field = descriptor->field(i);
481  if (field->containing_oneof()) {
482  void* field_ptr =
484  sizeof(uint32) * field->containing_oneof()->index());
485  if (*(reinterpret_cast<const uint32*>(field_ptr)) == field->number()) {
486  field_ptr = OffsetToPointer(
487  type_info_->offsets[descriptor->field_count() +
488  field->containing_oneof()->index()]);
489  if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
490  switch (field->options().ctype()) {
491  default:
492  case FieldOptions::STRING: {
493  const std::string* default_value =
494  &(reinterpret_cast<const ArenaStringPtr*>(
495  reinterpret_cast<const uint8*>(type_info_->prototype) +
496  type_info_->offsets[i])
497  ->Get());
498  reinterpret_cast<ArenaStringPtr*>(field_ptr)->Destroy(
500  break;
501  }
502  }
503  } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
504  delete *reinterpret_cast<Message**>(field_ptr);
505  }
506  }
507  continue;
508  }
509  void* field_ptr = OffsetToPointer(type_info_->offsets[i]);
510 
511  if (field->is_repeated()) {
512  switch (field->cpp_type()) {
513 #define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
514  case FieldDescriptor::CPPTYPE_##UPPERCASE: \
515  reinterpret_cast<RepeatedField<LOWERCASE>*>(field_ptr) \
516  ->~RepeatedField<LOWERCASE>(); \
517  break
518 
519  HANDLE_TYPE(INT32, int32);
520  HANDLE_TYPE(INT64, int64);
521  HANDLE_TYPE(UINT32, uint32);
522  HANDLE_TYPE(UINT64, uint64);
523  HANDLE_TYPE(DOUBLE, double);
524  HANDLE_TYPE(FLOAT, float);
525  HANDLE_TYPE(BOOL, bool);
526  HANDLE_TYPE(ENUM, int);
527 #undef HANDLE_TYPE
528 
530  switch (field->options().ctype()) {
531  default: // TODO(kenton): Support other string reps.
533  reinterpret_cast<RepeatedPtrField<std::string>*>(field_ptr)
535  break;
536  }
537  break;
538 
540  if (IsMapFieldInApi(field)) {
541  reinterpret_cast<DynamicMapField*>(field_ptr)->~DynamicMapField();
542  } else {
543  reinterpret_cast<RepeatedPtrField<Message>*>(field_ptr)
545  }
546  break;
547  }
548 
549  } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
550  switch (field->options().ctype()) {
551  default: // TODO(kenton): Support other string reps.
552  case FieldOptions::STRING: {
553  const std::string* default_value =
554  &(reinterpret_cast<const ArenaStringPtr*>(
556  type_info_->offsets[i]))
557  ->Get());
558  reinterpret_cast<ArenaStringPtr*>(field_ptr)->Destroy(default_value,
559  NULL);
560  break;
561  }
562  }
563  } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
564  if (!is_prototype()) {
565  Message* message = *reinterpret_cast<Message**>(field_ptr);
566  if (message != NULL) {
567  delete message;
568  }
569  }
570  }
571  }
572 }
573 
575  // This should only be called on the prototype message.
577 
580 
581  // Cross-link default messages.
582  for (int i = 0; i < descriptor->field_count(); i++) {
583  const FieldDescriptor* field = descriptor->field(i);
584  void* field_ptr = OffsetToPointer(type_info_->offsets[i]);
585  if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
586  !field->is_repeated()) {
587  // For fields with message types, we need to cross-link with the
588  // prototype for the field's type.
589  // For singular fields, the field is just a pointer which should
590  // point to the prototype.
591  *reinterpret_cast<const Message**>(field_ptr) =
592  factory->GetPrototypeNoLock(field->message_type());
593  }
594  }
595 }
596 
597 Message* DynamicMessage::New() const { return New(NULL); }
598 
599 Message* DynamicMessage::New(Arena* arena) const {
600  if (arena != NULL) {
601  void* new_base = Arena::CreateArray<char>(arena, type_info_->size);
602  memset(new_base, 0, type_info_->size);
603  return new (new_base) DynamicMessage(type_info_, arena);
604  } else {
605  void* new_base = operator new(type_info_->size);
606  memset(new_base, 0, type_info_->size);
607  return new (new_base) DynamicMessage(type_info_);
608  }
609 }
610 
612  return cached_byte_size_.load(std::memory_order_relaxed);
613 }
614 
616  cached_byte_size_.store(size, std::memory_order_relaxed);
617 }
618 
621  metadata.descriptor = type_info_->type;
622  metadata.reflection = type_info_->reflection.get();
623  return metadata;
624 }
625 
626 // ===================================================================
627 
629  typedef std::unordered_map<const Descriptor*, const DynamicMessage::TypeInfo*>
632 };
633 
635  : pool_(NULL),
636  delegate_to_generated_factory_(false),
637  prototypes_(new PrototypeMap) {}
638 
640  : pool_(pool),
641  delegate_to_generated_factory_(false),
642  prototypes_(new PrototypeMap) {}
643 
645  for (PrototypeMap::Map::iterator iter = prototypes_->map_.begin();
646  iter != prototypes_->map_.end(); ++iter) {
647  DeleteDefaultOneofInstance(iter->second->type, iter->second->offsets.get(),
648  iter->second->prototype);
649  delete iter->second;
650  }
651 }
652 
655  return GetPrototypeNoLock(type);
656 }
657 
659  const Descriptor* type) {
661  type->file()->pool() == DescriptorPool::generated_pool()) {
663  }
664 
666  if (*target != NULL) {
667  // Already exists.
668  return (*target)->prototype;
669  }
670 
672  *target = type_info;
673 
674  type_info->type = type;
675  type_info->pool = (pool_ == NULL) ? type->file()->pool() : pool_;
676  type_info->factory = this;
677 
678  // We need to construct all the structures passed to Reflection's constructor.
679  // This includes:
680  // - A block of memory that contains space for all the message's fields.
681  // - An array of integers indicating the byte offset of each field within
682  // this block.
683  // - A big bitfield containing a bit for each field indicating whether
684  // or not that field is set.
685 
686  // Compute size and offsets.
687  uint32* offsets = new uint32[type->field_count() + type->oneof_decl_count()];
688  type_info->offsets.reset(offsets);
689 
690  // Decide all field offsets by packing in order.
691  // We place the DynamicMessage object itself at the beginning of the allocated
692  // space.
693  int size = sizeof(DynamicMessage);
694  size = AlignOffset(size);
695 
696  // Next the has_bits, which is an array of uint32s.
697  if (type->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) {
698  type_info->has_bits_offset = -1;
699  } else {
700  type_info->has_bits_offset = size;
701  int has_bits_array_size =
702  DivideRoundingUp(type->field_count(), bitsizeof(uint32));
703  size += has_bits_array_size * sizeof(uint32);
704  size = AlignOffset(size);
705 
706  uint32* has_bits_indices = new uint32[type->field_count()];
707  for (int i = 0; i < type->field_count(); i++) {
708  has_bits_indices[i] = i;
709  }
710  type_info->has_bits_indices.reset(has_bits_indices);
711  }
712 
713  // The oneof_case, if any. It is an array of uint32s.
714  if (type->oneof_decl_count() > 0) {
715  type_info->oneof_case_offset = size;
716  size += type->oneof_decl_count() * sizeof(uint32);
717  size = AlignOffset(size);
718  }
719 
720  // The ExtensionSet, if any.
721  if (type->extension_range_count() > 0) {
722  type_info->extensions_offset = size;
723  size += sizeof(ExtensionSet);
724  size = AlignOffset(size);
725  } else {
726  // No extensions.
727  type_info->extensions_offset = -1;
728  }
729 
730  // All the fields.
731  //
732  // TODO(b/31226269): Optimize the order of fields to minimize padding.
733  int num_weak_fields = 0;
734  for (int i = 0; i < type->field_count(); i++) {
735  // Make sure field is aligned to avoid bus errors.
736  // Oneof fields do not use any space.
737  if (!type->field(i)->containing_oneof()) {
738  int field_size = FieldSpaceUsed(type->field(i));
739  size = AlignTo(size, std::min(kSafeAlignment, field_size));
740  offsets[i] = size;
741  size += field_size;
742  }
743  }
744 
745  // The oneofs.
746  for (int i = 0; i < type->oneof_decl_count(); i++) {
747  size = AlignTo(size, kSafeAlignment);
748  offsets[type->field_count() + i] = size;
749  size += kMaxOneofUnionSize;
750  }
751 
752  // Add the InternalMetadataWithArena to the end.
753  size = AlignOffset(size);
754  type_info->internal_metadata_offset = size;
755  size += sizeof(InternalMetadataWithArena);
756 
757  type_info->weak_field_map_offset = -1;
758 
759  // Align the final size to make sure no clever allocators think that
760  // alignment is not necessary.
761  type_info->size = size;
762 
763  // Construct the reflection object.
764 
765  if (type->oneof_decl_count() > 0) {
766  // Compute the size of default oneof instance and offsets of default
767  // oneof fields.
768  for (int i = 0; i < type->oneof_decl_count(); i++) {
769  for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) {
770  const FieldDescriptor* field = type->oneof_decl(i)->field(j);
771  int field_size = OneofFieldSpaceUsed(field);
772  size = AlignTo(size, std::min(kSafeAlignment, field_size));
773  offsets[field->index()] = size;
774  size += field_size;
775  }
776  }
777  }
778  size = AlignOffset(size);
779  // Allocate the prototype + oneof fields.
780  void* base = operator new(size);
781  memset(base, 0, size);
782 
783  // We have already locked the factory so we should not lock in the constructor
784  // of dynamic message to avoid dead lock.
785  DynamicMessage* prototype = new (base) DynamicMessage(type_info, false);
786 
787  if (type->oneof_decl_count() > 0 || num_weak_fields > 0) {
788  // Construct default oneof instance.
789  ConstructDefaultOneofInstance(type_info->type, type_info->offsets.get(),
790  prototype);
791  }
792 
793  internal::ReflectionSchema schema = {type_info->prototype,
794  type_info->offsets.get(),
795  type_info->has_bits_indices.get(),
796  type_info->has_bits_offset,
797  type_info->internal_metadata_offset,
798  type_info->extensions_offset,
799  type_info->oneof_case_offset,
800  type_info->size,
801  type_info->weak_field_map_offset};
802 
803  type_info->reflection.reset(
804  new Reflection(type_info->type, schema, type_info->pool, this));
805 
806  // Cross link prototypes.
807  prototype->CrossLinkPrototypes();
808 
809  return prototype;
810 }
811 
813  const Descriptor* type, const uint32 offsets[],
814  void* default_oneof_or_weak_instance) {
815  for (int i = 0; i < type->oneof_decl_count(); i++) {
816  for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) {
817  const FieldDescriptor* field = type->oneof_decl(i)->field(j);
818  void* field_ptr =
819  reinterpret_cast<uint8*>(default_oneof_or_weak_instance) +
820  offsets[field->index()];
821  switch (field->cpp_type()) {
822 #define HANDLE_TYPE(CPPTYPE, TYPE) \
823  case FieldDescriptor::CPPTYPE_##CPPTYPE: \
824  new (field_ptr) TYPE(field->default_value_##TYPE()); \
825  break;
826 
827  HANDLE_TYPE(INT32, int32);
828  HANDLE_TYPE(INT64, int64);
829  HANDLE_TYPE(UINT32, uint32);
830  HANDLE_TYPE(UINT64, uint64);
831  HANDLE_TYPE(DOUBLE, double);
832  HANDLE_TYPE(FLOAT, float);
833  HANDLE_TYPE(BOOL, bool);
834 #undef HANDLE_TYPE
835 
837  new (field_ptr) int(field->default_value_enum()->number());
838  break;
840  switch (field->options().ctype()) {
841  default:
843  ArenaStringPtr* asp = new (field_ptr) ArenaStringPtr();
844  asp->UnsafeSetDefault(&field->default_value_string());
845  break;
846  }
847  break;
848 
850  new (field_ptr) Message*(NULL);
851  break;
852  }
853  }
854  }
855  }
856 }
857 
859  const Descriptor* type, const uint32 offsets[],
860  const void* default_oneof_instance) {
861  for (int i = 0; i < type->oneof_decl_count(); i++) {
862  for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) {
863  const FieldDescriptor* field = type->oneof_decl(i)->field(j);
864  if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
865  switch (field->options().ctype()) {
866  default:
868  break;
869  }
870  }
871  }
872  }
873 }
874 
875 } // namespace protobuf
876 } // namespace google
reflection_ops.h
google::protobuf::DynamicMessage::TypeInfo::reflection
std::unique_ptr< const Reflection > reflection
Definition: dynamic_message.cc:250
google::protobuf.internal::ExtensionSet
Definition: extension_set.h:179
google::protobuf::DynamicMessageFactory::prototypes_mutex_
internal::WrappedMutex prototypes_mutex_
Definition: dynamic_message.h:137
google::protobuf::FieldDescriptor::CPPTYPE_ENUM
@ CPPTYPE_ENUM
Definition: src/google/protobuf/descriptor.h:561
google::protobuf::RepeatedPtrField< std::string >
google::protobuf::FieldDescriptor::options
const FieldOptions & options() const
google::protobuf.internal::ArenaStringPtr::UnsafeSetDefault
void UnsafeSetDefault(const ::std::string *default_value)
Definition: arenastring.h:251
google::protobuf::FieldDescriptor::CPPTYPE_STRING
@ CPPTYPE_STRING
Definition: src/google/protobuf/descriptor.h:562
google::protobuf::FieldDescriptor
Definition: src/google/protobuf/descriptor.h:515
google::protobuf::DynamicMessageFactory::delegate_to_generated_factory_
bool delegate_to_generated_factory_
Definition: dynamic_message.h:128
google::protobuf::DynamicMessageFactory::GetPrototypeNoLock
const Message * GetPrototypeNoLock(const Descriptor *type)
Definition: dynamic_message.cc:658
arenastring.h
Map
Definition: ruby/ext/google/protobuf_c/protobuf.h:442
google::protobuf.internal::InternalMetadataWithArena
Definition: metadata.h:52
google::protobuf::DynamicMessageFactory::PrototypeMap
Definition: dynamic_message.cc:628
NULL
NULL
Definition: test_security_zap.cpp:405
google::protobuf::int64
int64_t int64
Definition: protobuf/src/google/protobuf/stubs/port.h:151
google::protobuf::DynamicMessage::TypeInfo::offsets
std::unique_ptr< uint32[]> offsets
Definition: dynamic_message.cc:248
google::protobuf::FieldDescriptor::label
Label label() const
map_field_inl.h
extension_set.h
base
Definition: logging.cc:2162
google::protobuf::uint8
uint8_t uint8
Definition: protobuf/src/google/protobuf/stubs/port.h:153
google::protobuf::DynamicMessage::TypeInfo::has_bits_offset
int has_bits_offset
Definition: dynamic_message.cc:236
arena_
std::unique_ptr< Arena > arena_
Definition: lite_arena_unittest.cc:51
google::protobuf::DynamicMessage::arena_
Arena *const arena_
Definition: dynamic_message.cc:313
benchmarks.util.result_uploader.metadata
def metadata
Definition: result_uploader.py:97
google::protobuf::python::descriptor::Get
static PyObject * Get(PyContainer *self, PyObject *args)
Definition: descriptor_containers.cc:455
google::protobuf::DynamicMessage::TypeInfo
Definition: dynamic_message.cc:234
google::protobuf::DynamicMessage::TypeInfo::pool
const DescriptorPool * pool
Definition: dynamic_message.cc:243
google::protobuf::uint32
uint32_t uint32
Definition: protobuf/src/google/protobuf/stubs/port.h:155
google::protobuf::MessageFactory::generated_factory
static MessageFactory * generated_factory()
Definition: src/google/protobuf/message.cc:655
google::protobuf::DynamicMessage::cached_byte_size_
std::atomic< int > cached_byte_size_
Definition: dynamic_message.cc:314
google::protobuf::MessageFactory::GetPrototype
virtual const Message * GetPrototype(const Descriptor *type)=0
google::protobuf.internal::ArenaStringPtr::Get
const ::std::string & Get() const
Definition: arenastring.h:84
dynamic_message.h
map_type_handler.h
generated_message_reflection.h
string
GLsizei const GLchar *const * string
Definition: glcorearb.h:3083
google::protobuf::RepeatedField< int >
google::protobuf.internal::DynamicMapField
Definition: map_field.h:324
google::protobuf::DynamicMessage::GetMetadata
Metadata GetMetadata() const override
Definition: dynamic_message.cc:619
google::protobuf::DynamicMessage::~DynamicMessage
~DynamicMessage()
Definition: dynamic_message.cc:458
target
GLenum target
Definition: glcorearb.h:3739
google::protobuf::Reflection
Definition: src/google/protobuf/message.h:400
descriptor
Descriptor * descriptor
Definition: php/ext/google/protobuf/protobuf.h:936
google::protobuf::DynamicMessage::TypeInfo::~TypeInfo
~TypeInfo()
Definition: dynamic_message.cc:260
google::protobuf::HANDLE_TYPE
HANDLE_TYPE(int32, FieldDescriptor::CPPTYPE_INT32, -1)
google::protobuf::DynamicMessage::TypeInfo::oneof_case_offset
int oneof_case_offset
Definition: dynamic_message.cc:237
map_field.h
google::protobuf::DynamicMessage::type_info_
const TypeInfo * type_info_
Definition: dynamic_message.cc:312
google::protobuf::DynamicMessage::GetArena
Arena * GetArena() const override
Definition: dynamic_message.cc:277
FieldDescriptor
Definition: ruby/ext/google/protobuf_c/protobuf.h:129
google::protobuf::DynamicMessage::New
Message * New() const override
Definition: dynamic_message.cc:597
google::protobuf::DynamicMessageFactory::ConstructDefaultOneofInstance
static void ConstructDefaultOneofInstance(const Descriptor *type, const uint32 offsets[], void *default_oneof_instance)
Definition: dynamic_message.cc:812
google::protobuf::int32
int32_t int32
Definition: protobuf/src/google/protobuf/stubs/port.h:150
bitsizeof
#define bitsizeof(T)
Definition: dynamic_message.cc:226
google::protobuf::DynamicMessage::TypeInfo::internal_metadata_offset
int internal_metadata_offset
Definition: dynamic_message.cc:238
google::protobuf::DynamicMessage::TypeInfo::extensions_offset
int extensions_offset
Definition: dynamic_message.cc:239
google::protobuf::DynamicMessageFactory::DeleteDefaultOneofInstance
static void DeleteDefaultOneofInstance(const Descriptor *type, const uint32 offsets[], const void *default_oneof_instance)
Definition: dynamic_message.cc:858
google::protobuf::DynamicMessage::OffsetToPointer
void * OffsetToPointer(int offset)
Definition: dynamic_message.cc:305
google::protobuf::DynamicMessage::OffsetToPointer
const void * OffsetToPointer(int offset) const
Definition: dynamic_message.cc:308
offset
GLintptr offset
Definition: glcorearb.h:2944
google::protobuf::DynamicMessageFactory::PrototypeMap::map_
Map map_
Definition: dynamic_message.cc:631
google::protobuf::DescriptorPool
Definition: src/google/protobuf/descriptor.h:1539
GOOGLE_LOG
#define GOOGLE_LOG(LEVEL)
Definition: logging.h:146
google::protobuf::uint64
uint64_t uint64
Definition: protobuf/src/google/protobuf/stubs/port.h:156
size
#define size
Definition: glcorearb.h:2944
repeated_field.h
google::protobuf::DynamicMessageFactory::PrototypeMap::Map
std::unordered_map< const Descriptor *, const DynamicMessage::TypeInfo * > Map
Definition: dynamic_message.cc:630
google::protobuf::DynamicMessage::TypeInfo::weak_field_map_offset
int weak_field_map_offset
Definition: dynamic_message.cc:256
google::protobuf::DynamicMessage::GetCachedSize
int GetCachedSize() const override
Definition: dynamic_message.cc:611
google::protobuf::FileDescriptor::SYNTAX_PROTO3
@ SYNTAX_PROTO3
Definition: src/google/protobuf/descriptor.h:1394
google::protobuf::DynamicMessage
Definition: dynamic_message.cc:232
field
const FieldDescriptor * field
Definition: parser_unittest.cc:2694
google::protobuf.internal::MutexLock
Definition: protobuf/src/google/protobuf/stubs/mutex.h:116
GOOGLE_CHECK
#define GOOGLE_CHECK(EXPRESSION)
Definition: logging.h:153
pool
InternalDescriptorPool * pool
Definition: php/ext/google/protobuf/protobuf.h:798
i
int i
Definition: gmock-matchers_test.cc:764
google::protobuf::DynamicMessageFactory
Definition: dynamic_message.h:80
google::protobuf::Metadata
Definition: src/google/protobuf/message.h:190
google::protobuf::DynamicMessage::SharedCtor
void SharedCtor(bool lock_factory)
Definition: dynamic_message.cc:340
type
GLenum type
Definition: glcorearb.h:2695
google::protobuf::Message
Definition: src/google/protobuf/message.h:205
google::protobuf::DynamicMessage::TypeInfo::has_bits_indices
std::unique_ptr< uint32[]> has_bits_indices
Definition: dynamic_message.cc:249
google::protobuf::DynamicMessage::is_prototype
bool is_prototype() const
Definition: dynamic_message.cc:298
size
GLsizeiptr size
Definition: glcorearb.h:2943
google::protobuf::DynamicMessageFactory::~DynamicMessageFactory
~DynamicMessageFactory()
Definition: dynamic_message.cc:644
google::protobuf::DescriptorPool::generated_pool
static const DescriptorPool * generated_pool()
Definition: src/google/protobuf/descriptor.cc:1346
FieldOptions::ctype
PROTOBUF_NAMESPACE_ID::FieldOptions_CType ctype() const
Definition: descriptor.pb.h:10566
wire_format.h
google::protobuf::Descriptor
Definition: src/google/protobuf/descriptor.h:231
descriptor.h
default_value
def default_value(type_)
google::protobuf::DynamicMessage::CrossLinkPrototypes
void CrossLinkPrototypes()
Definition: dynamic_message.cc:574
hash.h
generated_message_util.h
google::protobuf::DynamicMessage::TypeInfo::TypeInfo
TypeInfo()
Definition: dynamic_message.cc:258
pool_
DescriptorPool pool_
Definition: parser_unittest.cc:183
google::protobuf::DynamicMessage::TypeInfo::type
const Descriptor * type
Definition: dynamic_message.cc:244
google::protobuf::DynamicMessage::TypeInfo::prototype
const DynamicMessage * prototype
Definition: dynamic_message.cc:255
google::protobuf.internal::ReflectionSchema
Definition: generated_message_reflection.h:126
google::protobuf::DynamicMessage::SetCachedSize
void SetCachedSize(int size) const override
Definition: dynamic_message.cc:615
FieldOptions::STRING
static constexpr CType STRING
Definition: descriptor.pb.h:4197
google::protobuf::DynamicMessageFactory::prototypes_
std::unique_ptr< PrototypeMap > prototypes_
Definition: dynamic_message.h:135
descriptor.pb.h
google::protobuf::DynamicMessage::DynamicMessage
DynamicMessage(const TypeInfo *type_info)
Definition: dynamic_message.cc:318
google::protobuf::DynamicMessageFactory::DynamicMessageFactory
DynamicMessageFactory()
Definition: dynamic_message.cc:634
google::protobuf::DynamicMessageFactory::DynamicMessage
friend class DynamicMessage
Definition: dynamic_message.h:139
google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE
@ CPPTYPE_MESSAGE
Definition: src/google/protobuf/descriptor.h:563
google::protobuf::DynamicMessage::GOOGLE_DISALLOW_EVIL_CONSTRUCTORS
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage)
google::protobuf::DynamicMessage::TypeInfo::size
int size
Definition: dynamic_message.cc:235
false
#define false
Definition: cJSON.c:70
google::protobuf::FieldDescriptor::cpp_type
CppType cpp_type() const
Definition: src/google/protobuf/descriptor.h:2139
google::protobuf::DynamicMessage::TypeInfo::factory
DynamicMessageFactory * factory
Definition: dynamic_message.cc:242
google
Definition: data_proto2_to_proto3_util.h:11
google::protobuf.internal::ArenaStringPtr
Definition: arenastring.h:68
message
GLenum GLuint GLenum GLsizei const GLchar * message
Definition: glcorearb.h:2695
google::protobuf::DynamicMessageFactory::GetPrototype
const Message * GetPrototype(const Descriptor *type) override
Definition: dynamic_message.cc:653
google::protobuf::DynamicMessageFactory::pool_
const DescriptorPool * pool_
Definition: dynamic_message.h:127
google::protobuf::FieldDescriptor::is_map
bool is_map() const
Definition: src/google/protobuf/descriptor.h:2075
RepeatedField
Definition: ruby/ext/google/protobuf_c/protobuf.h:395


libaditof
Author(s):
autogenerated on Wed May 21 2025 02:06:50