Turn on TDP table generation for messages with weak=true fields.

We still use the reflection based parser for it, but we have an otherwise
normal table generated.

PiperOrigin-RevId: 603481451
pull/15681/head
Protobuf Team Bot 10 months ago committed by Copybara-Service
parent a48090e329
commit 0a8409b5f4
  1. 52
      src/google/protobuf/compiler/cpp/parse_function_generator.cc
  2. 3
      src/google/protobuf/compiler/cpp/parse_function_generator.h
  3. 7
      src/google/protobuf/generated_message_reflection.cc
  4. 18
      src/google/protobuf/generated_message_tctable_gen.cc

@ -51,8 +51,7 @@ bool UseDirectTcParserTable(const FieldDescriptor* field,
const Options& options) {
if (field->cpp_type() != field->CPPTYPE_MESSAGE) return false;
auto* m = field->message_type();
return !m->options().message_set_wire_format() && !HasTracker(m, options) &&
!HasWeakFields(m)
return !m->options().message_set_wire_format() && !HasTracker(m, options)
; // NOLINT(whitespace/semicolon)
}
@ -113,26 +112,18 @@ ParseFunctionGenerator::ParseFunctionGenerator(
ordered_fields_(GetOrderedFields(descriptor_, options_)),
num_hasbits_(max_has_bit_index),
index_in_file_messages_(index_in_file_messages) {
if (should_generate_tctable()) {
tc_table_info_.reset(new TailCallTableInfo(
descriptor_, ordered_fields_,
{/* is_lite */ GetOptimizeFor(descriptor->file(), options_) ==
FileOptions::LITE_RUNTIME,
/* uses_codegen */ true, options_.profile_driven_cluster_aux_subtable},
GeneratedOptionProvider(this), has_bit_indices,
inlined_string_indices));
}
tc_table_info_.reset(new TailCallTableInfo(
descriptor_, ordered_fields_,
{/* is_lite */ GetOptimizeFor(descriptor->file(), options_) ==
FileOptions::LITE_RUNTIME,
/* uses_codegen */ true, options_.profile_driven_cluster_aux_subtable},
GeneratedOptionProvider(this), has_bit_indices, inlined_string_indices));
SetCommonMessageDataVariables(descriptor_, &variables_);
SetUnknownFieldsVariable(descriptor_, options_, &variables_);
variables_["classname"] = ClassName(descriptor, false);
}
void ParseFunctionGenerator::GenerateMethodDecls(io::Printer* printer) {
if (HasWeakFields(descriptor_)) {
// We use the reflection based one.
ABSL_CHECK(HasDescriptorMethods(descriptor_->file(), options_));
return;
}
Formatter format(printer, variables_);
format(
"const char* _InternalParse(const char* ptr, "
@ -157,25 +148,10 @@ void ParseFunctionGenerator::GenerateMethodImpls(io::Printer* printer) {
"}\n");
return;
}
if (HasWeakFields(descriptor_)) {
// We use the reflection based one.
ABSL_CHECK(HasDescriptorMethods(descriptor_->file(), options_));
return;
}
ABSL_CHECK(should_generate_tctable());
GenerateTailcallParseFunction(format);
}
bool ParseFunctionGenerator::should_generate_tctable() const {
if (HasWeakFields(descriptor_)) {
return false;
}
return true;
}
void ParseFunctionGenerator::GenerateTailcallParseFunction(Formatter& format) {
ABSL_CHECK(should_generate_tctable());
// Generate an `_InternalParse` that starts the tail-calling loop.
format(
"const char* $classname$::_InternalParse(\n"
@ -220,9 +196,6 @@ static int FieldNameDataSize(const std::vector<uint8_t>& data) {
}
void ParseFunctionGenerator::GenerateDataDecls(io::Printer* p) {
if (!should_generate_tctable()) {
return;
}
auto v = p->WithVars(variables_);
auto field_num_to_entry_table = MakeNumToEntryTable(ordered_fields_);
p->Emit(
@ -266,9 +239,6 @@ void ParseFunctionGenerator::GenerateDataDecls(io::Printer* p) {
}
void ParseFunctionGenerator::GenerateDataDefinitions(io::Printer* printer) {
if (!should_generate_tctable()) {
return;
}
GenerateTailCallTable(printer);
}
@ -336,12 +306,16 @@ static NumToEntryTable MakeNumToEntryTable(
void ParseFunctionGenerator::GenerateTailCallTable(io::Printer* printer) {
Formatter format(printer, variables_);
ABSL_CHECK(should_generate_tctable());
// All entries without a fast-path parsing function need a fallback.
std::string fallback = "::_pbi::TcParser::GenericFallback";
if (GetOptimizeFor(descriptor_->file(), options_) ==
FileOptions::LITE_RUNTIME) {
absl::StrAppend(&fallback, "Lite");
} else if (HasWeakFields(descriptor_)) {
// weak=true fields are handled with the reflection fallback, but we don't
// want to install that for normal messages because it has more overhead.
ABSL_CHECK(HasDescriptorMethods(descriptor_->file(), options_));
fallback = "::_pbi::TcParser::ReflectionFallback";
}
// For simplicity and speed, the table is not covering all proto
@ -654,7 +628,7 @@ void ParseFunctionGenerator::GenerateFieldEntries(Formatter& format) {
PrintFieldComment(format, field, options_);
format("{");
if (IsWeak(field, options_)) {
// Weak fields are handled by the generated fallback function.
// Weak fields are handled by the reflection fallback function.
// (These are handled by legacy Google-internal logic.)
format("/* weak */ 0, 0, 0, 0");
} else {

@ -51,9 +51,6 @@ class ParseFunctionGenerator {
private:
class GeneratedOptionProvider;
// Returns true if tailcall table code should be generated.
bool should_generate_tctable() const;
// Generates a tail-calling `_InternalParse` function.
void GenerateTailcallParseFunction(Formatter& format);

@ -3277,7 +3277,6 @@ void Reflection::PopulateTcParseEntries(
TcParseTableBase::FieldEntry* entries) const {
for (const auto& entry : table_info.field_entries) {
const FieldDescriptor* field = entry.field;
ABSL_CHECK(!field->options().weak());
if (field->type() == field->TYPE_ENUM &&
table_info.aux_entries[entry.aux_idx].type ==
internal::TailCallTableInfo::kEnumValidator) {
@ -3359,12 +3358,6 @@ const internal::TcParseTableBase* Reflection::CreateTcParseTable() const {
return CreateTcParseTableReflectionOnly();
}
for (int i = 0; i < descriptor_->field_count(); ++i) {
if (descriptor_->field(i)->options().weak()) {
return CreateTcParseTableReflectionOnly();
}
}
std::vector<const FieldDescriptor*> fields;
constexpr int kNoHasbit = -1;
std::vector<int> has_bit_indices(

@ -225,10 +225,10 @@ bool IsFieldEligibleForFastParsing(
const TailCallTableInfo::OptionProvider& option_provider) {
const auto* field = entry.field;
const auto options = option_provider.GetForField(field);
ABSL_CHECK(!field->options().weak());
// Map, oneof, weak, and split fields are not handled on the fast path.
if (field->is_map() || field->real_containing_oneof() ||
options.is_implicitly_weak || options.should_split) {
field->options().weak() || options.is_implicitly_weak ||
options.should_split) {
return false;
}
@ -794,7 +794,7 @@ TailCallTableInfo::TailCallTableInfo(
field->type() == FieldDescriptor::TYPE_GROUP) {
// Message-typed fields have a FieldAux with the default instance pointer.
if (field->is_map()) {
field_entries.back().aux_idx = aux_entries.size();
entry.aux_idx = aux_entries.size();
aux_entries.push_back({kMapAuxInfo, {field}});
if (message_options.uses_codegen) {
// If we don't use codegen we can't add these.
@ -807,9 +807,12 @@ TailCallTableInfo::TailCallTableInfo(
aux_entries.push_back({kEnumValidator, {map_value}});
}
}
} else if (field->options().weak()) {
// Disable the type card for this entry to force the fallback.
entry.type_card = 0;
} else if (HasLazyRep(field, options)) {
if (message_options.uses_codegen) {
field_entries.back().aux_idx = aux_entries.size();
entry.aux_idx = aux_entries.size();
aux_entries.push_back({kSubMessage, {field}});
if (options.lazy_opt == field_layout::kTvEager) {
aux_entries.push_back({kMessageVerifyFunc, {field}});
@ -817,8 +820,7 @@ TailCallTableInfo::TailCallTableInfo(
aux_entries.push_back({kNothing});
}
} else {
field_entries.back().aux_idx =
TcParseTableBase::FieldEntry::kNoAuxIdx;
entry.aux_idx = TcParseTableBase::FieldEntry::kNoAuxIdx;
}
} else {
AuxType type = options.is_implicitly_weak ? kSubMessageWeak
@ -827,10 +829,10 @@ TailCallTableInfo::TailCallTableInfo(
if (message_options.should_profile_driven_cluster_aux_subtable &&
type == kSubTable && is_non_cold(options)) {
aux_entries[subtable_aux_idx] = {type, {field}};
field_entries.back().aux_idx = subtable_aux_idx;
entry.aux_idx = subtable_aux_idx;
++subtable_aux_idx;
} else {
field_entries.back().aux_idx = aux_entries.size();
entry.aux_idx = aux_entries.size();
aux_entries.push_back({type, {field}});
}
}

Loading…
Cancel
Save