|
|
|
@ -51,6 +51,8 @@ |
|
|
|
|
#include "google/protobuf/map_entry_lite.h" |
|
|
|
|
#include "absl/container/flat_hash_map.h" |
|
|
|
|
#include "absl/container/flat_hash_set.h" |
|
|
|
|
#include "google/protobuf/stubs/logging.h" |
|
|
|
|
#include "google/protobuf/stubs/logging.h" |
|
|
|
|
#include "absl/strings/ascii.h" |
|
|
|
|
#include "absl/strings/escaping.h" |
|
|
|
|
#include "absl/strings/str_cat.h" |
|
|
|
@ -102,7 +104,7 @@ std::string ConditionalToCheckBitmasks( |
|
|
|
|
parts.push_back( |
|
|
|
|
absl::StrCat("((", has_bits_var, "[", i, "] & ", m, ") ^ ", m, ")")); |
|
|
|
|
} |
|
|
|
|
GOOGLE_CHECK(!parts.empty()); |
|
|
|
|
GOOGLE_ABSL_CHECK(!parts.empty()); |
|
|
|
|
// If we have multiple parts, each expected to be 0, then bitwise-or them.
|
|
|
|
|
std::string result = |
|
|
|
|
parts.size() == 1 |
|
|
|
@ -206,7 +208,7 @@ RunMap FindRuns(const std::vector<const FieldDescriptor*>& fields, |
|
|
|
|
// !HasHasbit(field).
|
|
|
|
|
bool EmitFieldNonDefaultCondition(io::Printer* p, const std::string& prefix, |
|
|
|
|
const FieldDescriptor* field) { |
|
|
|
|
GOOGLE_CHECK(!HasHasbit(field)); |
|
|
|
|
GOOGLE_ABSL_CHECK(!HasHasbit(field)); |
|
|
|
|
Formatter format(p); |
|
|
|
|
auto v = p->WithVars({{ |
|
|
|
|
{"prefix", prefix}, |
|
|
|
@ -271,7 +273,7 @@ bool HasInternalHasMethod(const FieldDescriptor* field) { |
|
|
|
|
void CollectMapInfo( |
|
|
|
|
const Options& options, const Descriptor* descriptor, |
|
|
|
|
absl::flat_hash_map<absl::string_view, std::string>* variables) { |
|
|
|
|
GOOGLE_CHECK(IsMapEntryMessage(descriptor)); |
|
|
|
|
GOOGLE_ABSL_CHECK(IsMapEntryMessage(descriptor)); |
|
|
|
|
absl::flat_hash_map<absl::string_view, std::string>& vars = *variables; |
|
|
|
|
const FieldDescriptor* key = descriptor->map_key(); |
|
|
|
|
const FieldDescriptor* val = descriptor->map_value(); |
|
|
|
@ -357,16 +359,16 @@ std::vector<std::vector<const FieldDescriptor*>> CollectFields( |
|
|
|
|
// masked to tell if any thing in "fields" is present.
|
|
|
|
|
uint32_t GenChunkMask(const std::vector<const FieldDescriptor*>& fields, |
|
|
|
|
const std::vector<int>& has_bit_indices) { |
|
|
|
|
GOOGLE_CHECK(!fields.empty()); |
|
|
|
|
GOOGLE_ABSL_CHECK(!fields.empty()); |
|
|
|
|
int first_index_offset = has_bit_indices[fields.front()->index()] / 32; |
|
|
|
|
uint32_t chunk_mask = 0; |
|
|
|
|
for (auto field : fields) { |
|
|
|
|
// "index" defines where in the _has_bits_ the field appears.
|
|
|
|
|
int index = has_bit_indices[field->index()]; |
|
|
|
|
GOOGLE_CHECK_EQ(first_index_offset, index / 32); |
|
|
|
|
GOOGLE_ABSL_CHECK_EQ(first_index_offset, index / 32); |
|
|
|
|
chunk_mask |= static_cast<uint32_t>(1) << (index % 32); |
|
|
|
|
} |
|
|
|
|
GOOGLE_CHECK_NE(0, chunk_mask); |
|
|
|
|
GOOGLE_ABSL_CHECK_NE(0, chunk_mask); |
|
|
|
|
return chunk_mask; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -463,7 +465,7 @@ void ColdChunkSkipper::OnStartChunk(int chunk, int cached_has_word_index, |
|
|
|
|
for (auto field : chunks_[chunk]) { |
|
|
|
|
int hasbit_index = has_bit_indices_[field->index()]; |
|
|
|
|
// Fields on a chunk must be in the same word.
|
|
|
|
|
GOOGLE_CHECK_EQ(this_word, hasbit_index / 32); |
|
|
|
|
GOOGLE_ABSL_CHECK_EQ(this_word, hasbit_index / 32); |
|
|
|
|
mask |= 1 << (hasbit_index % 32); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -1059,7 +1061,7 @@ void MessageGenerator::GenerateSingularFieldHasBits( |
|
|
|
|
} |
|
|
|
|
if (HasHasbit(field)) { |
|
|
|
|
int has_bit_index = HasBitIndex(field); |
|
|
|
|
GOOGLE_CHECK_NE(has_bit_index, kNoHasbit); |
|
|
|
|
GOOGLE_ABSL_CHECK_NE(has_bit_index, kNoHasbit); |
|
|
|
|
|
|
|
|
|
auto v = p->WithVars(HasbitVars(has_bit_index)); |
|
|
|
|
format( |
|
|
|
@ -1298,7 +1300,7 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* p) { |
|
|
|
|
" }\n", |
|
|
|
|
descriptor_->field(0)->full_name()); |
|
|
|
|
} else { |
|
|
|
|
GOOGLE_CHECK(utf8_check == Utf8CheckMode::kVerify); |
|
|
|
|
GOOGLE_ABSL_CHECK(utf8_check == Utf8CheckMode::kVerify); |
|
|
|
|
format( |
|
|
|
|
" static bool ValidateKey(std::string* s) {\n" |
|
|
|
|
"#ifndef NDEBUG\n" |
|
|
|
@ -1327,7 +1329,7 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* p) { |
|
|
|
|
" }\n", |
|
|
|
|
descriptor_->field(1)->full_name()); |
|
|
|
|
} else { |
|
|
|
|
GOOGLE_CHECK(utf8_check == Utf8CheckMode::kVerify); |
|
|
|
|
GOOGLE_ABSL_CHECK(utf8_check == Utf8CheckMode::kVerify); |
|
|
|
|
format( |
|
|
|
|
" static bool ValidateValue(std::string* s) {\n" |
|
|
|
|
"#ifndef NDEBUG\n" |
|
|
|
@ -1960,7 +1962,7 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* p) { |
|
|
|
|
|
|
|
|
|
format.Outdent(); |
|
|
|
|
format("};"); |
|
|
|
|
GOOGLE_DCHECK(!need_to_emit_cached_size); |
|
|
|
|
GOOGLE_ABSL_DCHECK(!need_to_emit_cached_size); |
|
|
|
|
} // NOLINT(readability/fn_size)
|
|
|
|
|
|
|
|
|
|
void MessageGenerator::GenerateInlineMethods(io::Printer* p) { |
|
|
|
@ -1997,8 +1999,8 @@ void MessageGenerator::GenerateSchema(io::Printer* p, int offset, |
|
|
|
|
if (inlined_string_indices_.empty()) { |
|
|
|
|
inlined_string_indices_offset = -1; |
|
|
|
|
} else { |
|
|
|
|
GOOGLE_DCHECK_NE(has_offset, -1); |
|
|
|
|
GOOGLE_DCHECK(!IsMapEntryMessage(descriptor_)); |
|
|
|
|
GOOGLE_ABSL_DCHECK_NE(has_offset, -1); |
|
|
|
|
GOOGLE_ABSL_DCHECK(!IsMapEntryMessage(descriptor_)); |
|
|
|
|
inlined_string_indices_offset = has_offset + has_bit_indices_.size(); |
|
|
|
|
} |
|
|
|
|
format("{ $1$, $2$, $3$, sizeof($classtype$)},\n", offset, has_offset, |
|
|
|
@ -2082,7 +2084,7 @@ void MessageGenerator::GenerateClassMethods(io::Printer* p) { |
|
|
|
|
} |
|
|
|
|
if (HasHasbit(field)) { |
|
|
|
|
int has_bit_index = HasBitIndex(field); |
|
|
|
|
GOOGLE_CHECK_NE(has_bit_index, kNoHasbit) << field->full_name(); |
|
|
|
|
GOOGLE_ABSL_CHECK_NE(has_bit_index, kNoHasbit) << field->full_name(); |
|
|
|
|
format( |
|
|
|
|
"static void set_has_$1$(HasBits* has_bits) {\n" |
|
|
|
|
" (*has_bits)[$2$] |= $3$u;\n" |
|
|
|
@ -2302,7 +2304,7 @@ std::pair<size_t, size_t> MessageGenerator::GenerateOffsets(io::Printer* p) { |
|
|
|
|
format("PROTOBUF_FIELD_OFFSET($classtype$, _impl_.$1$_),\n", oneof->name()); |
|
|
|
|
count++; |
|
|
|
|
} |
|
|
|
|
GOOGLE_CHECK_EQ(count, descriptor_->real_oneof_decl_count()); |
|
|
|
|
GOOGLE_ABSL_CHECK_EQ(count, descriptor_->real_oneof_decl_count()); |
|
|
|
|
|
|
|
|
|
if (IsMapEntryMessage(descriptor_)) { |
|
|
|
|
entries += 2; |
|
|
|
@ -2374,7 +2376,7 @@ void MessageGenerator::GenerateSharedConstructorCode(io::Printer* p) { |
|
|
|
|
|
|
|
|
|
// Initialize member variables with arena constructor.
|
|
|
|
|
for (auto field : optimized_order_) { |
|
|
|
|
GOOGLE_DCHECK(!IsFieldStripped(field, options_)); |
|
|
|
|
GOOGLE_ABSL_DCHECK(!IsFieldStripped(field, options_)); |
|
|
|
|
if (ShouldSplit(field, options_)) { |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
@ -2554,7 +2556,7 @@ ArenaDtorNeeds MessageGenerator::NeedsArenaDestructor() const { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void MessageGenerator::GenerateArenaDestructorCode(io::Printer* p) { |
|
|
|
|
GOOGLE_CHECK(NeedsArenaDestructor() > ArenaDtorNeeds::kNone); |
|
|
|
|
GOOGLE_ABSL_CHECK(NeedsArenaDestructor() > ArenaDtorNeeds::kNone); |
|
|
|
|
|
|
|
|
|
Formatter format(p); |
|
|
|
|
|
|
|
|
@ -3067,7 +3069,7 @@ void MessageGenerator::GenerateClear(io::Printer* p) { |
|
|
|
|
bool chunk_is_split = |
|
|
|
|
!chunk.empty() && ShouldSplit(chunk.front(), options_); |
|
|
|
|
// All chunks after the first split chunk should also be split.
|
|
|
|
|
GOOGLE_CHECK(!first_split_chunk_processed || chunk_is_split); |
|
|
|
|
GOOGLE_ABSL_CHECK(!first_split_chunk_processed || chunk_is_split); |
|
|
|
|
if (chunk_is_split && !first_split_chunk_processed) { |
|
|
|
|
// Some fields are cleared without checking has_bit. So we add the
|
|
|
|
|
// condition here to avoid writing to the default split instance.
|
|
|
|
@ -3078,7 +3080,7 @@ void MessageGenerator::GenerateClear(io::Printer* p) { |
|
|
|
|
|
|
|
|
|
for (const auto& field : chunk) { |
|
|
|
|
if (CanClearByZeroing(field)) { |
|
|
|
|
GOOGLE_CHECK(!saw_non_zero_init); |
|
|
|
|
GOOGLE_ABSL_CHECK(!saw_non_zero_init); |
|
|
|
|
if (!memset_start) memset_start = field; |
|
|
|
|
memset_end = field; |
|
|
|
|
} else { |
|
|
|
@ -3104,8 +3106,8 @@ void MessageGenerator::GenerateClear(io::Printer* p) { |
|
|
|
|
// Check (up to) 8 has_bits at a time if we have more than one field in
|
|
|
|
|
// this chunk. Due to field layout ordering, we may check
|
|
|
|
|
// _has_bits_[last_chunk * 8 / 32] multiple times.
|
|
|
|
|
GOOGLE_DCHECK_LE(2, popcnt(chunk_mask)); |
|
|
|
|
GOOGLE_DCHECK_GE(8, popcnt(chunk_mask)); |
|
|
|
|
GOOGLE_ABSL_DCHECK_LE(2, popcnt(chunk_mask)); |
|
|
|
|
GOOGLE_ABSL_DCHECK_GE(8, popcnt(chunk_mask)); |
|
|
|
|
|
|
|
|
|
if (cached_has_word_index != HasWordIndex(chunk.front())) { |
|
|
|
|
cached_has_word_index = HasWordIndex(chunk.front()); |
|
|
|
@ -3120,8 +3122,8 @@ void MessageGenerator::GenerateClear(io::Printer* p) { |
|
|
|
|
// For clarity, do not memset a single field.
|
|
|
|
|
field_generators_.get(memset_start).GenerateMessageClearingCode(p); |
|
|
|
|
} else { |
|
|
|
|
GOOGLE_CHECK_EQ(chunk_is_split, ShouldSplit(memset_start, options_)); |
|
|
|
|
GOOGLE_CHECK_EQ(chunk_is_split, ShouldSplit(memset_end, options_)); |
|
|
|
|
GOOGLE_ABSL_CHECK_EQ(chunk_is_split, ShouldSplit(memset_start, options_)); |
|
|
|
|
GOOGLE_ABSL_CHECK_EQ(chunk_is_split, ShouldSplit(memset_end, options_)); |
|
|
|
|
format( |
|
|
|
|
"::memset(&$1$, 0, static_cast<::size_t>(\n" |
|
|
|
|
" reinterpret_cast<char*>(&$2$) -\n" |
|
|
|
@ -3394,7 +3396,8 @@ void MessageGenerator::GenerateMergeFrom(io::Printer* p) { |
|
|
|
|
|
|
|
|
|
void MessageGenerator::GenerateClassSpecificMergeImpl(io::Printer* p) { |
|
|
|
|
if (HasSimpleBaseClass(descriptor_, options_)) return; |
|
|
|
|
// Generate the class-specific MergeFrom, which avoids the GOOGLE_CHECK and cast.
|
|
|
|
|
// Generate the class-specific MergeFrom, which avoids the GOOGLE_ABSL_CHECK and
|
|
|
|
|
// cast.
|
|
|
|
|
Formatter format(p); |
|
|
|
|
if (!HasDescriptorMethods(descriptor_->file(), options_)) { |
|
|
|
|
// For messages that don't inherit from Message, just implement MergeFrom
|
|
|
|
@ -3457,8 +3460,8 @@ void MessageGenerator::GenerateClassSpecificMergeImpl(io::Printer* p) { |
|
|
|
|
// Check (up to) 8 has_bits at a time if we have more than one field in
|
|
|
|
|
// this chunk. Due to field layout ordering, we may check
|
|
|
|
|
// _has_bits_[last_chunk * 8 / 32] multiple times.
|
|
|
|
|
GOOGLE_DCHECK_LE(2, popcnt(chunk_mask)); |
|
|
|
|
GOOGLE_DCHECK_GE(8, popcnt(chunk_mask)); |
|
|
|
|
GOOGLE_ABSL_DCHECK_LE(2, popcnt(chunk_mask)); |
|
|
|
|
GOOGLE_ABSL_DCHECK_GE(8, popcnt(chunk_mask)); |
|
|
|
|
|
|
|
|
|
if (cached_has_word_index != HasWordIndex(chunk.front())) { |
|
|
|
|
cached_has_word_index = HasWordIndex(chunk.front()); |
|
|
|
@ -3490,7 +3493,7 @@ void MessageGenerator::GenerateClassSpecificMergeImpl(io::Printer* p) { |
|
|
|
|
} else if (field->options().weak() || |
|
|
|
|
cached_has_word_index != HasWordIndex(field)) { |
|
|
|
|
// Check hasbit, not using cached bits.
|
|
|
|
|
GOOGLE_CHECK(HasHasbit(field)); |
|
|
|
|
GOOGLE_ABSL_CHECK(HasHasbit(field)); |
|
|
|
|
auto v = p->WithVars(HasbitVars(HasBitIndex(field))); |
|
|
|
|
format( |
|
|
|
|
"if ((from.$has_bits$[$has_array_index$] & $has_mask$) != 0) {\n"); |
|
|
|
@ -3500,7 +3503,7 @@ void MessageGenerator::GenerateClassSpecificMergeImpl(io::Printer* p) { |
|
|
|
|
format("}\n"); |
|
|
|
|
} else { |
|
|
|
|
// Check hasbit, using cached bits.
|
|
|
|
|
GOOGLE_CHECK(HasHasbit(field)); |
|
|
|
|
GOOGLE_ABSL_CHECK(HasHasbit(field)); |
|
|
|
|
int has_bit_index = has_bit_indices_[field->index()]; |
|
|
|
|
const std::string mask = absl::StrCat( |
|
|
|
|
absl::Hex(1u << (has_bit_index % 32), absl::kZeroPad8)); |
|
|
|
@ -3524,7 +3527,7 @@ void MessageGenerator::GenerateClassSpecificMergeImpl(io::Printer* p) { |
|
|
|
|
if (have_outer_if) { |
|
|
|
|
if (deferred_has_bit_changes) { |
|
|
|
|
// Flush the has bits for the primitives we deferred.
|
|
|
|
|
GOOGLE_CHECK_LE(0, cached_has_word_index); |
|
|
|
|
GOOGLE_ABSL_CHECK_LE(0, cached_has_word_index); |
|
|
|
|
format("_this->$has_bits$[$1$] |= cached_has_bits;\n", |
|
|
|
|
cached_has_word_index); |
|
|
|
|
} |
|
|
|
@ -3651,7 +3654,7 @@ void MessageGenerator::GenerateVerify(io::Printer* p) { |
|
|
|
|
void MessageGenerator::GenerateSerializeOneofFields( |
|
|
|
|
io::Printer* p, const std::vector<const FieldDescriptor*>& fields) { |
|
|
|
|
Formatter format(p); |
|
|
|
|
GOOGLE_CHECK(!fields.empty()); |
|
|
|
|
GOOGLE_ABSL_CHECK(!fields.empty()); |
|
|
|
|
if (fields.size() == 1) { |
|
|
|
|
GenerateSerializeOneField(p, fields[0], -1); |
|
|
|
|
return; |
|
|
|
@ -4014,7 +4017,7 @@ void MessageGenerator::GenerateSerializeWithCachedSizesBodyShuffled( |
|
|
|
|
|
|
|
|
|
int num_fields = ordered_fields.size() + sorted_extensions.size(); |
|
|
|
|
constexpr int kLargePrime = 1000003; |
|
|
|
|
GOOGLE_CHECK_LT(num_fields, kLargePrime) |
|
|
|
|
GOOGLE_ABSL_CHECK_LT(num_fields, kLargePrime) |
|
|
|
|
<< "Prime offset must be greater than the number of fields to ensure " |
|
|
|
|
"those are coprime."; |
|
|
|
|
|
|
|
|
@ -4233,8 +4236,8 @@ void MessageGenerator::GenerateByteSize(io::Printer* p) { |
|
|
|
|
// Check (up to) 8 has_bits at a time if we have more than one field in
|
|
|
|
|
// this chunk. Due to field layout ordering, we may check
|
|
|
|
|
// _has_bits_[last_chunk * 8 / 32] multiple times.
|
|
|
|
|
GOOGLE_DCHECK_LE(2, popcnt(chunk_mask)); |
|
|
|
|
GOOGLE_DCHECK_GE(8, popcnt(chunk_mask)); |
|
|
|
|
GOOGLE_ABSL_DCHECK_LE(2, popcnt(chunk_mask)); |
|
|
|
|
GOOGLE_ABSL_DCHECK_GE(8, popcnt(chunk_mask)); |
|
|
|
|
|
|
|
|
|
if (cached_has_word_index != HasWordIndex(chunk.front())) { |
|
|
|
|
cached_has_word_index = HasWordIndex(chunk.front()); |
|
|
|
|