mirror of
https://github.com/protocolbuffers/protobuf
synced 2026-08-26 02:23:14 -04:00
Change Reflection::GetDefaultMessageInstance to Reflection::GetMessageClassData.
`Reflection::GetMessageClassData` now has to call `GetClassData` on the prototype returned from the message factory, as the `MessageFactory` interface only has a `GetPrototype` method. We could add a `GetClassData` method to the generated message factory, but we already cache the `ClassData` pointer in the `FieldDescriptor` for fields from the generated factory. We couldn't add a `GetClassData` to dynamic factories, as `ClassData` is `internal` and dynamic factories have a public interface that users can override. This cl includes a refactor of `LazyField::InternalWrite` to accept `ClassData` instead of a `MessageLite` prototype, and changes the cached prototype to `ClassData` in `FieldDescriptor`. PiperOrigin-RevId: 963758127
This commit is contained in:
parent
7b59c75e36
commit
d0be1f2cb0
8 changed files with 41 additions and 26 deletions
|
|
@ -6437,7 +6437,7 @@ void internal::DescriptorBuilder::BuildFieldOrExtension(
|
|||
DescriptorPool::ErrorCollector::DEFAULT_VALUE,
|
||||
"Messages can't have default values.");
|
||||
result->has_default_value_ = false;
|
||||
result->default_generated_instance_ = nullptr;
|
||||
result->generated_class_data_ = nullptr;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -6485,7 +6485,7 @@ void internal::DescriptorBuilder::BuildFieldOrExtension(
|
|||
result->default_value_string_ = &internal::GetEmptyString();
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
result->default_generated_instance_ = nullptr;
|
||||
result->generated_class_data_ = nullptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@
|
|||
#include "absl/strings/str_format.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "google/protobuf/class_data.h"
|
||||
#include "google/protobuf/descriptor_lite.h" // IWYU pragma: export
|
||||
#include "google/protobuf/extension_set.h"
|
||||
#include "google/protobuf/offset_ptr.h"
|
||||
|
|
@ -1363,7 +1364,7 @@ class PROTOBUF_EXPORT FieldDescriptor : private internal::SymbolBase,
|
|||
|
||||
mutable const EnumValueDescriptor* default_value_enum_;
|
||||
const std::string* default_value_string_;
|
||||
mutable std::atomic<const Message*> default_generated_instance_;
|
||||
mutable std::atomic<const internal::ClassData*> generated_class_data_;
|
||||
};
|
||||
|
||||
static const CppType kTypeToCppTypeMap[MAX_TYPE + 1];
|
||||
|
|
|
|||
|
|
@ -393,7 +393,7 @@ size_t ExtensionSet::GetMessageByteSizeLong(int number) const {
|
|||
}
|
||||
|
||||
uint8_t* ExtensionSet::InternalSerializeMessage(
|
||||
int number, const MessageLite* prototype, uint8_t* target,
|
||||
int number, const ClassData* class_data, uint8_t* target,
|
||||
io::EpsCopyOutputStream* stream) const {
|
||||
const Extension* extension = FindOrNull(number);
|
||||
ABSL_CHECK(extension != nullptr) << "not present";
|
||||
|
|
@ -1846,7 +1846,7 @@ uint8_t* ExtensionSet::Extension::InternalSerializeFieldWithCachedSizesToArray(
|
|||
return target;
|
||||
}
|
||||
|
||||
const MessageLite* ExtensionSet::GetPrototypeForLazyMessage(
|
||||
const ClassData* ExtensionSet::GetClassDataForLazyMessage(
|
||||
const MessageLite* extendee, int number) {
|
||||
GeneratedExtensionFinder finder(extendee);
|
||||
bool was_packed_on_wire = false;
|
||||
|
|
@ -1856,7 +1856,7 @@ const MessageLite* ExtensionSet::GetPrototypeForLazyMessage(
|
|||
&extension_info, &was_packed_on_wire)) {
|
||||
return nullptr;
|
||||
}
|
||||
return extension_info.message_info.GetPrototype();
|
||||
return extension_info.message_info.GetClassData();
|
||||
}
|
||||
|
||||
uint8_t*
|
||||
|
|
|
|||
|
|
@ -696,7 +696,7 @@ class PROTOBUF_EXPORT ExtensionSet {
|
|||
static bool FieldTypeIsPointer(FieldType type);
|
||||
|
||||
size_t GetMessageByteSizeLong(int number) const;
|
||||
uint8_t* InternalSerializeMessage(int number, const MessageLite* prototype,
|
||||
uint8_t* InternalSerializeMessage(int number, const ClassData* class_data,
|
||||
uint8_t* target,
|
||||
io::EpsCopyOutputStream* stream) const;
|
||||
|
||||
|
|
@ -1158,9 +1158,9 @@ class PROTOBUF_EXPORT ExtensionSet {
|
|||
return expected_wire_type == wire_type;
|
||||
}
|
||||
|
||||
// Find the prototype for a LazyMessage from the extension registry. Returns
|
||||
// null if the extension is not found.
|
||||
static const MessageLite* GetPrototypeForLazyMessage(
|
||||
// Returns the ClassData for a LazyMessage from the extension registry.
|
||||
// Returns null if the extension is not found.
|
||||
static const ClassData* GetClassDataForLazyMessage(
|
||||
const MessageLite* extendee, int number);
|
||||
|
||||
// Returns true if extension is present and lazy.
|
||||
|
|
|
|||
|
|
@ -2574,7 +2574,7 @@ void Reflection::AddEnumValueInternal(Message* message,
|
|||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
const Message* Reflection::GetDefaultMessageInstance(
|
||||
const internal::ClassData* Reflection::GetMessageClassData(
|
||||
const FieldDescriptor* field) const {
|
||||
// If we are using the generated factory, we cache the prototype in the field
|
||||
// descriptor for faster access.
|
||||
|
|
@ -2582,11 +2582,13 @@ const Message* Reflection::GetDefaultMessageInstance(
|
|||
// means they contain null pointers on their message fields and can't be used
|
||||
// to get the default of submessages.
|
||||
if (message_factory_ == MessageFactory::generated_factory()) {
|
||||
auto& ptr = field->default_generated_instance_;
|
||||
auto& ptr = field->generated_class_data_;
|
||||
auto* res = ptr.load(std::memory_order_acquire);
|
||||
if (res == nullptr) {
|
||||
// First time asking for this field's default. Load it and cache it.
|
||||
res = message_factory_->GetPrototype(field->message_type());
|
||||
const MessageLite* prototype =
|
||||
message_factory_->GetPrototype(field->message_type());
|
||||
res = internal::GetClassData(*prototype);
|
||||
ptr.store(res, std::memory_order_release);
|
||||
}
|
||||
return res;
|
||||
|
|
@ -2602,12 +2604,13 @@ const Message* Reflection::GetDefaultMessageInstance(
|
|||
PROTOBUF_IGNORE_DEPRECATION_STOP
|
||||
if (!field->is_extension() && !field->is_repeated() && !field_is_weak &&
|
||||
!IsLazyField(field) && !schema_.InRealOneof(field)) {
|
||||
auto* res = DefaultRaw<const Message*>(field);
|
||||
ABSL_DCHECK_NE(res, nullptr);
|
||||
return res;
|
||||
const Message* prototype = DefaultRaw<const Message*>(field);
|
||||
ABSL_DCHECK_NE(prototype, nullptr);
|
||||
return internal::GetClassData(*prototype);
|
||||
}
|
||||
// Otherwise, just go to the factory.
|
||||
return message_factory_->GetPrototype(field->message_type());
|
||||
return internal::GetClassData(
|
||||
*message_factory_->GetPrototype(field->message_type()));
|
||||
}
|
||||
|
||||
const Message& Reflection::GetMessage(const Message& message,
|
||||
|
|
@ -2622,11 +2625,13 @@ const Message& Reflection::GetMessage(const Message& message,
|
|||
message.GetArena(), field->number(), field->message_type(), factory));
|
||||
} else {
|
||||
if (schema_.InRealOneof(field) && !HasOneofField(message, field)) {
|
||||
return *GetDefaultMessageInstance(field);
|
||||
return *DownCastMessage<Message>(
|
||||
GetMessageClassData(field)->default_instance());
|
||||
}
|
||||
const Message* result = GetRaw<const Message*>(message, field);
|
||||
if (result == nullptr) {
|
||||
result = GetDefaultMessageInstance(field);
|
||||
result = DownCastMessage<Message>(
|
||||
GetMessageClassData(field)->default_instance());
|
||||
}
|
||||
return *result;
|
||||
}
|
||||
|
|
@ -2652,16 +2657,16 @@ Message* Reflection::MutableMessage(Message* message,
|
|||
if (!HasOneofField(*message, field)) {
|
||||
ClearOneof(message, field->containing_oneof());
|
||||
result_holder = MutableField<Message*>(message, field);
|
||||
const Message* default_message = GetDefaultMessageInstance(field);
|
||||
*result_holder = default_message->New(arena);
|
||||
*result_holder =
|
||||
DownCastMessage<Message>(GetMessageClassData(field)->New(arena));
|
||||
}
|
||||
} else {
|
||||
SetHasBit(message, field);
|
||||
}
|
||||
|
||||
if (*result_holder == nullptr) {
|
||||
const Message* default_message = GetDefaultMessageInstance(field);
|
||||
*result_holder = default_message->New(arena);
|
||||
*result_holder =
|
||||
DownCastMessage<Message>(GetMessageClassData(field)->New(arena));
|
||||
}
|
||||
result = *result_holder;
|
||||
return result;
|
||||
|
|
@ -3759,8 +3764,7 @@ void Reflection::PopulateTcParseFieldAux(
|
|||
field_aux++->offset = schema_.SizeofSplit();
|
||||
break;
|
||||
case internal::TailCallTableInfo::kClassData:
|
||||
field_aux++->class_data_p =
|
||||
internal::GetClassData(*GetDefaultMessageInstance(aux_entry.field));
|
||||
field_aux++->class_data_p = GetMessageClassData(aux_entry.field);
|
||||
break;
|
||||
case internal::TailCallTableInfo::kClassDataWeak:
|
||||
case internal::TailCallTableInfo::kMessageVerifyFunc:
|
||||
|
|
|
|||
|
|
@ -1345,7 +1345,8 @@ class PROTOBUF_EXPORT Reflection final {
|
|||
template <typename Type>
|
||||
const Type& DefaultRaw(const FieldDescriptor* field) const;
|
||||
|
||||
const Message* GetDefaultMessageInstance(const FieldDescriptor* field) const;
|
||||
const internal::ClassData* GetMessageClassData(
|
||||
const FieldDescriptor* field) const;
|
||||
|
||||
const uint32_t* GetHasBits(const Message& message) const;
|
||||
inline uint32_t* MutableHasBits(Message* message) const;
|
||||
|
|
|
|||
|
|
@ -258,6 +258,10 @@ struct MessageGlobalsBase {
|
|||
const void* default_instance) {
|
||||
return reinterpret_cast<const MessageGlobalsBase*>(default_instance);
|
||||
}
|
||||
|
||||
static const MessageGlobalsBase* FromClassData(const ClassData* class_data) {
|
||||
return FromDefaultInstance(class_data->default_instance());
|
||||
}
|
||||
};
|
||||
|
||||
template <const auto* kDefault, const auto* kClassData>
|
||||
|
|
@ -302,6 +306,10 @@ struct MessageGlobalsBase {
|
|||
}
|
||||
constexpr const ClassData* GetClassData() const { return class_data.base(); }
|
||||
|
||||
static const MessageGlobalsBase* FromClassData(const void* class_data) {
|
||||
return reinterpret_cast<const MessageGlobalsBase*>(class_data);
|
||||
}
|
||||
|
||||
explicit constexpr MessageGlobalsBase(ClassDataFull class_data)
|
||||
: class_data(class_data) {}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "absl/log/absl_log.h"
|
||||
#include "absl/strings/cord.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "google/protobuf/class_data.h"
|
||||
#include "google/protobuf/descriptor.h"
|
||||
#include "google/protobuf/descriptor.pb.h"
|
||||
#include "google/protobuf/dynamic_message.h"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue