Skip to content

Commit

Permalink
Precompute the most common field properties in FieldGeneratorBase
Browse files Browse the repository at this point in the history
This is a cleanup that is intended to reduce the noise in current and planned protocol compiler code, and improve readability of the code.

PiperOrigin-RevId: 550631662
  • Loading branch information
martijnvels authored and copybara-github committed Jul 24, 2023
1 parent 46ddd14 commit d4f2d48
Show file tree
Hide file tree
Showing 8 changed files with 226 additions and 145 deletions.
39 changes: 38 additions & 1 deletion src/google/protobuf/compiler/cpp/field.cc
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,43 @@ std::vector<Sub> FieldVars(const FieldDescriptor* field, const Options& opts) {
return vars;
}

FieldGeneratorBase::FieldGeneratorBase(const FieldDescriptor* descriptor,
const Options& options,
MessageSCCAnalyzer* scc)
: descriptor_(descriptor), options_(options) {
should_split_ = ShouldSplit(descriptor, options);
is_oneof_ = descriptor->real_containing_oneof() != nullptr;
switch (descriptor->cpp_type()) {
case FieldDescriptor::CPPTYPE_ENUM:
case FieldDescriptor::CPPTYPE_INT32:
case FieldDescriptor::CPPTYPE_INT64:
case FieldDescriptor::CPPTYPE_UINT32:
case FieldDescriptor::CPPTYPE_UINT64:
case FieldDescriptor::CPPTYPE_FLOAT:
case FieldDescriptor::CPPTYPE_DOUBLE:
case FieldDescriptor::CPPTYPE_BOOL:
is_trivial_ = !(descriptor->is_repeated() || descriptor->is_map());
has_trivial_value_ = is_trivial_;
break;
case FieldDescriptor::CPPTYPE_STRING:
is_string_ = true;
string_type_ = descriptor->options().ctype();
is_inlined_ = IsStringInlined(descriptor, options);
is_bytes_ = descriptor->type() == FieldDescriptor::TYPE_BYTES;
break;
case FieldDescriptor::CPPTYPE_MESSAGE:
is_message_ = true;
is_group_ = descriptor->type() == FieldDescriptor::TYPE_GROUP;
is_foreign_ = IsCrossFileMessage(descriptor);
is_lazy_ = IsLazy(descriptor, options, scc);
is_weak_ = IsImplicitWeakField(descriptor, options, scc);
if (!(descriptor->is_repeated() || descriptor->is_map())) {
has_trivial_value_ = !is_lazy_;
}
break;
}
}

