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