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
69 #include <google/protobuf/stubs/hash.h>
70
71 #include <google/protobuf/descriptor.pb.h>
72 #include <google/protobuf/descriptor.h>
73 #include <google/protobuf/dynamic_message.h>
74 #include <google/protobuf/generated_message_reflection.h>
75 #include <google/protobuf/generated_message_util.h>
76 #include <google/protobuf/arenastring.h>
77 #include <google/protobuf/extension_set.h>
78 #include <google/protobuf/map_field.h>
79 #include <google/protobuf/map_field_inl.h>
80 #include <google/protobuf/map_type_handler.h>
81 #include <google/protobuf/reflection_ops.h>
82 #include <google/protobuf/repeated_field.h>
83 #include <google/protobuf/wire_format.h>
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
IsMapFieldInApi(const FieldDescriptor * field)101 bool IsMapFieldInApi(const FieldDescriptor* field) { return field->is_map(); }
102
103 // Compute the byte size of the in-memory representation of the field.
FieldSpaceUsed(const FieldDescriptor * 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.
134 case FieldOptions::STRING:
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.
164 case FieldOptions::STRING:
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.
OneofFieldSpaceUsed(const FieldDescriptor * field)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:
203 case FieldOptions::STRING:
204 return sizeof(ArenaStringPtr);
205 }
206 break;
207 }
208
209 GOOGLE_LOG(DFATAL) << "Can't get here.";
210 return 0;
211 }
212
DivideRoundingUp(int i,int j)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
AlignTo(int offset,int alignment)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.
AlignOffset(int offset)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;
236 int has_bits_offset;
237 int oneof_case_offset;
238 int internal_metadata_offset;
239 int extensions_offset;
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.
255 const DynamicMessage* prototype;
256 int weak_field_map_offset; // The offset for the weak_field_map;
257
TypeInfogoogle::protobuf::DynamicMessage::TypeInfo258 TypeInfo() : prototype(NULL) {}
259
~TypeInfogoogle::protobuf::DynamicMessage::TypeInfo260 ~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;
GetArena() const277 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
operator delete(void * ptr)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
is_prototype() const298 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.
302 type_info_->prototype == NULL;
303 }
304
OffsetToPointer(int offset)305 inline void* OffsetToPointer(int offset) {
306 return reinterpret_cast<uint8*>(this) + offset;
307 }
OffsetToPointer(int offset) const308 inline const void* OffsetToPointer(int offset) const {
309 return reinterpret_cast<const uint8*>(this) + offset;
310 }
311
312 const TypeInfo* type_info_;
313 Arena* const arena_;
314 mutable std::atomic<int> cached_byte_size_;
315 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage);
316 };
317
DynamicMessage(const TypeInfo * type_info)318 DynamicMessage::DynamicMessage(const TypeInfo* type_info)
319 : type_info_(type_info), arena_(NULL), cached_byte_size_(0) {
320 SharedCtor(true);
321 }
322
DynamicMessage(const TypeInfo * type_info,Arena * arena)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
DynamicMessage(TypeInfo * type_info,bool lock_factory)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
SharedCtor(bool lock_factory)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
350 const Descriptor* descriptor = type_info_->type;
351 // Initialize oneof cases.
352 for (int i = 0; i < descriptor->oneof_decl_count(); ++i) {
353 new (OffsetToPointer(type_info_->oneof_case_offset + sizeof(uint32) * i))
354 uint32(0);
355 }
356
357 new (OffsetToPointer(type_info_->internal_metadata_offset))
358 InternalMetadataWithArena(arena_);
359
360 if (type_info_->extensions_offset != -1) {
361 new (OffsetToPointer(type_info_->extensions_offset)) ExtensionSet(arena_);
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
388 case FieldDescriptor::CPPTYPE_ENUM:
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
396 case FieldDescriptor::CPPTYPE_STRING:
397 switch (field->options().ctype()) {
398 default: // TODO(kenton): Support other string reps.
399 case FieldOptions::STRING:
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*>(
406 type_info_->prototype->OffsetToPointer(
407 type_info_->offsets[i]))
408 ->Get());
409 }
410 ArenaStringPtr* asp = new (field_ptr) ArenaStringPtr();
411 asp->UnsafeSetDefault(default_value);
412 } else {
413 new (field_ptr) RepeatedPtrField<std::string>(arena_);
414 }
415 break;
416 }
417 break;
418
419 case FieldDescriptor::CPPTYPE_MESSAGE: {
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)
439 DynamicMapField(type_info_->factory->GetPrototypeNoLock(
440 field->message_type()),
441 arena_);
442 } else {
443 new (field_ptr)
444 DynamicMapField(type_info_->factory->GetPrototypeNoLock(
445 field->message_type()));
446 }
447 }
448 } else {
449 new (field_ptr) RepeatedPtrField<Message>(arena_);
450 }
451 }
452 break;
453 }
454 }
455 }
456 }
457
~DynamicMessage()458 DynamicMessage::~DynamicMessage() {
459 const Descriptor* descriptor = type_info_->type;
460
461 reinterpret_cast<InternalMetadataWithArena*>(
462 OffsetToPointer(type_info_->internal_metadata_offset))
463 ->~InternalMetadataWithArena();
464
465 if (type_info_->extensions_offset != -1) {
466 reinterpret_cast<ExtensionSet*>(
467 OffsetToPointer(type_info_->extensions_offset))
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 =
483 OffsetToPointer(type_info_->oneof_case_offset +
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(
499 default_value, NULL);
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
529 case FieldDescriptor::CPPTYPE_STRING:
530 switch (field->options().ctype()) {
531 default: // TODO(kenton): Support other string reps.
532 case FieldOptions::STRING:
533 reinterpret_cast<RepeatedPtrField<std::string>*>(field_ptr)
534 ->~RepeatedPtrField<std::string>();
535 break;
536 }
537 break;
538
539 case FieldDescriptor::CPPTYPE_MESSAGE:
540 if (IsMapFieldInApi(field)) {
541 reinterpret_cast<DynamicMapField*>(field_ptr)->~DynamicMapField();
542 } else {
543 reinterpret_cast<RepeatedPtrField<Message>*>(field_ptr)
544 ->~RepeatedPtrField<Message>();
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*>(
555 type_info_->prototype->OffsetToPointer(
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
CrossLinkPrototypes()574 void DynamicMessage::CrossLinkPrototypes() {
575 // This should only be called on the prototype message.
576 GOOGLE_CHECK(is_prototype());
577
578 DynamicMessageFactory* factory = type_info_->factory;
579 const Descriptor* descriptor = type_info_->type;
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
New() const597 Message* DynamicMessage::New() const { return New(NULL); }
598
New(Arena * arena) const599 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
GetCachedSize() const611 int DynamicMessage::GetCachedSize() const {
612 return cached_byte_size_.load(std::memory_order_relaxed);
613 }
614
SetCachedSize(int size) const615 void DynamicMessage::SetCachedSize(int size) const {
616 cached_byte_size_.store(size, std::memory_order_relaxed);
617 }
618
GetMetadata() const619 Metadata DynamicMessage::GetMetadata() const {
620 Metadata metadata;
621 metadata.descriptor = type_info_->type;
622 metadata.reflection = type_info_->reflection.get();
623 return metadata;
624 }
625
626 // ===================================================================
627
628 struct DynamicMessageFactory::PrototypeMap {
629 typedef std::unordered_map<const Descriptor*, const DynamicMessage::TypeInfo*>
630 Map;
631 Map map_;
632 };
633
DynamicMessageFactory()634 DynamicMessageFactory::DynamicMessageFactory()
635 : pool_(NULL),
636 delegate_to_generated_factory_(false),
637 prototypes_(new PrototypeMap) {}
638
DynamicMessageFactory(const DescriptorPool * pool)639 DynamicMessageFactory::DynamicMessageFactory(const DescriptorPool* pool)
640 : pool_(pool),
641 delegate_to_generated_factory_(false),
642 prototypes_(new PrototypeMap) {}
643
~DynamicMessageFactory()644 DynamicMessageFactory::~DynamicMessageFactory() {
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
GetPrototype(const Descriptor * type)653 const Message* DynamicMessageFactory::GetPrototype(const Descriptor* type) {
654 MutexLock lock(&prototypes_mutex_);
655 return GetPrototypeNoLock(type);
656 }
657
GetPrototypeNoLock(const Descriptor * type)658 const Message* DynamicMessageFactory::GetPrototypeNoLock(
659 const Descriptor* type) {
660 if (delegate_to_generated_factory_ &&
661 type->file()->pool() == DescriptorPool::generated_pool()) {
662 return MessageFactory::generated_factory()->GetPrototype(type);
663 }
664
665 const DynamicMessage::TypeInfo** target = &prototypes_->map_[type];
666 if (*target != NULL) {
667 // Already exists.
668 return (*target)->prototype;
669 }
670
671 DynamicMessage::TypeInfo* type_info = new DynamicMessage::TypeInfo;
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
ConstructDefaultOneofInstance(const Descriptor * type,const uint32 offsets[],void * default_oneof_or_weak_instance)812 void DynamicMessageFactory::ConstructDefaultOneofInstance(
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
836 case FieldDescriptor::CPPTYPE_ENUM:
837 new (field_ptr) int(field->default_value_enum()->number());
838 break;
839 case FieldDescriptor::CPPTYPE_STRING:
840 switch (field->options().ctype()) {
841 default:
842 case FieldOptions::STRING:
843 ArenaStringPtr* asp = new (field_ptr) ArenaStringPtr();
844 asp->UnsafeSetDefault(&field->default_value_string());
845 break;
846 }
847 break;
848
849 case FieldDescriptor::CPPTYPE_MESSAGE: {
850 new (field_ptr) Message*(NULL);
851 break;
852 }
853 }
854 }
855 }
856 }
857
DeleteDefaultOneofInstance(const Descriptor * type,const uint32 offsets[],const void * default_oneof_instance)858 void DynamicMessageFactory::DeleteDefaultOneofInstance(
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:
867 case FieldOptions::STRING:
868 break;
869 }
870 }
871 }
872 }
873 }
874
875 } // namespace protobuf
876 } // namespace google
877