void FieldGeneratorBase::GenerateAggregateInitializer(io::Printer* p) const {
if (ShouldSplit(descriptor_, options_)) {
p->Emit(R"cc(
Expand Down Expand Up @@ -144,7 +181,7 @@ void FieldGeneratorBase::GenerateCopyAggregateInitializer(
}

void FieldGeneratorBase::GenerateCopyConstructorCode(io::Printer* p) const {
if (ShouldSplit(descriptor_, options_)) {
if (should_split()) {
// There is no copy constructor for the `Split` struct, so we need to copy
// the value here.
Formatter format(p, variables_);
Expand Down
62 changes: 60 additions & 2 deletions src/google/protobuf/compiler/cpp/field.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,57 @@ namespace cpp {
// matter of clean composability.
class FieldGeneratorBase {
public:
FieldGeneratorBase(const FieldDescriptor* descriptor, const Options& options)
: descriptor_(descriptor), options_(options) {}
FieldGeneratorBase(const FieldDescriptor* descriptor, const Options& options,
MessageSCCAnalyzer* scc_analyzer);

FieldGeneratorBase(const FieldGeneratorBase&) = delete;
FieldGeneratorBase& operator=(const FieldGeneratorBase&) = delete;

virtual ~FieldGeneratorBase() = 0;

// Returns true if this field should be placed in the cold 'Split' section.
bool should_split() const { return should_split_; }

// Returns true if this field is trivial. (int, float, double, enum, bool)
bool is_trivial() const { return is_trivial_; }

// Returns true if the field value itself is trivial, i.e., the field is
// trivial, or a (raw) pointer value to a singular, non lazy message.
bool has_trivial_value() const { return has_trivial_value_; }

// Returns true if the field is a singular or repeated message.
// This includes group message types. To explicitly check if a message
// type is a group type, use the `is_group()` function,
bool is_message() const { return is_message_; }

// Returns true if the field is a group message field (TYPE_GROUP).
bool is_group() const { return is_group_; }

// Returns true if the field is a weak message
bool is_weak() const { return is_weak_; }

// Returns true if the field is a lazy message.
bool is_lazy() const { return is_lazy_; }

// Returns true if the field is a foreign message field.
bool is_foreign() const { return is_foreign_; }

// Returns true if the field is a string field.
bool is_string() const { return is_string_; }

// Returns true if the field API uses bytes (void) instead of chars.
bool is_bytes() const { return is_bytes_; }

// Returns the public API string type for string fields.
FieldOptions::CType string_type() const { return string_type_; }

// Returns true if this field is part of a oneof field.
bool is_oneof() const { return is_oneof_; }

// Returns true if the field should be inlined instead of dynamically
// allocated. Applies to string and message value.
bool is_inlined() const { return is_inlined_; }

virtual std::vector<io::Printer::Sub> MakeVars() const { return {}; }

virtual void GeneratePrivateMembers(io::Printer* p) const = 0;
Expand Down Expand Up @@ -131,6 +174,21 @@ class FieldGeneratorBase {
const FieldDescriptor* descriptor_;
const Options& options_;
absl::flat_hash_map<absl::string_view, std::string> variables_;

private:
bool should_split_ = false;
bool is_trivial_ = false;
bool has_trivial_value_ = false;
bool is_message_ = false;
bool is_group_ = false;
bool is_string_ = false;
bool is_bytes_ = false;
bool is_inlined_ = false;
bool is_foreign_ = false;
bool is_lazy_ = false;
bool is_weak_ = false;
bool is_oneof_ = false;
FieldOptions::CType string_type_ = FieldOptions::STRING;
};

inline FieldGeneratorBase::~FieldGeneratorBase() = default;
Expand Down
27 changes: 15 additions & 12 deletions src/google/protobuf/compiler/cpp/field_generators/cord_field.cc
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ void SetCordVariables(

class CordFieldGenerator : public FieldGeneratorBase {
public:
CordFieldGenerator(const FieldDescriptor* descriptor, const Options& options);
CordFieldGenerator(const FieldDescriptor* descriptor, const Options& options,
MessageSCCAnalyzer* scc);
~CordFieldGenerator() override = default;

void GeneratePrivateMembers(io::Printer* printer) const override;
Expand All @@ -103,7 +104,7 @@ class CordFieldGenerator : public FieldGeneratorBase {
class CordOneofFieldGenerator : public CordFieldGenerator {
public:
CordOneofFieldGenerator(const FieldDescriptor* descriptor,
const Options& options);
const Options& options, MessageSCCAnalyzer* scc);
~CordOneofFieldGenerator() override = default;

void GeneratePrivateMembers(io::Printer* printer) const override;
Expand All @@ -123,8 +124,9 @@ class CordOneofFieldGenerator : public CordFieldGenerator {


CordFieldGenerator::CordFieldGenerator(const FieldDescriptor* descriptor,
const Options& options)
: FieldGeneratorBase(descriptor, options) {
const Options& options,
MessageSCCAnalyzer* scc)
: FieldGeneratorBase(descriptor, options, scc) {
SetCordVariables(descriptor, &variables_, options);
}

Expand Down Expand Up @@ -215,7 +217,7 @@ void CordFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
}

void CordFieldGenerator::GenerateConstructorCode(io::Printer* printer) const {
ABSL_CHECK(!ShouldSplit(descriptor_, options_));
ABSL_CHECK(!should_split());
Formatter format(printer, variables_);
if (!descriptor_->default_value_string().empty()) {
format("$field$ = ::absl::string_view($default$, $default_length$);\n");
Expand All @@ -224,7 +226,7 @@ void CordFieldGenerator::GenerateConstructorCode(io::Printer* printer) const {

void CordFieldGenerator::GenerateDestructorCode(io::Printer* printer) const {
Formatter format(printer, variables_);
if (ShouldSplit(descriptor_, options_)) {
if (should_split()) {
// A cord field in the `Split` struct is automatically destroyed when the
// split pointer is deleted and should not be explicitly destroyed here.
return;
Expand Down Expand Up @@ -270,7 +272,7 @@ void CordFieldGenerator::GenerateConstexprAggregateInitializer(
)cc");
} else {
p->Emit(
{{"Split", ShouldSplit(descriptor_, options_) ? "Split::" : ""}},
{{"Split", should_split() ? "Split::" : ""}},
R"cc(
/*decltype($field$)*/ {::absl::strings_internal::MakeStringConstant(
$classname$::Impl_::$Split$_default_$name$_func_{})},
Expand All @@ -279,7 +281,7 @@ void CordFieldGenerator::GenerateConstexprAggregateInitializer(
}

void CordFieldGenerator::GenerateAggregateInitializer(io::Printer* p) const {
if (ShouldSplit(descriptor_, options_)) {
if (should_split()) {
p->Emit(R"cc(
decltype(Impl_::Split::$name$_){},
)cc");
Expand All @@ -293,8 +295,9 @@ void CordFieldGenerator::GenerateAggregateInitializer(io::Printer* p) const {
// ===================================================================

CordOneofFieldGenerator::CordOneofFieldGenerator(
const FieldDescriptor* descriptor, const Options& options)
: CordFieldGenerator(descriptor, options) {}
const FieldDescriptor* descriptor, const Options& options,
MessageSCCAnalyzer* scc)
: CordFieldGenerator(descriptor, options, scc) {}

void CordOneofFieldGenerator::GeneratePrivateMembers(
io::Printer* printer) const {
Expand Down Expand Up @@ -410,14 +413,14 @@ void CordOneofFieldGenerator::GenerateArenaDestructorCode(
std::unique_ptr<FieldGeneratorBase> MakeSingularCordGenerator(
const FieldDescriptor* desc, const Options& options,
MessageSCCAnalyzer* scc) {
return absl::make_unique<CordFieldGenerator>(desc, options);
return absl::make_unique<CordFieldGenerator>(desc, options, scc);
}


std::unique_ptr<FieldGeneratorBase> MakeOneofCordGenerator(
const FieldDescriptor* desc, const Options& options,
MessageSCCAnalyzer* scc) {
return absl::make_unique<CordOneofFieldGenerator>(desc, options);
return absl::make_unique<CordOneofFieldGenerator>(desc, options, scc);
}

} // namespace cpp
Expand Down
40 changes: 19 additions & 21 deletions src/google/protobuf/compiler/cpp/field_generators/enum_field.cc
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,9 @@ std::vector<Sub> Vars(const FieldDescriptor* field, const Options& opts) {

class SingularEnum : public FieldGeneratorBase {
public:
SingularEnum(const FieldDescriptor* field, const Options& opts)
: FieldGeneratorBase(field, opts),
field_(field),
opts_(&opts),
is_oneof_(field->real_containing_oneof() != nullptr) {}
SingularEnum(const FieldDescriptor* field, const Options& opts,
MessageSCCAnalyzer* scc)
: FieldGeneratorBase(field, opts, scc), field_(field), opts_(&opts) {}
~SingularEnum() override = default;

std::vector<Sub> MakeVars() const override { return Vars(field_, *opts_); }
Expand All @@ -103,15 +101,15 @@ class SingularEnum : public FieldGeneratorBase {
}

void GenerateSwappingCode(io::Printer* p) const override {
if (is_oneof_) return;
if (is_oneof()) return;

p->Emit(R"cc(
swap($field_$, other->$field_$);
)cc");
}

void GenerateConstructorCode(io::Printer* p) const override {
if (!is_oneof_) return;
if (!is_oneof()) return;
p->Emit(R"cc(
$ns$::_$Msg$_default_instance_.$field_$ = $kDefault$;
)cc");
Expand Down Expand Up @@ -145,7 +143,7 @@ class SingularEnum : public FieldGeneratorBase {
}

void GenerateAggregateInitializer(io::Printer* p) const override {
if (ShouldSplit(descriptor_, options_)) {
if (should_split()) {
p->Emit(R"cc(
decltype(Impl_::Split::$name$_){$kDefault$},
)cc");
Expand All @@ -168,7 +166,6 @@ class SingularEnum : public FieldGeneratorBase {
private:
const FieldDescriptor* field_;
const Options* opts_;
bool is_oneof_;
};

void SingularEnum::GenerateAccessorDeclarations(io::Printer* p) const {
Expand Down Expand Up @@ -202,7 +199,7 @@ void SingularEnum::GenerateInlineAccessorDefinitions(io::Printer* p) const {
}
)cc");

if (is_oneof_) {
if (is_oneof()) {
p->Emit(R"cc(
inline $Enum$ $Msg$::_internal_$name$() const {
if ($has_field$) {
Expand Down Expand Up @@ -237,19 +234,20 @@ void SingularEnum::GenerateInlineAccessorDefinitions(io::Printer* p) const {

class RepeatedEnum : public FieldGeneratorBase {
public:
RepeatedEnum(const FieldDescriptor* field, const Options& opts)
: FieldGeneratorBase(field, opts),
RepeatedEnum(const FieldDescriptor* field, const Options& opts,
MessageSCCAnalyzer* scc)
: FieldGeneratorBase(field, opts, scc),
field_(field),
opts_(&opts),
has_cached_size_(field_->is_packed() &&
HasGeneratedMethods(field_->file(), opts) &&
!ShouldSplit(descriptor_, options_)) {}
!should_split()) {}
~RepeatedEnum() override = default;

std::vector<Sub> MakeVars() const override { return Vars(field_, *opts_); }

void GeneratePrivateMembers(io::Printer* p) const override {
if (ShouldSplit(descriptor_, options_)) {
if (should_split()) {
p->Emit(R"cc(
$pbi$::RawPtr<$pb$::RepeatedField<int>> $name$_;
)cc");
Expand Down Expand Up @@ -280,7 +278,7 @@ class RepeatedEnum : public FieldGeneratorBase {
_this->_internal_mutable_$name$()->MergeFrom(from._internal_$name$());
)cc");
};
if (!ShouldSplit(descriptor_, options_)) {
if (!should_split()) {
body();
} else {
p->Emit({{"body", body}}, R"cc(
Expand All @@ -292,14 +290,14 @@ class RepeatedEnum : public FieldGeneratorBase {
}

void GenerateSwappingCode(io::Printer* p) const override {
ABSL_CHECK(!ShouldSplit(descriptor_, options_));
ABSL_CHECK(!should_split());
p->Emit(R"cc(
$field_$.InternalSwap(&other->$field_$);
)cc");
}

void GenerateDestructorCode(io::Printer* p) const override {
if (ShouldSplit(descriptor_, options_)) {
if (should_split()) {
p->Emit(R"cc(
$field_$.DeleteIfNotDefault();
)cc");
Expand Down Expand Up @@ -347,7 +345,7 @@ class RepeatedEnum : public FieldGeneratorBase {
}

void GenerateCopyConstructorCode(io::Printer* p) const override {
if (ShouldSplit(descriptor_, options_)) {
if (should_split()) {
p->Emit(R"cc(
if (!from._internal_$name$().empty()) {
_internal_mutable_$name$()->MergeFrom(from._internal_$name$());
Expand Down Expand Up @@ -425,7 +423,7 @@ void RepeatedEnum::GenerateInlineAccessorDefinitions(io::Printer* p) const {
return _internal_mutable_$name$();
}
)cc");
if (ShouldSplit(descriptor_, options_)) {
if (should_split()) {
p->Emit(R"cc(
inline const $pb$::RepeatedField<int>& $Msg$::_internal_$name$() const {
$TsanDetectConcurrentRead$;
Expand Down Expand Up @@ -544,13 +542,13 @@ void RepeatedEnum::GenerateByteSize(io::Printer* p) const {
std::unique_ptr<FieldGeneratorBase> MakeSinguarEnumGenerator(
const FieldDescriptor* desc, const Options& options,
MessageSCCAnalyzer* scc) {
return absl::make_unique<SingularEnum>(desc, options);
return absl::make_unique<SingularEnum>(desc, options, scc);
}

std::unique_ptr<FieldGeneratorBase> MakeRepeatedEnumGenerator(
const FieldDescriptor* desc, const Options& options,
MessageSCCAnalyzer* scc) {
return absl::make_unique<RepeatedEnum>(desc, options);
return absl::make_unique<RepeatedEnum>(desc, options, scc);
}

} // namespace cpp
Expand Down
Loading

0 comments on commit d4f2d48

Please sign in to comment.