@@ -121,18 +121,21 @@ void DebugAssertUniformLikelyPresence(
121
121
// to use.
122
122
std::string GenerateConditionMaybeWithProbability (
123
123
uint32_t mask, std::optional<float > probability, bool use_cached_has_bits,
124
- std::optional<int > has_array_index, bool is_batch = false ) {
124
+ std::optional<int > has_array_index, bool is_batch, bool is_repeated) {
125
+ ABSL_DCHECK (!is_batch || !is_repeated);
125
126
std::string condition;
126
127
if (use_cached_has_bits) {
127
- condition = absl::StrFormat (" %sCheckHasBit(cached_has_bits, 0x%08xU)" ,
128
- (is_batch ? " Batch" : " " ), mask);
128
+ condition = absl::StrFormat (" %sCheckHasBit%s(cached_has_bits, 0x%08xU)" ,
129
+ (is_batch ? " Batch" : " " ),
130
+ (is_repeated ? " ForRepeated" : " " ), mask);
129
131
} else {
130
132
// We only use has_array_index when use_cached_has_bits is false, make sure
131
133
// we pas a valid index when we need it.
132
134
ABSL_DCHECK (has_array_index.has_value ());
133
- condition =
134
- absl::StrFormat (" %sCheckHasBit(this_._impl_._has_bits_[%d], 0x%08xU)" ,
135
- (is_batch ? " Batch" : " " ), *has_array_index, mask);
135
+ condition = absl::StrFormat (
136
+ " %sCheckHasBit%s(this_._impl_._has_bits_[%d], 0x%08xU)" ,
137
+ (is_batch ? " Batch" : " " ), (is_repeated ? " ForRepeated" : " " ),
138
+ *has_array_index, mask);
136
139
}
137
140
if (probability.has_value ()) {
138
141
return absl::StrFormat (" PROTOBUF_EXPECT_TRUE_WITH_PROBABILITY(%s, %.3f)" ,
@@ -142,12 +145,13 @@ std::string GenerateConditionMaybeWithProbability(
142
145
}
143
146
144
147
std::string GenerateConditionMaybeWithProbabilityForField (
145
- int has_bit_index, const FieldDescriptor* field, const Options& options) {
148
+ int has_bit_index, const FieldDescriptor* field, const Options& options,
149
+ bool is_repeated) {
146
150
auto prob = GetPresenceProbability (field, options);
147
- return GenerateConditionMaybeWithProbability (
148
- 1u << (has_bit_index % 32 ), prob ,
149
- /* use_cached_has_bits */ true ,
150
- /* has_array_index */ std::nullopt );
151
+ return GenerateConditionMaybeWithProbability (1u << (has_bit_index % 32 ), prob,
152
+ /* use_cached_has_bits */ true ,
153
+ /* has_array_index */ std::nullopt ,
154
+ /* is_batch= */ false , is_repeated );
151
155
}
152
156
153
157
std::string GenerateConditionMaybeWithProbabilityForGroup (
@@ -157,7 +161,8 @@ std::string GenerateConditionMaybeWithProbabilityForGroup(
157
161
return GenerateConditionMaybeWithProbability (mask, prob,
158
162
/* use_cached_has_bits*/ true ,
159
163
/* has_array_index*/ std::nullopt,
160
- /* is_batch*/ true );
164
+ /* is_batch*/ true ,
165
+ /* is_repeated*/ false );
161
166
}
162
167
163
168
void PrintPresenceCheck (const FieldDescriptor* field,
@@ -172,8 +177,9 @@ void PrintPresenceCheck(const FieldDescriptor* field,
172
177
cached_has_bits = $has_bits$[$index$];
173
178
)cc" );
174
179
}
175
- p->Emit ({{" condition" , GenerateConditionMaybeWithProbabilityForField (
176
- has_bit_index, field, options)}},
180
+ p->Emit ({{" condition" ,
181
+ GenerateConditionMaybeWithProbabilityForField (
182
+ has_bit_index, field, options, field->is_repeated ())}},
177
183
R"cc(
178
184
if ($condition$) {
179
185
)cc" );
@@ -686,6 +692,14 @@ MessageGenerator::MessageGenerator(
686
692
index_in_file_messages_);
687
693
}
688
694
695
+ bool MessageGenerator::ShouldGenerateEnclosingIf (
696
+ const FieldDescriptor& field) const {
697
+ return HasBitIndex (&field) != kNoHasbit &&
698
+ (field.is_repeated () ||
699
+ field.cpp_type () == FieldDescriptor::CPPTYPE_MESSAGE ||
700
+ field.cpp_type () == FieldDescriptor::CPPTYPE_STRING);
701
+ }
702
+
689
703
size_t MessageGenerator::HasBitsSize () const {
690
704
return (max_has_bit_index_ + 31 ) / 32 ;
691
705
}
@@ -1236,9 +1250,13 @@ void MessageGenerator::GenerateFieldClear(const FieldDescriptor* field,
1236
1250
field_generators_.get (field).GenerateClearingCode (p);
1237
1251
if (HasHasbit (field, options_)) {
1238
1252
auto v = p->WithVars (HasBitVars (field));
1239
- p->Emit (R"cc(
1240
- ClearHasBit($has_bits$[$has_array_index$], $has_mask$);
1241
- )cc" );
1253
+ p->Emit ({{" clear_has_bit" , field->is_repeated ()
1254
+ ? " ClearHasBitForRepeated"
1255
+ : " ClearHasBit" }},
1256
+ R"cc(
1257
+ $clear_has_bit$($has_bits$[$has_array_index$],
1258
+ $has_mask$);
1259
+ )cc" );
1242
1260
}
1243
1261
}
1244
1262
}}},
@@ -1345,8 +1363,9 @@ void MessageGenerator::EmitCheckAndUpdateByteSizeForField(
1345
1363
}
1346
1364
1347
1365
int has_bit_index = has_bit_indices_[field->index ()];
1348
- p->Emit ({{" condition" , GenerateConditionMaybeWithProbabilityForField (
1349
- has_bit_index, field, options_)},
1366
+ p->Emit ({{" condition" ,
1367
+ GenerateConditionMaybeWithProbabilityForField (
1368
+ has_bit_index, field, options_, field->is_repeated ())},
1350
1369
{" check_nondefault_and_emit_body" ,
1351
1370
[&] {
1352
1371
// Note that it's possible that the field has explicit presence.
@@ -3265,8 +3284,9 @@ void MessageGenerator::GenerateCopyInitFields(io::Printer* p) const {
3265
3284
p->Emit (" from.$field$ != nullptr" );
3266
3285
} else {
3267
3286
int has_bit_index = has_bit_indices_[field->index ()];
3268
- p->Emit ({{" condition" , GenerateConditionMaybeWithProbabilityForField (
3269
- has_bit_index, field, options_)}},
3287
+ p->Emit ({{" condition" ,
3288
+ GenerateConditionMaybeWithProbabilityForField (
3289
+ has_bit_index, field, options_, /* is_repeated=*/ false )}},
3270
3290
" $condition$" );
3271
3291
}
3272
3292
};
@@ -3630,7 +3650,6 @@ void MessageGenerator::GenerateClear(io::Printer* p) {
3630
3650
// (memset) per chunk, and if present it will be at the beginning.
3631
3651
bool same =
3632
3652
HasByteIndex (a) == HasByteIndex (b) &&
3633
- a->is_repeated () == b->is_repeated () &&
3634
3653
IsLikelyPresent (a, options_) == IsLikelyPresent (b, options_) &&
3635
3654
ShouldSplit (a, options_) == ShouldSplit (b, options_) &&
3636
3655
(CanClearByZeroing (a) == CanClearByZeroing (b) ||
@@ -3727,10 +3746,7 @@ void MessageGenerator::GenerateClear(io::Printer* p) {
3727
3746
// clear strings and messages if they were set.
3728
3747
//
3729
3748
// TODO: Let the CppFieldGenerator decide this somehow.
3730
- bool have_enclosing_if =
3731
- HasBitIndex (field) != kNoHasbit &&
3732
- (field->cpp_type () == FieldDescriptor::CPPTYPE_MESSAGE ||
3733
- field->cpp_type () == FieldDescriptor::CPPTYPE_STRING);
3749
+ const bool have_enclosing_if = ShouldGenerateEnclosingIf (*field);
3734
3750
3735
3751
if (have_enclosing_if) {
3736
3752
PrintPresenceCheck (field, has_bit_indices_, p, &cached_has_word_index,
@@ -4348,10 +4364,7 @@ void MessageGenerator::GenerateClassSpecificMergeImpl(io::Printer* p) {
4348
4364
for (const auto * field : fields) {
4349
4365
const auto & generator = field_generators_.get (field);
4350
4366
4351
- if (field->is_repeated ()) {
4352
- generator.GenerateMergingCode (p);
4353
- } else if (!field->is_required () && !field->is_repeated () &&
4354
- !HasHasbit (field, options_)) {
4367
+ if (!field->is_required () && !HasHasbit (field, options_)) {
4355
4368
// Merge semantics without true field presence: primitive fields are
4356
4369
// merged only if non-zero (numeric) or non-empty (string).
4357
4370
MayEmitMutableIfNonDefaultCheck (
@@ -4363,8 +4376,12 @@ void MessageGenerator::GenerateClassSpecificMergeImpl(io::Printer* p) {
4363
4376
// Check hasbit, not using cached bits.
4364
4377
auto v = p->WithVars (HasBitVars (field));
4365
4378
p->Emit (
4366
- {{" merge_field" , [&] { generator.GenerateMergingCode (p); }}}, R"cc(
4367
- if (CheckHasBit(from.$has_bits$[$has_array_index$], $has_mask$)) {
4379
+ {{" check_has_bit" ,
4380
+ field->is_repeated () ? " CheckHasBitForRepeated" : " CheckHasBit" },
4381
+ {" merge_field" , [&] { generator.GenerateMergingCode (p); }}},
4382
+ R"cc(
4383
+ if ($check_has_bit$(from.$has_bits$[$has_array_index$],
4384
+ $has_mask$)) {
4368
4385
$merge_field$;
4369
4386
}
4370
4387
)cc" );
@@ -4374,8 +4391,9 @@ void MessageGenerator::GenerateClassSpecificMergeImpl(io::Printer* p) {
4374
4391
int has_bit_index = has_bit_indices_[field->index ()];
4375
4392
4376
4393
p->Emit (
4377
- {{" condition" , GenerateConditionMaybeWithProbabilityForField (
4378
- has_bit_index, field, options_)},
4394
+ {{" condition" ,
4395
+ GenerateConditionMaybeWithProbabilityForField (
4396
+ has_bit_index, field, options_, field->is_repeated ())},
4379
4397
{" merge_field" ,
4380
4398
[&] {
4381
4399
if (GetFieldHasbitMode (field, options_) ==
@@ -4719,10 +4737,12 @@ void MessageGenerator::GenerateSerializeOneField(io::Printer* p,
4719
4737
std::move (emit_body),
4720
4738
/* with_enclosing_braces_always=*/ false );
4721
4739
}},
4722
- {" cond" , GenerateConditionMaybeWithProbability (
4723
- 1u << (has_bit_index % 32 ),
4724
- GetPresenceProbability (field, options_),
4725
- use_cached_has_bits, has_word_index)},
4740
+ {" cond" ,
4741
+ GenerateConditionMaybeWithProbability (
4742
+ 1u << (has_bit_index % 32 ),
4743
+ GetPresenceProbability (field, options_), use_cached_has_bits,
4744
+ has_word_index, /* is_batch=*/ false ,
4745
+ /* is_repeated=*/ field->is_repeated ())},
4726
4746
},
4727
4747
R"cc(
4728
4748
if ($cond$) {
@@ -5245,7 +5265,6 @@ void MessageGenerator::GenerateByteSize(io::Printer* p) {
5245
5265
std::vector<FieldChunk> chunks =
5246
5266
CollectFields (rest, options_, [&](const auto * a, const auto * b) {
5247
5267
return a->is_required () == b->is_required () &&
5248
- a->is_repeated () == b->is_repeated () &&
5249
5268
HasByteIndex (a) == HasByteIndex (b) &&
5250
5269
IsLikelyPresent (a, options_) == IsLikelyPresent (b, options_) &&
5251
5270
ShouldSplit (a, options_) == ShouldSplit (b, options_);
@@ -5560,8 +5579,9 @@ void MessageGenerator::EmitCheckAndSerializeField(const FieldDescriptor* field,
5560
5579
}
5561
5580
5562
5581
int has_bit_index = has_bit_indices_[field->index ()];
5563
- p->Emit ({{" condition" , GenerateConditionMaybeWithProbabilityForField (
5564
- has_bit_index, field, options_)},
5582
+ p->Emit ({{" condition" ,
5583
+ GenerateConditionMaybeWithProbabilityForField (
5584
+ has_bit_index, field, options_, field->is_repeated ())},
5565
5585
{" check_nondefault_and_emit_body" ,
5566
5586
[&] {
5567
5587
// Note that it's possible that the field has explicit presence.
0 commit comments