Use the TcParseFunction enum instead of strings when generating the table

instructions.
This avoids the string creation in the reflection case altogether, as well
as the map lookups.

PiperOrigin-RevId: 563108247
pull/13873/head
Protobuf Team Bot 1 year ago committed by Copybara-Service
parent 7b77796f86
commit 5e9a9a87bc
  1. 18
      src/google/protobuf/compiler/cpp/parse_function_generator.cc
  2. 24
      src/google/protobuf/generated_message_reflection.cc
  3. 15
      src/google/protobuf/generated_message_tctable_gen.cc
  4. 5
      src/google/protobuf/generated_message_tctable_gen.h
  5. 3
      src/google/protobuf/generated_message_tctable_impl.h

@ -585,17 +585,29 @@ void ParseFunctionGenerator::GenerateTailCallTable(io::Printer* printer) {
format("};\n\n"); // _table_
}
static std::string TcParseFunctionName(internal::TcParseFunction func) {
#define PROTOBUF_TC_PARSE_FUNCTION_X(value) #value,
static constexpr absl::string_view kNames[] = {
{}, PROTOBUF_TC_PARSE_FUNCTION_LIST};
#undef PROTOBUF_TC_PARSE_FUNCTION_X
const int func_index = static_cast<int>(func);
ABSL_CHECK_GE(func_index, 0);
ABSL_CHECK_LT(func_index, std::end(kNames) - std::begin(kNames));
static constexpr absl::string_view ns = "::_pbi::TcParser::";
return absl::StrCat(ns, kNames[func_index]);
}
void ParseFunctionGenerator::GenerateFastFieldEntries(Formatter& format) {
for (const auto& info : tc_table_info_->fast_path_fields) {
if (auto* nonfield = info.AsNonField()) {
// Fast slot that is not associated with a field. Eg end group tags.
format("{$1$, {$2$, $3$}},\n", nonfield->func_name, nonfield->coded_tag,
nonfield->nonfield_info);
format("{$1$, {$2$, $3$}},\n", TcParseFunctionName(nonfield->func),
nonfield->coded_tag, nonfield->nonfield_info);
} else if (auto* as_field = info.AsField()) {
PrintFieldComment(format, as_field->field, options_);
ABSL_CHECK(!ShouldSplit(as_field->field, options_));
std::string func_name = as_field->func_name;
std::string func_name = TcParseFunctionName(as_field->func);
if (GetOptimizeFor(as_field->field->file(), options_) ==
FileOptions::SPEED) {
// For 1-byte tags we have a more optimized version of the varint parser

@ -54,6 +54,7 @@
#include "google/protobuf/descriptor.pb.h"
#include "google/protobuf/descriptor_legacy.h"
#include "google/protobuf/extension_set.h"
#include "google/protobuf/generated_message_tctable_decl.h"
#include "google/protobuf/generated_message_tctable_gen.h"
#include "google/protobuf/generated_message_tctable_impl.h"
#include "google/protobuf/generated_message_util.h"
@ -3218,21 +3219,20 @@ static uint32_t AlignTo(uint32_t v) {
}
static internal::TailCallParseFunc GetFastParseFunction(
absl::string_view func_name) {
#define PROTOBUF_TC_PARSE_FUNCTION_X(value) \
{"::_pbi::TcParser::" #value, internal::TcParser::value},
static const auto* const map =
new absl::flat_hash_map<absl::string_view, internal::TailCallParseFunc>{
PROTOBUF_TC_PARSE_FUNCTION_LIST};
internal::TcParseFunction func) {
#define PROTOBUF_TC_PARSE_FUNCTION_X(value) internal::TcParser::value,
static constexpr internal::TailCallParseFunc kFuncs[] = {
{}, PROTOBUF_TC_PARSE_FUNCTION_LIST};
#undef PROTOBUF_TC_PARSE_FUNCTION_X
auto it = map->find(func_name);
if (it == map->end()) {
ABSL_DLOG(FATAL) << "Failed to find function: " << func_name;
const int index = static_cast<int>(func);
if (index < 0 || index >= std::end(kFuncs) - std::begin(kFuncs) ||
kFuncs[index] == nullptr) {
ABSL_DLOG(FATAL) << "Failed to find function: " << static_cast<int>(func);
// Let's not crash in opt, just in case.
// MiniParse is always a valid parser.
return &internal::TcParser::MiniParse;
}
return it->second;
return kFuncs[index];
}
const internal::TcParseTableBase* Reflection::CreateTcParseTableReflectionOnly()
@ -3259,11 +3259,11 @@ void Reflection::PopulateTcParseFastEntries(
for (const auto& fast_field : table_info.fast_path_fields) {
if (auto* nonfield = fast_field.AsNonField()) {
// No field, but still a special entry.
*fast_entries++ = {GetFastParseFunction(nonfield->func_name),
*fast_entries++ = {GetFastParseFunction(nonfield->func),
{nonfield->coded_tag, nonfield->nonfield_info}};
} else if (auto* as_field = fast_field.AsField()) {
*fast_entries++ = {
GetFastParseFunction(as_field->func_name),
GetFastParseFunction(as_field->func),
{as_field->coded_tag, as_field->hasbit_idx, as_field->aux_idx,
static_cast<uint16_t>(schema_.GetFieldOffset(as_field->field))}};
} else {

@ -80,14 +80,6 @@ bool GetEnumValidationRange(const EnumDescriptor* enum_type, int16_t& start,
}
}
absl::string_view ParseFunctionValue(TcParseFunction function) {
#define PROTOBUF_TC_PARSE_FUNCTION_X(value) #value,
static constexpr absl::string_view functions[] = {
{}, PROTOBUF_TC_PARSE_FUNCTION_LIST};
#undef PROTOBUF_TC_PARSE_FUNCTION_X
return functions[static_cast<int>(function)];
};
enum class EnumRangeInfo {
kNone, // No contiguous range
kContiguous, // Has a contiguous range
@ -238,8 +230,7 @@ TailCallTableInfo::FastFieldInfo::Field MakeFastFieldEntry(
}
ABSL_CHECK(picked != TcParseFunction::kNone);
static constexpr absl::string_view ns = "::_pbi::TcParser::";
info.func_name = absl::StrCat(ns, ParseFunctionValue(picked));
info.func = picked;
return info;
#undef PROTOBUF_PICK_FUNCTION
@ -393,8 +384,8 @@ std::vector<TailCallTableInfo::FastFieldInfo> SplitFastFieldsForSize(
TailCallTableInfo::FastFieldInfo& info = result[fast_idx];
info.data = TailCallTableInfo::FastFieldInfo::NonField{
absl::StrCat("::_pbi::TcParser::FastEndG",
*end_group_tag < 128 ? "1" : "2"),
*end_group_tag < 128 ? TcParseFunction::kFastEndG1
: TcParseFunction::kFastEndG2,
static_cast<uint16_t>(tag),
static_cast<uint16_t>(*end_group_tag),
};

@ -50,6 +50,7 @@
namespace google {
namespace protobuf {
namespace internal {
enum class TcParseFunction : uint8_t;
namespace field_layout {
enum TransformValidation : uint16_t;
@ -90,14 +91,14 @@ struct PROTOBUF_EXPORT TailCallTableInfo {
struct FastFieldInfo {
struct Empty {};
struct Field {
std::string func_name;
TcParseFunction func;
uint16_t coded_tag;
const FieldDescriptor* field;
uint8_t hasbit_idx;
uint8_t aux_idx;
};
struct NonField {
std::string func_name;
TcParseFunction func;
uint16_t coded_tag;
uint16_t nonfield_info;
};

@ -37,6 +37,7 @@
#include <type_traits>
#include <utility>
#include "absl/log/absl_log.h"
#include "google/protobuf/extension_set.h"
#include "google/protobuf/generated_message_tctable_decl.h"
#include "google/protobuf/map.h"
@ -379,7 +380,7 @@ inline void AlignFail(std::integral_constant<size_t, 1>,
PROTOBUF_TC_PARSE_FUNCTION_LIST_END_GROUP()
#define PROTOBUF_TC_PARSE_FUNCTION_X(value) k##value,
enum class TcParseFunction { kNone, PROTOBUF_TC_PARSE_FUNCTION_LIST };
enum class TcParseFunction : uint8_t { kNone, PROTOBUF_TC_PARSE_FUNCTION_LIST };
#undef PROTOBUF_TC_PARSE_FUNCTION_X
// TcParser implements most of the parsing logic for tailcall tables.

Loading…
Cancel
Save