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 <google/protobuf/dynamic_message.h>
66
67 #include <algorithm>
68 #include <cstddef>
69 #include <memory>
70 #include <unordered_map>
71
72 #include <google/protobuf/descriptor.pb.h>
73 #include <google/protobuf/descriptor.h>
74 #include <google/protobuf/generated_message_reflection.h>
75 #include <google/protobuf/generated_message_util.h>
76 #include <google/protobuf/unknown_field_set.h>
77 #include <google/protobuf/stubs/hash.h>
78 #include <google/protobuf/arenastring.h>
79 #include <google/protobuf/extension_set.h>
80 #include <google/protobuf/map_field.h>
81 #include <google/protobuf/map_field_inl.h>
82 #include <google/protobuf/map_type_handler.h>
83 #include <google/protobuf/reflection_ops.h>
84 #include <google/protobuf/repeated_field.h>
85 #include <google/protobuf/wire_format.h>
86
87 #include <google/protobuf/port_def.inc> // NOLINT
88
89 namespace google {
90 namespace protobuf {
91
92 using internal::DynamicMapField;
93 using internal::ExtensionSet;
94 using internal::MapField;
95
96
97 using internal::ArenaStringPtr;
98
99 // ===================================================================
100 // Some helper tables and functions...
101
102 namespace {
103
IsMapFieldInApi(const FieldDescriptor * field)104 bool IsMapFieldInApi(const FieldDescriptor* field) { return field->is_map(); }
105
106 // Sync with helpers.h.
HasHasbit(const FieldDescriptor * field)107 inline bool HasHasbit(const FieldDescriptor* field) {
108 // This predicate includes proto3 message fields only if they have "optional".
109 // Foo submsg1 = 1; // HasHasbit() == false
110 // optional Foo submsg2 = 2; // HasHasbit() == true
111 // This is slightly odd, as adding "optional" to a singular proto3 field does
112 // not change the semantics or API. However whenever any field in a message
113 // has a hasbit, it forces reflection to include hasbit offsets for *all*
114 // fields, even if almost all of them are set to -1 (no hasbit). So to avoid
115 // causing a sudden size regression for ~all proto3 messages, we give proto3
116 // message fields a hasbit only if "optional" is present. If the user is
117 // explicitly writing "optional", it is likely they are writing it on
118 // primitive fields also.
119 return (field->has_optional_keyword() || field->is_required()) &&
120 !field->options().weak();
121 }
122
InRealOneof(const FieldDescriptor * field)123 inline bool InRealOneof(const FieldDescriptor* field) {
124 return field->containing_oneof() &&
125 !field->containing_oneof()->is_synthetic();
126 }
127
128 // Compute the byte size of the in-memory representation of the field.
FieldSpaceUsed(const FieldDescriptor * field)129 int FieldSpaceUsed(const FieldDescriptor* field) {
130 typedef FieldDescriptor FD; // avoid line wrapping
131 if (field->label() == FD::LABEL_REPEATED) {
132 switch (field->cpp_type()) {
133 case FD::CPPTYPE_INT32:
134 return sizeof(RepeatedField<int32>);
135 case FD::CPPTYPE_INT64:
136 return sizeof(RepeatedField<int64>);
137 case FD::CPPTYPE_UINT32:
138 return sizeof(RepeatedField<uint32>);
139 case FD::CPPTYPE_UINT64:
140 return sizeof(RepeatedField<uint64>);
141 case FD::CPPTYPE_DOUBLE:
142 return sizeof(RepeatedField<double>);
143 case FD::CPPTYPE_FLOAT:
144 return sizeof(RepeatedField<float>);
145 case FD::CPPTYPE_BOOL:
146 return sizeof(RepeatedField<bool>);
147 case FD::CPPTYPE_ENUM:
148 return sizeof(RepeatedField<int>);
149 case FD::CPPTYPE_MESSAGE:
150 if (IsMapFieldInApi(field)) {
151 return sizeof(DynamicMapField);
152 } else {
153 return sizeof(RepeatedPtrField<Message>);
154 }
155
156 case FD::CPPTYPE_STRING:
157 switch (field->options().ctype()) {
158 default: // TODO(kenton): Support other string reps.
159 case FieldOptions::STRING:
160 return sizeof(RepeatedPtrField<std::string>);
161 }
162 break;
163 }
164 } else {
165 switch (field->cpp_type()) {
166 case FD::CPPTYPE_INT32:
167 return sizeof(int32);
168 case FD::CPPTYPE_INT64:
169 return sizeof(int64);
170 case FD::CPPTYPE_UINT32:
171 return sizeof(uint32);
172 case FD::CPPTYPE_UINT64:
173 return sizeof(uint64);
174 case FD::CPPTYPE_DOUBLE:
175 return sizeof(double);
176 case FD::CPPTYPE_FLOAT:
177 return sizeof(float);
178 case FD::CPPTYPE_BOOL:
179 return sizeof(bool);
180 case FD::CPPTYPE_ENUM:
181 return sizeof(int);
182
183 case FD::CPPTYPE_MESSAGE:
184 return sizeof(Message*);
185
186 case FD::CPPTYPE_STRING:
187 switch (field->options().ctype()) {
188 default: // TODO(kenton): Support other string reps.
189 case FieldOptions::STRING:
190 return sizeof(ArenaStringPtr);
191 }
192 break;
193 }
194 }
195
196 GOOGLE_LOG(DFATAL) << "Can't get here.";
197 return 0;
198 }
199
200 // Compute the byte size of in-memory representation of the oneof fields
201 // in default oneof instance.
OneofFieldSpaceUsed(const FieldDescriptor * field)202 int OneofFieldSpaceUsed(const FieldDescriptor* field) {
203 typedef FieldDescriptor FD; // avoid line wrapping
204 switch (field->cpp_type()) {
205 case FD::CPPTYPE_INT32:
206 return sizeof(int32);
207 case FD::CPPTYPE_INT64:
208 return sizeof(int64);
209 case FD::CPPTYPE_UINT32:
210 return sizeof(uint32);
211 case FD::CPPTYPE_UINT64:
212 return sizeof(uint64);
213 case FD::CPPTYPE_DOUBLE:
214 return sizeof(double);
215 case FD::CPPTYPE_FLOAT:
216 return sizeof(float);
217 case FD::CPPTYPE_BOOL:
218 return sizeof(bool);
219 case FD::CPPTYPE_ENUM:
220 return sizeof(int);
221
222 case FD::CPPTYPE_MESSAGE:
223 return sizeof(Message*);
224
225 case FD::CPPTYPE_STRING:
226 switch (field->options().ctype()) {
227 default:
228 case FieldOptions::STRING:
229 return sizeof(ArenaStringPtr);
230 }
231 break;
232 }
233
234 GOOGLE_LOG(DFATAL) << "Can't get here.";
235 return 0;
236 }
237
DivideRoundingUp(int i,int j)238 inline int DivideRoundingUp(int i, int j) { return (i + (j - 1)) / j; }
239
240 static const int kSafeAlignment = sizeof(uint64);
241 static const int kMaxOneofUnionSize = sizeof(uint64);
242
AlignTo(int offset,int alignment)243 inline int AlignTo(int offset, int alignment) {
244 return DivideRoundingUp(offset, alignment) * alignment;
245 }
246
247 // Rounds the given byte offset up to the next offset aligned such that any
248 // type may be stored at it.
AlignOffset(int offset)249 inline int AlignOffset(int offset) { return AlignTo(offset, kSafeAlignment); }
250
251 #define bitsizeof(T) (sizeof(T) * 8)
252
253 } // namespace
254
255 // ===================================================================
256
257 class DynamicMessage : public Message {
258 public:
259 struct TypeInfo {
260 int size;
261 int has_bits_offset;
262 int oneof_case_offset;
263 int extensions_offset;
264
265 // Not owned by the TypeInfo.
266 DynamicMessageFactory* factory; // The factory that created this object.
267 const DescriptorPool* pool; // The factory's DescriptorPool.
268 const Descriptor* type; // Type of this DynamicMessage.
269
270 // Warning: The order in which the following pointers are defined is
271 // important (the prototype must be deleted *before* the offsets).
272 std::unique_ptr<uint32[]> offsets;
273 std::unique_ptr<uint32[]> has_bits_indices;
274 std::unique_ptr<const Reflection> reflection;
275 // Don't use a unique_ptr to hold the prototype: the destructor for
276 // DynamicMessage needs to know whether it is the prototype, and does so by
277 // looking back at this field. This would assume details about the
278 // implementation of unique_ptr.
279 const DynamicMessage* prototype;
280 int weak_field_map_offset; // The offset for the weak_field_map;
281
TypeInfogoogle::protobuf::DynamicMessage::TypeInfo282 TypeInfo() : prototype(NULL) {}
283
~TypeInfogoogle::protobuf::DynamicMessage::TypeInfo284 ~TypeInfo() { delete prototype; }
285 };
286
287 DynamicMessage(const TypeInfo* type_info);
288
289 // This should only be used by GetPrototypeNoLock() to avoid dead lock.
290 DynamicMessage(TypeInfo* type_info, bool lock_factory);
291
292 ~DynamicMessage();
293
294 // Called on the prototype after construction to initialize message fields.
295 void CrossLinkPrototypes();
296
297 // implements Message ----------------------------------------------
298
299 Message* New() const override;
300 Message* New(Arena* arena) const override;
301
302 int GetCachedSize() const override;
303 void SetCachedSize(int size) const override;
304
305 Metadata GetMetadata() const override;
306
307 // We actually allocate more memory than sizeof(*this) when this
308 // class's memory is allocated via the global operator new. Thus, we need to
309 // manually call the global operator delete. Calling the destructor is taken
310 // care of for us. This makes DynamicMessage compatible with -fsized-delete.
311 // It doesn't work for MSVC though.
312 #ifndef _MSC_VER
operator delete(void * ptr)313 static void operator delete(void* ptr) { ::operator delete(ptr); }
314 #endif // !_MSC_VER
315
316 private:
317 DynamicMessage(const TypeInfo* type_info, Arena* arena);
318
319 void SharedCtor(bool lock_factory);
320
321 // Needed to get the offset of the internal metadata member.
322 friend class DynamicMessageFactory;
323
is_prototype() const324 inline bool is_prototype() const {
325 return type_info_->prototype == this ||
326 // If type_info_->prototype is NULL, then we must be constructing
327 // the prototype now, which means we must be the prototype.
328 type_info_->prototype == NULL;
329 }
330
OffsetToPointer(int offset)331 inline void* OffsetToPointer(int offset) {
332 return reinterpret_cast<uint8*>(this) + offset;
333 }
OffsetToPointer(int offset) const334 inline const void* OffsetToPointer(int offset) const {
335 return reinterpret_cast<const uint8*>(this) + offset;
336 }
337
338 const TypeInfo* type_info_;
339 mutable std::atomic<int> cached_byte_size_;
340 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage);
341 };
342
DynamicMessage(const TypeInfo * type_info)343 DynamicMessage::DynamicMessage(const TypeInfo* type_info)
344 : type_info_(type_info), cached_byte_size_(0) {
345 SharedCtor(true);
346 }
347
DynamicMessage(const TypeInfo * type_info,Arena * arena)348 DynamicMessage::DynamicMessage(const TypeInfo* type_info, Arena* arena)
349 : Message(arena),
350 type_info_(type_info),
351 cached_byte_size_(0) {
352 SharedCtor(true);
353 }
354
DynamicMessage(TypeInfo * type_info,bool lock_factory)355 DynamicMessage::DynamicMessage(TypeInfo* type_info, bool lock_factory)
356 : type_info_(type_info), cached_byte_size_(0) {
357 // The prototype in type_info has to be set before creating the prototype
358 // instance on memory. e.g., message Foo { map<int32, Foo> a = 1; }. When
359 // creating prototype for Foo, prototype of the map entry will also be
360 // created, which needs the address of the prototype of Foo (the value in
361 // map). To break the cyclic dependency, we have to assign the address of
362 // prototype into type_info first.
363 type_info->prototype = this;
364 SharedCtor(lock_factory);
365 }
366
SharedCtor(bool lock_factory)367 void DynamicMessage::SharedCtor(bool lock_factory) {
368 // We need to call constructors for various fields manually and set
369 // default values where appropriate. We use placement new to call
370 // constructors. If you haven't heard of placement new, I suggest Googling
371 // it now. We use placement new even for primitive types that don't have
372 // constructors for consistency. (In theory, placement new should be used
373 // any time you are trying to convert untyped memory to typed memory, though
374 // in practice that's not strictly necessary for types that don't have a
375 // constructor.)
376
377 const Descriptor* descriptor = type_info_->type;
378 // Initialize oneof cases.
379 int oneof_count = 0;
380 for (int i = 0; i < descriptor->oneof_decl_count(); ++i) {
381 if (descriptor->oneof_decl(i)->is_synthetic()) continue;
382 new (OffsetToPointer(type_info_->oneof_case_offset +
383 sizeof(uint32) * oneof_count++)) uint32(0);
384 }
385
386 if (type_info_->extensions_offset != -1) {
387 new (OffsetToPointer(type_info_->extensions_offset))
388 ExtensionSet(GetArena());
389 }
390 for (int i = 0; i < descriptor->field_count(); i++) {
391 const FieldDescriptor* field = descriptor->field(i);
392 void* field_ptr = OffsetToPointer(type_info_->offsets[i]);
393 if (InRealOneof(field)) {
394 continue;
395 }
396 switch (field->cpp_type()) {
397 #define HANDLE_TYPE(CPPTYPE, TYPE) \
398 case FieldDescriptor::CPPTYPE_##CPPTYPE: \
399 if (!field->is_repeated()) { \
400 new (field_ptr) TYPE(field->default_value_##TYPE()); \
401 } else { \
402 new (field_ptr) RepeatedField<TYPE>(GetArena()); \
403 } \
404 break;
405
406 HANDLE_TYPE(INT32, int32);
407 HANDLE_TYPE(INT64, int64);
408 HANDLE_TYPE(UINT32, uint32);
409 HANDLE_TYPE(UINT64, uint64);
410 HANDLE_TYPE(DOUBLE, double);
411 HANDLE_TYPE(FLOAT, float);
412 HANDLE_TYPE(BOOL, bool);
413 #undef HANDLE_TYPE
414
415 case FieldDescriptor::CPPTYPE_ENUM:
416 if (!field->is_repeated()) {
417 new (field_ptr) int(field->default_value_enum()->number());
418 } else {
419 new (field_ptr) RepeatedField<int>(GetArena());
420 }
421 break;
422
423 case FieldDescriptor::CPPTYPE_STRING:
424 switch (field->options().ctype()) {
425 default: // TODO(kenton): Support other string reps.
426 case FieldOptions::STRING:
427 if (!field->is_repeated()) {
428 const std::string* default_value;
429 if (is_prototype()) {
430 default_value = &field->default_value_string();
431 } else {
432 default_value = &(reinterpret_cast<const ArenaStringPtr*>(
433 type_info_->prototype->OffsetToPointer(
434 type_info_->offsets[i]))
435 ->Get());
436 }
437 ArenaStringPtr* asp = new (field_ptr) ArenaStringPtr();
438 asp->UnsafeSetDefault(default_value);
439 } else {
440 new (field_ptr) RepeatedPtrField<std::string>(GetArena());
441 }
442 break;
443 }
444 break;
445
446 case FieldDescriptor::CPPTYPE_MESSAGE: {
447 if (!field->is_repeated()) {
448 new (field_ptr) Message*(NULL);
449 } else {
450 if (IsMapFieldInApi(field)) {
451 // We need to lock in most cases to avoid data racing. Only not lock
452 // when the constructor is called inside GetPrototype(), in which
453 // case we have already locked the factory.
454 if (lock_factory) {
455 if (GetArena() != nullptr) {
456 new (field_ptr) DynamicMapField(
457 type_info_->factory->GetPrototype(field->message_type()),
458 GetArena());
459 } else {
460 new (field_ptr) DynamicMapField(
461 type_info_->factory->GetPrototype(field->message_type()));
462 }
463 } else {
464 if (GetArena() != nullptr) {
465 new (field_ptr)
466 DynamicMapField(type_info_->factory->GetPrototypeNoLock(
467 field->message_type()),
468 GetArena());
469 } else {
470 new (field_ptr)
471 DynamicMapField(type_info_->factory->GetPrototypeNoLock(
472 field->message_type()));
473 }
474 }
475 } else {
476 new (field_ptr) RepeatedPtrField<Message>(GetArena());
477 }
478 }
479 break;
480 }
481 }
482 }
483 }
484
~DynamicMessage()485 DynamicMessage::~DynamicMessage() {
486 const Descriptor* descriptor = type_info_->type;
487
488 _internal_metadata_.Delete<UnknownFieldSet>();
489
490 if (type_info_->extensions_offset != -1) {
491 reinterpret_cast<ExtensionSet*>(
492 OffsetToPointer(type_info_->extensions_offset))
493 ->~ExtensionSet();
494 }
495
496 // We need to manually run the destructors for repeated fields and strings,
497 // just as we ran their constructors in the DynamicMessage constructor.
498 // We also need to manually delete oneof fields if it is set and is string
499 // or message.
500 // Additionally, if any singular embedded messages have been allocated, we
501 // need to delete them, UNLESS we are the prototype message of this type,
502 // in which case any embedded messages are other prototypes and shouldn't
503 // be touched.
504 for (int i = 0; i < descriptor->field_count(); i++) {
505 const FieldDescriptor* field = descriptor->field(i);
506 if (InRealOneof(field)) {
507 void* field_ptr =
508 OffsetToPointer(type_info_->oneof_case_offset +
509 sizeof(uint32) * field->containing_oneof()->index());
510 if (*(reinterpret_cast<const uint32*>(field_ptr)) == field->number()) {
511 field_ptr = OffsetToPointer(
512 type_info_->offsets[descriptor->field_count() +
513 field->containing_oneof()->index()]);
514 if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
515 switch (field->options().ctype()) {
516 default:
517 case FieldOptions::STRING: {
518 const std::string* default_value =
519 &(reinterpret_cast<const ArenaStringPtr*>(
520 reinterpret_cast<const uint8*>(type_info_->prototype) +
521 type_info_->offsets[i])
522 ->Get());
523 reinterpret_cast<ArenaStringPtr*>(field_ptr)->Destroy(
524 default_value, NULL);
525 break;
526 }
527 }
528 } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
529 delete *reinterpret_cast<Message**>(field_ptr);
530 }
531 }
532 continue;
533 }
534 void* field_ptr = OffsetToPointer(type_info_->offsets[i]);
535
536 if (field->is_repeated()) {
537 switch (field->cpp_type()) {
538 #define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
539 case FieldDescriptor::CPPTYPE_##UPPERCASE: \
540 reinterpret_cast<RepeatedField<LOWERCASE>*>(field_ptr) \
541 ->~RepeatedField<LOWERCASE>(); \
542 break
543
544 HANDLE_TYPE(INT32, int32);
545 HANDLE_TYPE(INT64, int64);
546 HANDLE_TYPE(UINT32, uint32);
547 HANDLE_TYPE(UINT64, uint64);
548 HANDLE_TYPE(DOUBLE, double);
549 HANDLE_TYPE(FLOAT, float);
550 HANDLE_TYPE(BOOL, bool);
551 HANDLE_TYPE(ENUM, int);
552 #undef HANDLE_TYPE
553
554 case FieldDescriptor::CPPTYPE_STRING:
555 switch (field->options().ctype()) {
556 default: // TODO(kenton): Support other string reps.
557 case FieldOptions::STRING:
558 reinterpret_cast<RepeatedPtrField<std::string>*>(field_ptr)
559 ->~RepeatedPtrField<std::string>();
560 break;
561 }
562 break;
563
564 case FieldDescriptor::CPPTYPE_MESSAGE:
565 if (IsMapFieldInApi(field)) {
566 reinterpret_cast<DynamicMapField*>(field_ptr)->~DynamicMapField();
567 } else {
568 reinterpret_cast<RepeatedPtrField<Message>*>(field_ptr)
569 ->~RepeatedPtrField<Message>();
570 }
571 break;
572 }
573
574 } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
575 switch (field->options().ctype()) {
576 default: // TODO(kenton): Support other string reps.
577 case FieldOptions::STRING: {
578 const std::string* default_value =
579 &(reinterpret_cast<const ArenaStringPtr*>(
580 type_info_->prototype->OffsetToPointer(
581 type_info_->offsets[i]))
582 ->Get());
583 reinterpret_cast<ArenaStringPtr*>(field_ptr)->Destroy(default_value,
584 NULL);
585 break;
586 }
587 }
588 } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
589 if (!is_prototype()) {
590 Message* message = *reinterpret_cast<Message**>(field_ptr);
591 if (message != NULL) {
592 delete message;
593 }
594 }
595 }
596 }
597 }
598
CrossLinkPrototypes()599 void DynamicMessage::CrossLinkPrototypes() {
600 // This should only be called on the prototype message.
601 GOOGLE_CHECK(is_prototype());
602
603 DynamicMessageFactory* factory = type_info_->factory;
604 const Descriptor* descriptor = type_info_->type;
605
606 // Cross-link default messages.
607 for (int i = 0; i < descriptor->field_count(); i++) {
608 const FieldDescriptor* field = descriptor->field(i);
609 void* field_ptr = OffsetToPointer(type_info_->offsets[i]);
610 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
611 !field->is_repeated()) {
612 // For fields with message types, we need to cross-link with the
613 // prototype for the field's type.
614 // For singular fields, the field is just a pointer which should
615 // point to the prototype.
616 *reinterpret_cast<const Message**>(field_ptr) =
617 factory->GetPrototypeNoLock(field->message_type());
618 }
619 }
620 }
621
New() const622 Message* DynamicMessage::New() const { return New(NULL); }
623
New(Arena * arena) const624 Message* DynamicMessage::New(Arena* arena) const {
625 if (arena != NULL) {
626 void* new_base = Arena::CreateArray<char>(arena, type_info_->size);
627 memset(new_base, 0, type_info_->size);
628 return new (new_base) DynamicMessage(type_info_, arena);
629 } else {
630 void* new_base = operator new(type_info_->size);
631 memset(new_base, 0, type_info_->size);
632 return new (new_base) DynamicMessage(type_info_);
633 }
634 }
635
GetCachedSize() const636 int DynamicMessage::GetCachedSize() const {
637 return cached_byte_size_.load(std::memory_order_relaxed);
638 }
639
SetCachedSize(int size) const640 void DynamicMessage::SetCachedSize(int size) const {
641 cached_byte_size_.store(size, std::memory_order_relaxed);
642 }
643
GetMetadata() const644 Metadata DynamicMessage::GetMetadata() const {
645 Metadata metadata;
646 metadata.descriptor = type_info_->type;
647 metadata.reflection = type_info_->reflection.get();
648 return metadata;
649 }
650
651 // ===================================================================
652
653 struct DynamicMessageFactory::PrototypeMap {
654 typedef std::unordered_map<const Descriptor*, const DynamicMessage::TypeInfo*>
655 Map;
656 Map map_;
657 };
658
DynamicMessageFactory()659 DynamicMessageFactory::DynamicMessageFactory()
660 : pool_(NULL),
661 delegate_to_generated_factory_(false),
662 prototypes_(new PrototypeMap) {}
663
DynamicMessageFactory(const DescriptorPool * pool)664 DynamicMessageFactory::DynamicMessageFactory(const DescriptorPool* pool)
665 : pool_(pool),
666 delegate_to_generated_factory_(false),
667 prototypes_(new PrototypeMap) {}
668
~DynamicMessageFactory()669 DynamicMessageFactory::~DynamicMessageFactory() {
670 for (PrototypeMap::Map::iterator iter = prototypes_->map_.begin();
671 iter != prototypes_->map_.end(); ++iter) {
672 DeleteDefaultOneofInstance(iter->second->type, iter->second->offsets.get(),
673 iter->second->prototype);
674 delete iter->second;
675 }
676 }
677
GetPrototype(const Descriptor * type)678 const Message* DynamicMessageFactory::GetPrototype(const Descriptor* type) {
679 MutexLock lock(&prototypes_mutex_);
680 return GetPrototypeNoLock(type);
681 }
682
GetPrototypeNoLock(const Descriptor * type)683 const Message* DynamicMessageFactory::GetPrototypeNoLock(
684 const Descriptor* type) {
685 if (delegate_to_generated_factory_ &&
686 type->file()->pool() == DescriptorPool::generated_pool()) {
687 return MessageFactory::generated_factory()->GetPrototype(type);
688 }
689
690 const DynamicMessage::TypeInfo** target = &prototypes_->map_[type];
691 if (*target != NULL) {
692 // Already exists.
693 return (*target)->prototype;
694 }
695
696 DynamicMessage::TypeInfo* type_info = new DynamicMessage::TypeInfo;
697 *target = type_info;
698
699 type_info->type = type;
700 type_info->pool = (pool_ == NULL) ? type->file()->pool() : pool_;
701 type_info->factory = this;
702
703 // We need to construct all the structures passed to Reflection's constructor.
704 // This includes:
705 // - A block of memory that contains space for all the message's fields.
706 // - An array of integers indicating the byte offset of each field within
707 // this block.
708 // - A big bitfield containing a bit for each field indicating whether
709 // or not that field is set.
710 int real_oneof_count = 0;
711 for (int i = 0; i < type->oneof_decl_count(); i++) {
712 if (!type->oneof_decl(i)->is_synthetic()) {
713 real_oneof_count++;
714 }
715 }
716
717 // Compute size and offsets.
718 uint32* offsets = new uint32[type->field_count() + real_oneof_count];
719 type_info->offsets.reset(offsets);
720
721 // Decide all field offsets by packing in order.
722 // We place the DynamicMessage object itself at the beginning of the allocated
723 // space.
724 int size = sizeof(DynamicMessage);
725 size = AlignOffset(size);
726
727 // Next the has_bits, which is an array of uint32s.
728 type_info->has_bits_offset = -1;
729 int max_hasbit = 0;
730 for (int i = 0; i < type->field_count(); i++) {
731 if (HasHasbit(type->field(i))) {
732 if (type_info->has_bits_offset == -1) {
733 // At least one field in the message requires a hasbit, so allocate
734 // hasbits.
735 type_info->has_bits_offset = size;
736 uint32* has_bits_indices = new uint32[type->field_count()];
737 for (int i = 0; i < type->field_count(); i++) {
738 // Initialize to -1, fields that need a hasbit will overwrite.
739 has_bits_indices[i] = static_cast<uint32>(-1);
740 }
741 type_info->has_bits_indices.reset(has_bits_indices);
742 }
743 type_info->has_bits_indices[i] = max_hasbit++;
744 }
745 }
746
747 if (max_hasbit > 0) {
748 int has_bits_array_size = DivideRoundingUp(max_hasbit, bitsizeof(uint32));
749 size += has_bits_array_size * sizeof(uint32);
750 size = AlignOffset(size);
751 }
752
753 // The oneof_case, if any. It is an array of uint32s.
754 if (real_oneof_count > 0) {
755 type_info->oneof_case_offset = size;
756 size += real_oneof_count * sizeof(uint32);
757 size = AlignOffset(size);
758 }
759
760 // The ExtensionSet, if any.
761 if (type->extension_range_count() > 0) {
762 type_info->extensions_offset = size;
763 size += sizeof(ExtensionSet);
764 size = AlignOffset(size);
765 } else {
766 // No extensions.
767 type_info->extensions_offset = -1;
768 }
769
770 // All the fields.
771 //
772 // TODO(b/31226269): Optimize the order of fields to minimize padding.
773 int num_weak_fields = 0;
774 for (int i = 0; i < type->field_count(); i++) {
775 // Make sure field is aligned to avoid bus errors.
776 // Oneof fields do not use any space.
777 if (!InRealOneof(type->field(i))) {
778 int field_size = FieldSpaceUsed(type->field(i));
779 size = AlignTo(size, std::min(kSafeAlignment, field_size));
780 offsets[i] = size;
781 size += field_size;
782 }
783 }
784
785 // The oneofs.
786 for (int i = 0; i < type->oneof_decl_count(); i++) {
787 if (!type->oneof_decl(i)->is_synthetic()) {
788 size = AlignTo(size, kSafeAlignment);
789 offsets[type->field_count() + i] = size;
790 size += kMaxOneofUnionSize;
791 }
792 }
793
794 type_info->weak_field_map_offset = -1;
795
796 // Align the final size to make sure no clever allocators think that
797 // alignment is not necessary.
798 type_info->size = size;
799
800 // Construct the reflection object.
801
802 // Compute the size of default oneof instance and offsets of default
803 // oneof fields.
804 for (int i = 0; i < type->oneof_decl_count(); i++) {
805 if (type->oneof_decl(i)->is_synthetic()) continue;
806 for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) {
807 const FieldDescriptor* field = type->oneof_decl(i)->field(j);
808 int field_size = OneofFieldSpaceUsed(field);
809 size = AlignTo(size, std::min(kSafeAlignment, field_size));
810 offsets[field->index()] = size;
811 size += field_size;
812 }
813 }
814 size = AlignOffset(size);
815 // Allocate the prototype + oneof fields.
816 void* base = operator new(size);
817 memset(base, 0, size);
818
819 // We have already locked the factory so we should not lock in the constructor
820 // of dynamic message to avoid dead lock.
821 DynamicMessage* prototype = new (base) DynamicMessage(type_info, false);
822
823 if (real_oneof_count > 0 || num_weak_fields > 0) {
824 // Construct default oneof instance.
825 ConstructDefaultOneofInstance(type_info->type, type_info->offsets.get(),
826 prototype);
827 }
828
829 internal::ReflectionSchema schema = {
830 type_info->prototype,
831 type_info->offsets.get(),
832 type_info->has_bits_indices.get(),
833 type_info->has_bits_offset,
834 PROTOBUF_FIELD_OFFSET(DynamicMessage, _internal_metadata_),
835 type_info->extensions_offset,
836 type_info->oneof_case_offset,
837 type_info->size,
838 type_info->weak_field_map_offset};
839
840 type_info->reflection.reset(
841 new Reflection(type_info->type, schema, type_info->pool, this));
842
843 // Cross link prototypes.
844 prototype->CrossLinkPrototypes();
845
846 return prototype;
847 }
848
ConstructDefaultOneofInstance(const Descriptor * type,const uint32 offsets[],void * default_oneof_or_weak_instance)849 void DynamicMessageFactory::ConstructDefaultOneofInstance(
850 const Descriptor* type, const uint32 offsets[],
851 void* default_oneof_or_weak_instance) {
852 for (int i = 0; i < type->oneof_decl_count(); i++) {
853 if (type->oneof_decl(i)->is_synthetic()) continue;
854 for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) {
855 const FieldDescriptor* field = type->oneof_decl(i)->field(j);
856 void* field_ptr =
857 reinterpret_cast<uint8*>(default_oneof_or_weak_instance) +
858 offsets[field->index()];
859 switch (field->cpp_type()) {
860 #define HANDLE_TYPE(CPPTYPE, TYPE) \
861 case FieldDescriptor::CPPTYPE_##CPPTYPE: \
862 new (field_ptr) TYPE(field->default_value_##TYPE()); \
863 break;
864
865 HANDLE_TYPE(INT32, int32);
866 HANDLE_TYPE(INT64, int64);
867 HANDLE_TYPE(UINT32, uint32);
868 HANDLE_TYPE(UINT64, uint64);
869 HANDLE_TYPE(DOUBLE, double);
870 HANDLE_TYPE(FLOAT, float);
871 HANDLE_TYPE(BOOL, bool);
872 #undef HANDLE_TYPE
873
874 case FieldDescriptor::CPPTYPE_ENUM:
875 new (field_ptr) int(field->default_value_enum()->number());
876 break;
877 case FieldDescriptor::CPPTYPE_STRING:
878 switch (field->options().ctype()) {
879 default:
880 case FieldOptions::STRING:
881 ArenaStringPtr* asp = new (field_ptr) ArenaStringPtr();
882 asp->UnsafeSetDefault(&field->default_value_string());
883 break;
884 }
885 break;
886
887 case FieldDescriptor::CPPTYPE_MESSAGE: {
888 new (field_ptr) Message*(NULL);
889 break;
890 }
891 }
892 }
893 }
894 }
895
DeleteDefaultOneofInstance(const Descriptor * type,const uint32 offsets[],const void * default_oneof_instance)896 void DynamicMessageFactory::DeleteDefaultOneofInstance(
897 const Descriptor* type, const uint32 offsets[],
898 const void* default_oneof_instance) {
899 for (int i = 0; i < type->oneof_decl_count(); i++) {
900 if (type->oneof_decl(i)->is_synthetic()) continue;
901 for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) {
902 const FieldDescriptor* field = type->oneof_decl(i)->field(j);
903 if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
904 switch (field->options().ctype()) {
905 default:
906 case FieldOptions::STRING:
907 break;
908 }
909 }
910 }
911 }
912 }
913
914 } // namespace protobuf
915 } // namespace google
916
917 #include <google/protobuf/port_undef.inc> // NOLINT
918