mirror of
https://github.com/protocolbuffers/protobuf
synced 2026-08-26 02:23:14 -04:00
Internal change.
PiperOrigin-RevId: 967874213
This commit is contained in:
parent
b6ca8b9fb1
commit
ad66689f2b
8 changed files with 110 additions and 52 deletions
|
|
@ -1,6 +1,7 @@
|
|||
#include "google/protobuf/compiler/java/full/field_generator.h"
|
||||
|
||||
#include "google/protobuf/compiler/java/context.h"
|
||||
#include "google/protobuf/compiler/java/helpers.h"
|
||||
#include "google/protobuf/compiler/java/name_resolver.h"
|
||||
|
||||
namespace google {
|
||||
|
|
@ -15,6 +16,18 @@ ImmutableFieldGenerator::ImmutableFieldGenerator(
|
|||
context_(context),
|
||||
name_resolver_(context->GetNameResolver()) {}
|
||||
|
||||
bool ImmutableFieldGenerator::HasHasbit() const {
|
||||
return ::google::protobuf::compiler::java::HasHasbit(descriptor_);
|
||||
}
|
||||
|
||||
bool ImmutableFieldGenerator::IsRealOneof() const {
|
||||
return ::google::protobuf::compiler::java::IsRealOneof(descriptor_);
|
||||
}
|
||||
|
||||
bool ImmutableFieldGenerator::BitfieldTracksMutability() const {
|
||||
return ::google::protobuf::compiler::java::BitfieldTracksMutability(descriptor_);
|
||||
}
|
||||
|
||||
} // namespace java
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
|
|
|||
|
|
@ -23,6 +23,10 @@ class ImmutableFieldGenerator : public FieldGenerator {
|
|||
ImmutableFieldGenerator& operator=(const ImmutableFieldGenerator&) = delete;
|
||||
~ImmutableFieldGenerator() override = default;
|
||||
|
||||
bool HasHasbit() const;
|
||||
bool IsRealOneof() const;
|
||||
bool BitfieldTracksMutability() const;
|
||||
|
||||
int GetBitIndex() const { return bit_index_; }
|
||||
constexpr int GetNumBits() const { return 1; }
|
||||
virtual void GenerateInterfaceMembers(io::Printer* printer) const = 0;
|
||||
|
|
|
|||
|
|
@ -86,7 +86,15 @@ std::unique_ptr<ImmutableFieldGenerator> MakeImmutableGenerator(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool HasExplicitPresence(const FieldDescriptor* field) {
|
||||
return HasHasbit(field);
|
||||
}
|
||||
bool HasNoPresence(const FieldDescriptor* field) {
|
||||
return IsRealOneof(field) || BitfieldTracksMutability(field);
|
||||
}
|
||||
bool HasHintBitFields(const FieldDescriptor* field) {
|
||||
return !HasExplicitPresence(field) && !HasNoPresence(field);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
FieldGeneratorMap<ImmutableFieldGenerator> MakeImmutableFieldGenerators(
|
||||
|
|
@ -95,11 +103,35 @@ FieldGeneratorMap<ImmutableFieldGenerator> MakeImmutableFieldGenerators(
|
|||
// bit fields.
|
||||
int bit_index = 0;
|
||||
FieldGeneratorMap<ImmutableFieldGenerator> ret(descriptor);
|
||||
|
||||
// First pass: fields with real presence bits.
|
||||
for (int i = 0; i < descriptor->field_count(); i++) {
|
||||
const FieldDescriptor* field = descriptor->field(i);
|
||||
auto generator = MakeImmutableGenerator(field, bit_index, context);
|
||||
bit_index += generator->GetNumBits();
|
||||
ret.Add(field, std::move(generator));
|
||||
if (HasExplicitPresence(field)) {
|
||||
auto generator = MakeImmutableGenerator(field, bit_index, context);
|
||||
bit_index += generator->GetNumBits();
|
||||
ret.Add(field, std::move(generator));
|
||||
}
|
||||
}
|
||||
|
||||
// Second pass: fields with hint presence bits.
|
||||
for (int i = 0; i < descriptor->field_count(); i++) {
|
||||
const FieldDescriptor* field = descriptor->field(i);
|
||||
if (HasHintBitFields(field)) {
|
||||
auto generator = MakeImmutableGenerator(field, bit_index, context);
|
||||
bit_index += generator->GetNumBits();
|
||||
ret.Add(field, std::move(generator));
|
||||
}
|
||||
}
|
||||
|
||||
// Third pass: fields with no presence tracking.
|
||||
for (int i = 0; i < descriptor->field_count(); i++) {
|
||||
const FieldDescriptor* field = descriptor->field(i);
|
||||
if (HasNoPresence(field)) {
|
||||
auto generator = MakeImmutableGenerator(field, bit_index, context);
|
||||
bit_index += generator->GetNumBits();
|
||||
ret.Add(field, std::move(generator));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,10 +18,7 @@
|
|||
#include <vector>
|
||||
|
||||
#include "absl/container/btree_map.h"
|
||||
#include "absl/container/btree_set.h"
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/log/absl_check.h"
|
||||
#include "absl/strings/ascii.h"
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "absl/strings/str_replace.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
|
|
@ -30,7 +27,7 @@
|
|||
#include "google/protobuf/compiler/java/context.h"
|
||||
#include "google/protobuf/compiler/java/doc_comment.h"
|
||||
#include "google/protobuf/compiler/java/field_common.h"
|
||||
#include "google/protobuf/compiler/java/generator_factory.h"
|
||||
#include "google/protobuf/compiler/java/generator_common.h"
|
||||
#include "google/protobuf/compiler/java/helpers.h"
|
||||
#include "google/protobuf/compiler/java/full/enum.h"
|
||||
#include "google/protobuf/compiler/java/full/extension.h"
|
||||
|
|
@ -584,9 +581,8 @@ void MessageBuilderGenerator::GenerateBuildPartial(io::Printer* printer) {
|
|||
"classname", name_resolver_->GetImmutableClassName(descriptor_));
|
||||
|
||||
// Build all fields in shards organized by bitfield membership.
|
||||
int start_field = 0;
|
||||
for (int i = 0; i < totalInts; i++) {
|
||||
start_field = GenerateBuildPartialShard(printer, i, start_field);
|
||||
GenerateBuildPartialShard(printer, i);
|
||||
}
|
||||
|
||||
// Build Oneofs
|
||||
|
|
@ -603,50 +599,35 @@ void MessageBuilderGenerator::GenerateBuildPartial(io::Printer* printer) {
|
|||
}
|
||||
}
|
||||
|
||||
int MessageBuilderGenerator::GenerateBuildPartialShard(io::Printer* printer,
|
||||
int shard,
|
||||
int first_field) {
|
||||
void MessageBuilderGenerator::GenerateBuildPartialShard(io::Printer* printer,
|
||||
int shard) {
|
||||
printer->Print(
|
||||
"private void buildPartial_autosplit_$shard$($classname$ result) {\n"
|
||||
" int from_$bit_field_name$ = $bit_field_name$;\n",
|
||||
" int from_$bit_field_name$ = $bit_field_name$;\n"
|
||||
" int to_$bit_field_name$ = 0;\n",
|
||||
"classname", name_resolver_->GetImmutableClassName(descriptor_), "shard",
|
||||
absl::StrCat(shard), "bit_field_name", GetBitFieldName(shard));
|
||||
printer->Indent();
|
||||
absl::btree_set<int> declared_to_bitfields;
|
||||
|
||||
int bit = 0;
|
||||
int next = first_field;
|
||||
for (; bit < 32 && next < descriptor_->field_count(); ++next, ++bit) {
|
||||
int i = shard * 32;
|
||||
int shard_end = std::min(i + 32, static_cast<int>(field_generators_.size()));
|
||||
for (; i < shard_end; ++i) {
|
||||
const ImmutableFieldGenerator& field =
|
||||
field_generators_.get(descriptor_->field(next));
|
||||
field_generators_.getInInsertOrder(i);
|
||||
|
||||
// Skip oneof fields that are handled separately
|
||||
if (IsRealOneof(descriptor_->field(next))) {
|
||||
// Currently oneofs are not built in shards.
|
||||
if (field.IsRealOneof()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Track message bits if necessary
|
||||
int to_bitfield = field.GetBitIndex() / 32;
|
||||
if (declared_to_bitfields.count(to_bitfield) == 0) {
|
||||
printer->Print("int to_$bit_field_name$ = 0;\n", "bit_field_name",
|
||||
GetBitFieldName(to_bitfield));
|
||||
declared_to_bitfields.insert(to_bitfield);
|
||||
}
|
||||
|
||||
// Copy the field from the builder to the message
|
||||
field.GenerateBuildingCode(printer);
|
||||
}
|
||||
printer->Outdent();
|
||||
|
||||
// Copy the bit field results to the generated message
|
||||
for (int to_bitfield : declared_to_bitfields) {
|
||||
printer->Print("result.$bit_field_name$ |= to_$bit_field_name$;\n",
|
||||
"bit_field_name", GetBitFieldName(to_bitfield));
|
||||
}
|
||||
|
||||
printer->Outdent();
|
||||
printer->Print("}\n\n");
|
||||
|
||||
return next;
|
||||
printer->Print(
|
||||
" result.$bit_field_name$ |= to_$bit_field_name$;\n"
|
||||
"}\n\n",
|
||||
"bit_field_name", GetBitFieldName(shard));
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
|
|
|||
|
|
@ -14,11 +14,11 @@
|
|||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/container/btree_map.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/types/span.h"
|
||||
#include "google/protobuf/compiler/java/generator_common.h"
|
||||
#include "google/protobuf/compiler/java/full/field_generator.h"
|
||||
#include "google/protobuf/compiler/java/full/oneof_generator.h"
|
||||
#include "google/protobuf/descriptor.h"
|
||||
|
|
@ -67,8 +67,7 @@ class MessageBuilderGenerator {
|
|||
io::Printer* printer, absl::Span<const std::string> merging_code_blocks,
|
||||
absl::string_view method_suffix);
|
||||
void GenerateBuildPartial(io::Printer* printer);
|
||||
int GenerateBuildPartialShard(io::Printer* printer, int shard,
|
||||
int first_field);
|
||||
void GenerateBuildPartialShard(io::Printer* printer, int shard);
|
||||
void GenerateDescriptorMethods(io::Printer* printer);
|
||||
void GenerateBuilderParsingMethods(io::Printer* printer);
|
||||
void GenerateBuilderFieldParsingCases(io::Printer* printer);
|
||||
|
|
|
|||
|
|
@ -30,11 +30,12 @@ class FieldGeneratorMap {
|
|||
public:
|
||||
explicit FieldGeneratorMap(const Descriptor* descriptor)
|
||||
: descriptor_(descriptor) {
|
||||
field_generators_.reserve(static_cast<size_t>(descriptor->field_count()));
|
||||
insert_order_.reserve(static_cast<size_t>(descriptor->field_count()));
|
||||
index_order_.resize(static_cast<size_t>(descriptor->field_count()));
|
||||
}
|
||||
|
||||
~FieldGeneratorMap() {
|
||||
for (const auto* g : field_generators_) {
|
||||
for (const auto* g : insert_order_) {
|
||||
delete g;
|
||||
}
|
||||
}
|
||||
|
|
@ -45,21 +46,28 @@ class FieldGeneratorMap {
|
|||
FieldGeneratorMap(const FieldGeneratorMap&) = delete;
|
||||
FieldGeneratorMap& operator=(const FieldGeneratorMap&) = delete;
|
||||
|
||||
size_t size() const { return insert_order_.size(); }
|
||||
|
||||
void Add(const FieldDescriptor* field,
|
||||
std::unique_ptr<FieldGeneratorType> field_generator) {
|
||||
ABSL_CHECK_EQ(field->containing_type(), descriptor_);
|
||||
field_generators_.push_back(field_generator.release());
|
||||
insert_order_.push_back(field_generator.release());
|
||||
index_order_[static_cast<size_t>(field->index())] = insert_order_.back();
|
||||
}
|
||||
|
||||
const FieldGeneratorType& get(const FieldDescriptor* field) const {
|
||||
ABSL_CHECK_EQ(field->containing_type(), descriptor_);
|
||||
return *field_generators_[static_cast<size_t>(field->index())];
|
||||
return *index_order_[static_cast<size_t>(field->index())];
|
||||
}
|
||||
|
||||
const FieldGeneratorType& getInInsertOrder(int index) const {
|
||||
return *insert_order_[static_cast<size_t>(index)];
|
||||
}
|
||||
|
||||
std::vector<const FieldGenerator*> field_generators() const {
|
||||
std::vector<const FieldGenerator*> field_generators;
|
||||
field_generators.reserve(field_generators_.size());
|
||||
for (const auto* g : field_generators_) {
|
||||
field_generators.reserve(index_order_.size());
|
||||
for (const auto* g : index_order_) {
|
||||
field_generators.push_back(g);
|
||||
}
|
||||
return field_generators;
|
||||
|
|
@ -67,7 +75,8 @@ class FieldGeneratorMap {
|
|||
|
||||
private:
|
||||
const Descriptor* descriptor_;
|
||||
std::vector<const FieldGeneratorType*> field_generators_;
|
||||
std::vector<const FieldGeneratorType*> insert_order_;
|
||||
std::vector<const FieldGeneratorType*> index_order_;
|
||||
};
|
||||
|
||||
inline void ReportUnexpectedPackedFieldsCall() {
|
||||
|
|
|
|||
|
|
@ -831,15 +831,33 @@ bool HasRequiredFields(const Descriptor* type,
|
|||
return false;
|
||||
}
|
||||
|
||||
bool HasRequiredFields(const Descriptor* type) {
|
||||
bool HasRequiredFields(const Descriptor* descriptor) {
|
||||
absl::flat_hash_set<const Descriptor*> already_seen;
|
||||
return HasRequiredFields(type, &already_seen);
|
||||
return HasRequiredFields(descriptor, &already_seen);
|
||||
}
|
||||
|
||||
bool IsRealOneof(const FieldDescriptor* descriptor) {
|
||||
return descriptor->real_containing_oneof();
|
||||
}
|
||||
|
||||
bool BitfieldTracksMutability(const FieldDescriptor* const descriptor) {
|
||||
if (!descriptor->is_repeated() || IsMapField(descriptor)) {
|
||||
return false;
|
||||
}
|
||||
// TODO: update this to migrate repeated fields to use
|
||||
// ProtobufList (which tracks immutability internally). That allows us to use
|
||||
// the presence bit to skip work on the repeated field if it is not populated.
|
||||
// Once all repeated fields are held in ProtobufLists, this method shouldn't
|
||||
// be needed.
|
||||
switch (descriptor->type()) {
|
||||
case FieldDescriptor::TYPE_GROUP:
|
||||
case FieldDescriptor::TYPE_MESSAGE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool HasRepeatedFields(const Descriptor* descriptor) {
|
||||
for (int i = 0; i < descriptor->field_count(); ++i) {
|
||||
const FieldDescriptor* field = descriptor->field(i);
|
||||
|
|
|
|||
|
|
@ -351,6 +351,8 @@ inline bool HasHasbit(const FieldDescriptor* descriptor) {
|
|||
return descriptor->has_presence() && !descriptor->real_containing_oneof();
|
||||
}
|
||||
|
||||
bool BitfieldTracksMutability(const FieldDescriptor* descriptor);
|
||||
|
||||
// Whether unknown enum values are kept (i.e., not stored in UnknownFieldSet
|
||||
// but in the message and can be queried using additional getters that return
|
||||
// ints.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue