Skip to content

Commit 183bfee

Browse files
sbenzaquencopybara-github
authored andcommitted
Cache the result of FieldDescriptor::is_map().
This is queried from reflection frequently. PiperOrigin-RevId: 756861989
1 parent f9727e8 commit 183bfee

File tree

2 files changed

+14
-1
lines changed

2 files changed

+14
-1
lines changed

src/google/protobuf/descriptor.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7035,6 +7035,7 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto,
70357035
result->is_extension_ = is_extension;
70367036
result->is_oneof_ = false;
70377037
result->in_real_oneof_ = false;
7038+
result->is_map_ = false;
70387039
result->proto3_optional_ = proto.proto3_optional();
70397040
result->legacy_proto_ctype_ = FieldOptions::CType_MAX + 1;
70407041
// We initialize to STRING because descriptor.proto needs it for
@@ -7982,6 +7983,13 @@ void DescriptorBuilder::CrossLinkField(FieldDescriptor* field,
79827983
}
79837984
}
79847985

7986+
// Map entries must be in the same file, so we can populate it directly if
7987+
// the descriptor is already known. If it is not known, then it must not be
7988+
// a map entry.
7989+
if (auto* sub_message = type.descriptor()) {
7990+
field->is_map_ = sub_message->options().map_entry();
7991+
}
7992+
79857993
if (!type.IsVisibleFrom(file_)) {
79867994
AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
79877995
[&] { return type.GetVisibilityError(file_); });

src/google/protobuf/descriptor.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1182,6 +1182,10 @@ class PROTOBUF_EXPORT FieldDescriptor : private internal::SymbolBase,
11821182
// Located here for bitpacking.
11831183
bool in_real_oneof_ : 1;
11841184

1185+
// We could calculate as `message_type()->options().map_entry()`, but that is
1186+
// way more expensive and can potentially force load extra lazy files.
1187+
bool is_map_ : 1;
1188+
11851189
// Actually an optional `CType`, but stored as uint8_t to save space. This
11861190
// contains the original ctype option specified in the .proto file.
11871191
uint8_t legacy_proto_ctype_ : 2;
@@ -2937,7 +2941,8 @@ inline bool FieldDescriptor::is_packable() const {
29372941
}
29382942

29392943
inline bool FieldDescriptor::is_map() const {
2940-
return type() == TYPE_MESSAGE && is_map_message_type();
2944+
ABSL_DCHECK_EQ(is_map_, type() == TYPE_MESSAGE && is_map_message_type());
2945+
return is_map_;
29412946
}
29422947

29432948
inline const OneofDescriptor* FieldDescriptor::real_containing_oneof() const {

0 commit comments

Comments
 (0)