|
|
|
@ -67,6 +67,7 @@ |
|
|
|
|
#include "google/protobuf/compiler/cpp/padding_optimizer.h" |
|
|
|
|
#include "google/protobuf/compiler/cpp/parse_function_generator.h" |
|
|
|
|
#include "google/protobuf/descriptor.pb.h" |
|
|
|
|
#include "google/protobuf/generated_message_tctable_gen.h" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Must be included last.
|
|
|
|
@ -473,8 +474,7 @@ void ColdChunkSkipper::OnStartChunk(int chunk, int cached_has_word_index, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Emit has_bit check for each has_bit_dword index.
|
|
|
|
|
format("if (PROTOBUF_PREDICT_FALSE("); |
|
|
|
|
int first_word = HasbitWord(chunk, 0); |
|
|
|
|
format("if (PROTOBUF_PREDICT_FALSE(false"); |
|
|
|
|
while (chunk < limit_chunk_) { |
|
|
|
|
uint32_t mask = 0; |
|
|
|
|
int this_word = HasbitWord(chunk, 0); |
|
|
|
@ -488,9 +488,7 @@ void ColdChunkSkipper::OnStartChunk(int chunk, int cached_has_word_index, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (this_word != first_word) { |
|
|
|
|
format(" ||\n "); |
|
|
|
|
} |
|
|
|
|
format(" ||\n "); |
|
|
|
|
format.Set("mask", absl::Hex(mask, absl::kZeroPad8)); |
|
|
|
|
if (this_word == cached_has_word_index) { |
|
|
|
|
format("(cached_has_bits & 0x$mask$u) != 0"); |
|
|
|
@ -669,13 +667,46 @@ MessageGenerator::MessageGenerator( |
|
|
|
|
message_layout_helper_->OptimizeLayout(&optimized_order_, options_, |
|
|
|
|
scc_analyzer_); |
|
|
|
|
|
|
|
|
|
// This message has hasbits iff one or more fields need one.
|
|
|
|
|
// Allocate has_bit_indices_ iff the message has a field that needs hasbits.
|
|
|
|
|
int has_bit_fields = 0; |
|
|
|
|
for (auto field : optimized_order_) { |
|
|
|
|
if (HasHasbit(field)) { |
|
|
|
|
++has_bit_fields; |
|
|
|
|
if (has_bit_indices_.empty()) { |
|
|
|
|
has_bit_indices_.resize(descriptor_->field_count(), kNoHasbit); |
|
|
|
|
} |
|
|
|
|
has_bit_indices_[field->index()] = max_has_bit_index_++; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// For messages with more than 32 has bits, do a first pass which only
|
|
|
|
|
// allocates has bits to fields that might be in the fast table.
|
|
|
|
|
bool allocated_fast[32] = {}; |
|
|
|
|
if (has_bit_fields > 32) { |
|
|
|
|
for (const auto* field : optimized_order_) { |
|
|
|
|
if (HasHasbit(field)) { |
|
|
|
|
if (!IsDescriptorEligibleForFastParsing(field)) continue; |
|
|
|
|
|
|
|
|
|
// A fast-table with > 16 entries ends up incorporating
|
|
|
|
|
// the high-bit for VarInt encoding into the index for the table,
|
|
|
|
|
// so we have to incorporate it here also, when computing the
|
|
|
|
|
// index likely to be used for that table.
|
|
|
|
|
int fast_index = field->number(); |
|
|
|
|
if (fast_index >= 16) fast_index = 16 + (fast_index % 16); |
|
|
|
|
GOOGLE_CHECK_GE(fast_index, 1); |
|
|
|
|
GOOGLE_CHECK_LT(fast_index, 32); |
|
|
|
|
|
|
|
|
|
if (allocated_fast[fast_index]) continue; |
|
|
|
|
allocated_fast[fast_index] = true; |
|
|
|
|
|
|
|
|
|
has_bit_indices_[field->index()] = max_has_bit_index_++; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// Then do a second pass which allocates all remaining has bits
|
|
|
|
|
for (const auto* field : optimized_order_) { |
|
|
|
|
if (HasHasbit(field)) { |
|
|
|
|
if (has_bit_indices_[field->index()] == kNoHasbit) { |
|
|
|
|
has_bit_indices_[field->index()] = max_has_bit_index_++; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (IsStringInlined(field, options_)) { |
|
|
|
|
if (inlined_string_indices_.empty()) { |
|
|
|
@ -687,6 +718,7 @@ MessageGenerator::MessageGenerator( |
|
|
|
|
inlined_string_indices_[field->index()] = max_inlined_string_index_++; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
GOOGLE_CHECK_EQ(max_has_bit_index_, has_bit_fields); |
|
|
|
|
|
|
|
|
|
if (!has_bit_indices_.empty()) { |
|
|
|
|
field_generators_.SetHasBitIndices(has_bit_indices_); |
|
|
|
|