Migrate repeated numeric fields to use bit field to track presence instead of using it to indicate the field mutability to potentially skip work on the field during build operations.

PiperOrigin-RevId: 531589847
pull/12784/head
Protobuf Team Bot 2 years ago committed by Copybara-Service
parent ad67472fea
commit f0de774705
  1. 9
      src/google/protobuf/compiler/java/message_builder.cc
  2. 114
      src/google/protobuf/compiler/java/primitive_field.cc

@ -84,10 +84,13 @@ bool BitfieldTracksMutability(const FieldDescriptor* const descriptor) {
// Once all repeated fields are held in ProtobufLists, this method shouldn't
// be needed.
switch (descriptor->type()) {
case FieldDescriptor::TYPE_STRING:
return false;
default:
case FieldDescriptor::TYPE_GROUP:
case FieldDescriptor::TYPE_MESSAGE:
case FieldDescriptor::TYPE_ENUM:
case FieldDescriptor::TYPE_BYTES:
return true;
default:
return false;
}
}
} // namespace

@ -170,8 +170,10 @@ void SetPrimitiveVariables(
break;
}
}
// For repeated builders, one bit is used for whether the array is immutable.
// For repeated bytes builders, one bit is used for whether the array is
// mutable.
// TODO(b/255468704): migrate bytes field to ProtobufList so that we can
// use the bit field to track their presence instead of mutability.
(*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
(*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
(*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
@ -692,8 +694,10 @@ void RepeatedImmutablePrimitiveFieldGenerator::GenerateInterfaceMembers(
void RepeatedImmutablePrimitiveFieldGenerator::GenerateMembers(
io::Printer* printer) const {
printer->Print(variables_, "@SuppressWarnings(\"serial\")\n"
"private $field_list_type$ $name$_;\n");
printer->Print(variables_,
"@SuppressWarnings(\"serial\")\n"
"private $field_list_type$ $name$_ =\n"
" $empty_list$;\n");
PrintExtraFieldInfo(variables_, printer);
WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
printer->Print(variables_,
@ -738,26 +742,45 @@ void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderMembers(
printer->Print(variables_,
"private $field_list_type$ $name$_ = $empty_list$;\n");
printer->Print(variables_,
"private void ensure$capitalized_name$IsMutable() {\n"
" if (!$get_mutable_bit_builder$) {\n"
" $name$_ = $mutable_copy_list$;\n"
" $set_mutable_bit_builder$;\n"
" }\n"
"}\n");
if (descriptor_->type() == FieldDescriptor::TYPE_BYTES) {
printer->Print(variables_,
"private void ensure$capitalized_name$IsMutable() {\n"
" if (!$get_mutable_bit_builder$) {\n"
" $name$_ = $mutable_copy_list$;\n"
" $set_mutable_bit_builder$;\n"
" }\n"
"}\n");
} else {
printer->Print(variables_,
"private void ensure$capitalized_name$IsMutable() {\n"
" if (!$name$_.isModifiable()) {\n"
" $name$_ = $mutable_copy_list$;\n"
" }\n"
" $set_has_field_bit_builder$\n"
"}\n");
}
// Note: We return an unmodifiable list because otherwise the caller
// could hold on to the returned list and modify it after the message
// has been built, thus mutating the message which is supposed to be
// immutable.
WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
printer->Print(
variables_,
"$deprecation$public java.util.List<$boxed_type$>\n"
" ${$get$capitalized_name$List$}$() {\n"
" return $get_mutable_bit_builder$ ?\n"
" java.util.Collections.unmodifiableList($name$_) : $name$_;\n"
"}\n");
if (descriptor_->type() == FieldDescriptor::TYPE_BYTES) {
printer->Print(variables_,
"$deprecation$public java.util.List<$boxed_type$>\n"
" ${$get$capitalized_name$List$}$() {\n"
" return $get_mutable_bit_builder$ ?\n"
" java.util.Collections.unmodifiableList($name$_) "
": $name$_;\n"
"}\n");
} else {
printer->Print(variables_,
"$deprecation$public java.util.List<$boxed_type$>\n"
" ${$get$capitalized_name$List$}$() {\n"
" $name$_.makeImmutable();\n"
" return $name$_;\n"
"}\n");
}
printer->Annotate("{", "}", descriptor_);
WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
printer->Print(
@ -780,11 +803,15 @@ void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderMembers(
" int index, $type$ value) {\n"
" $null_check$\n"
" ensure$capitalized_name$IsMutable();\n"
" $repeated_set$(index, value);\n"
" $repeated_set$(index, value);\n");
printer->Annotate("{", "}", descriptor_);
if (descriptor_->type() != FieldDescriptor::TYPE_BYTES) {
printer->Print(variables_, " $set_has_field_bit_builder$\n");
}
printer->Print(variables_,
" $on_changed$\n"
" return this;\n"
"}\n");
printer->Annotate("{", "}", descriptor_);
WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
/* builder */ true);
printer->Print(variables_,
@ -792,11 +819,15 @@ void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderMembers(
"${$add$capitalized_name$$}$($type$ value) {\n"
" $null_check$\n"
" ensure$capitalized_name$IsMutable();\n"
" $repeated_add$(value);\n"
" $repeated_add$(value);\n");
printer->Annotate("{", "}", descriptor_);
if (descriptor_->type() != FieldDescriptor::TYPE_BYTES) {
printer->Print(variables_, " $set_has_field_bit_builder$\n");
}
printer->Print(variables_,
" $on_changed$\n"
" return this;\n"
"}\n");
printer->Annotate("{", "}", descriptor_);
WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
/* builder */ true);
printer->Print(variables_,
@ -804,11 +835,15 @@ void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderMembers(
" java.lang.Iterable<? extends $boxed_type$> values) {\n"
" ensure$capitalized_name$IsMutable();\n"
" com.google.protobuf.AbstractMessageLite.Builder.addAll(\n"
" values, $name$_);\n"
" values, $name$_);\n");
printer->Annotate("{", "}", descriptor_);
if (descriptor_->type() != FieldDescriptor::TYPE_BYTES) {
printer->Print(variables_, " $set_has_field_bit_builder$\n");
}
printer->Print(variables_,
" $on_changed$\n"
" return this;\n"
"}\n");
printer->Annotate("{", "}", descriptor_);
WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
/* builder */ true);
printer->Print(
@ -941,8 +976,15 @@ void RepeatedImmutablePrimitiveFieldGenerator::GenerateMergingCode(
printer->Print(variables_,
"if (!other.$name$_.isEmpty()) {\n"
" if ($name$_.isEmpty()) {\n"
" $name$_ = other.$name$_;\n"
" $clear_mutable_bit_builder$;\n"
" $name$_ = other.$name$_;\n");
if (descriptor_->type() == FieldDescriptor::TYPE_BYTES) {
printer->Print(variables_, " $clear_mutable_bit_builder$;\n");
} else {
printer->Print(variables_,
" $name$_.makeImmutable();\n"
" $set_has_field_bit_builder$\n");
}
printer->Print(variables_,
" } else {\n"
" ensure$capitalized_name$IsMutable();\n"
" $name$_.addAll(other.$name$_);\n"
@ -955,12 +997,20 @@ void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuildingCode(
io::Printer* printer) const {
// The code below ensures that the result has an immutable list. If our
// list is immutable, we can just reuse it. If not, we make it immutable.
printer->Print(variables_,
"if ($get_mutable_bit_builder$) {\n"
" $name_make_immutable$;\n"
" $clear_mutable_bit_builder$;\n"
"}\n"
"result.$name$_ = $name$_;\n");
if (descriptor_->type() == FieldDescriptor::TYPE_BYTES) {
printer->Print(variables_,
"if ($get_mutable_bit_builder$) {\n"
" $name_make_immutable$;\n"
" $clear_mutable_bit_builder$;\n"
"}\n"
"result.$name$_ = $name$_;\n");
} else {
printer->Print(variables_,
"if ($get_has_field_bit_from_local$) {\n"
" $name_make_immutable$;\n"
" result.$name$_ = $name$_;\n"
"}\n");
}
}
void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderParsingCode(

Loading…
Cancel
Save