From d17cf6743414afca09d85ef6c55e1bf850ef8188 Mon Sep 17 00:00:00 2001 From: Protobuf Team Bot Date: Tue, 25 Aug 2026 07:47:58 -0700 Subject: [PATCH] Use monomorphic static dispatch for Java Protobuf submessage parsing PiperOrigin-RevId: 970550003 --- .../com/google/protobuf/CodedInputStream.java | 4 +- .../compiler/java/full/message_field.cc | 118 ++++++++++++++---- .../compiler/java/full/message_field.h | 3 + 3 files changed, 100 insertions(+), 25 deletions(-) diff --git a/java/core/src/main/java/com/google/protobuf/CodedInputStream.java b/java/core/src/main/java/com/google/protobuf/CodedInputStream.java index 033187ab46..0189b8e8e1 100644 --- a/java/core/src/main/java/com/google/protobuf/CodedInputStream.java +++ b/java/core/src/main/java/com/google/protobuf/CodedInputStream.java @@ -609,7 +609,7 @@ public abstract class CodedInputStream { @CanIgnoreReturnValue public abstract int pushLimit(int byteLimit) throws InvalidProtocolBufferException; - final int pushLimitBeforeMessage() throws IOException { + public final int pushLimitBeforeMessage() throws IOException { final int length = readRawVarint32(); checkRecursionLimit(); final int oldLimit = pushLimit(length); @@ -624,7 +624,7 @@ public abstract class CodedInputStream { */ public abstract void popLimit(final int oldLimit); - final void popLimitAfterMessage(int oldLimit) throws IOException { + public final void popLimitAfterMessage(int oldLimit) throws IOException { checkLastTagWas(0); --messageDepth; if (getBytesUntilLimit() != 0) { diff --git a/src/google/protobuf/compiler/java/full/message_field.cc b/src/google/protobuf/compiler/java/full/message_field.cc index 1ca87825f4..26cb67a950 100644 --- a/src/google/protobuf/compiler/java/full/message_field.cc +++ b/src/google/protobuf/compiler/java/full/message_field.cc @@ -11,6 +11,7 @@ #include "google/protobuf/compiler/java/full/message_field.h" +#include #include #include "absl/log/absl_check.h" @@ -85,6 +86,8 @@ void SetMessageVariables( (*variables)["get_has_field_bit_from_local"] = GenerateGetBitFromLocal(bit_index); + (*variables)["tag"] = absl::StrCat( + static_cast(internal::WireFormat::MakeTag(descriptor))); (*variables)["tag_size"] = absl::StrCat( internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor))); } @@ -181,6 +184,29 @@ void ImmutableMessageFieldGenerator::GenerateMembers( GenerateHasMethod(printer); GenerateGetMethod(printer); GenerateGetOrBuilderMethod(printer); + GenerateWriteFieldMethod(printer); +} + +void ImmutableMessageFieldGenerator::GenerateWriteFieldMethod( + io::Printer* printer) const { + if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) { + printer->Print(variables_, + "private void write$capitalized_name$Field(\n" + " com.google.protobuf.CodedOutputStream output)\n" + " throws java.io.IOException {\n" + " output.writeGroup($number$, get$capitalized_name$());\n" + "}\n"); + } else { + printer->Print(variables_, + "private void write$capitalized_name$Field(\n" + " com.google.protobuf.CodedOutputStream output)\n" + " throws java.io.IOException {\n" + " $type$ tmp = get$capitalized_name$();\n" + " output.writeUInt32NoTag($tag$);\n" + " output.writeUInt32NoTag(tmp.getSerializedSize());\n" + " tmp.writeTo(output);\n" + "}\n"); + } } void ImmutableMessageFieldGenerator::PrintNestedBuilderCondition( @@ -394,14 +420,15 @@ void ImmutableMessageFieldGenerator::GenerateBuilderParseMethod( } else { printer->Print( variables_, + "final int oldLimit = input.pushLimitBeforeMessage();\n" "if ($name$_ != null || $name$Builder_ != null) {\n" - " input.readMessage(\n" - " " - "internalGet$capitalized_name$FieldBuilder().getBuilder(),\n" - " extensionRegistry);\n" + " internalGet$capitalized_name$FieldBuilder().getBuilder()\n" + " .mergeFrom(input, extensionRegistry);\n" "} else {\n" - " $name$_ = input.readMessage($type$.parser(), extensionRegistry);\n" + " $name$_ = $type$.parser().parsePartialFrom(input, " + "extensionRegistry);\n" "}\n" + "input.popLimitAfterMessage(oldLimit);\n" "$set_has_field_bit$\n"); } printer->Outdent(); @@ -482,11 +509,10 @@ void ImmutableMessageFieldGenerator::GenerateBuilderParsingCode( void ImmutableMessageFieldGenerator::GenerateSerializationCode( io::Printer* printer) const { - printer->Print( - variables_, - "if ($is_field_present$) {\n" - " output.write$group_or_message$($number$, get$capitalized_name$());\n" - "}\n"); + printer->Print(variables_, + "if ($is_field_present$) {\n" + " write$capitalized_name$Field(output);\n" + "}\n"); } void ImmutableMessageFieldGenerator::GenerateSerializedSizeCode( @@ -578,6 +604,29 @@ void ImmutableMessageOneofFieldGenerator::GenerateMembers( GenerateHasMethod(printer); GenerateGetMethod(printer); GenerateGetOrBuilderMethod(printer); + GenerateWriteFieldMethod(printer); +} + +void ImmutableMessageOneofFieldGenerator::GenerateWriteFieldMethod( + io::Printer* printer) const { + if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) { + printer->Print(variables_, + "private void write$capitalized_name$Field(\n" + " com.google.protobuf.CodedOutputStream output)\n" + " throws java.io.IOException {\n" + " output.writeGroup($number$, ($type$) $oneof_name$_);\n" + "}\n"); + } else { + printer->Print(variables_, + "private void write$capitalized_name$Field(\n" + " com.google.protobuf.CodedOutputStream output)\n" + " throws java.io.IOException {\n" + " $type$ tmp = ($type$) $oneof_name$_;\n" + " output.writeUInt32NoTag($tag$);\n" + " output.writeUInt32NoTag(tmp.getSerializedSize());\n" + " tmp.writeTo(output);\n" + "}\n"); + } } void ImmutableMessageOneofFieldGenerator::GenerateBuilderHasMethod( @@ -826,11 +875,10 @@ void ImmutableMessageOneofFieldGenerator::GenerateBuilderParsingCode( void ImmutableMessageOneofFieldGenerator::GenerateSerializationCode( io::Printer* printer) const { - printer->Print( - variables_, - "if ($has_oneof_case_message$) {\n" - " output.write$group_or_message$($number$, ($type$) $oneof_name$_);\n" - "}\n"); + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n" + " write$capitalized_name$Field(output);\n" + "}\n"); } void ImmutableMessageOneofFieldGenerator::GenerateSerializedSizeCode( @@ -982,6 +1030,33 @@ void RepeatedImmutableMessageFieldGenerator::GenerateMembers( GenerateGetCountMethod(printer); GenerateGetMethod(printer); GenerateGetOrBuilderMethod(printer); + GenerateWriteFieldMethod(printer); +} + +void RepeatedImmutableMessageFieldGenerator::GenerateWriteFieldMethod( + io::Printer* printer) const { + if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) { + printer->Print(variables_, + "private void write$capitalized_name$Field(\n" + " com.google.protobuf.CodedOutputStream output)\n" + " throws java.io.IOException {\n" + " for (int i = 0; i < $name$_.size(); i++) {\n" + " output.writeGroup($number$, $name$_.get(i));\n" + " }\n" + "}\n"); + } else { + printer->Print(variables_, + "private void write$capitalized_name$Field(\n" + " com.google.protobuf.CodedOutputStream output)\n" + " throws java.io.IOException {\n" + " for (int i = 0; i < $name$_.size(); i++) {\n" + " $type$ tmp = $name$_.get(i);\n" + " output.writeUInt32NoTag($tag$);\n" + " output.writeUInt32NoTag(tmp.getSerializedSize());\n" + " tmp.writeTo(output);\n" + " }\n" + "}\n"); + } } void RepeatedImmutableMessageFieldGenerator::GenerateEnsureIsMutableMethod( @@ -1436,10 +1511,10 @@ void RepeatedImmutableMessageFieldGenerator::GenerateBuilderParsingCode( " extensionRegistry);\n"); } else { printer->Print(variables_, - "$type$ m =\n" - " input.readMessage(\n" - " $type$.$get_parser$,\n" - " extensionRegistry);\n"); + "final int oldLimit = input.pushLimitBeforeMessage();\n" + "$type$ m = $type$.parser().parsePartialFrom(input, " + "extensionRegistry);\n" + "input.popLimitAfterMessage(oldLimit);\n"); } PrintNestedBuilderCondition(printer, "ensure$capitalized_name$IsMutable();\n" @@ -1451,10 +1526,7 @@ void RepeatedImmutableMessageFieldGenerator::GenerateBuilderParsingCode( void RepeatedImmutableMessageFieldGenerator::GenerateSerializationCode( io::Printer* printer) const { - printer->Print(variables_, - "for (int i = 0; i < $name$_.size(); i++) {\n" - " output.write$group_or_message$($number$, $name$_.get(i));\n" - "}\n"); + printer->Print(variables_, "write$capitalized_name$Field(output);\n"); } void RepeatedImmutableMessageFieldGenerator::GenerateSerializedSizeCode( diff --git a/src/google/protobuf/compiler/java/full/message_field.h b/src/google/protobuf/compiler/java/full/message_field.h index dd002888c1..c14b32efac 100644 --- a/src/google/protobuf/compiler/java/full/message_field.h +++ b/src/google/protobuf/compiler/java/full/message_field.h @@ -83,6 +83,7 @@ class ImmutableMessageFieldGenerator : public ImmutableFieldGenerator { void GenerateHasMethod(io::Printer* printer) const; void GenerateGetMethod(io::Printer* printer) const; void GenerateGetOrBuilderMethod(io::Printer* printer) const; + void GenerateWriteFieldMethod(io::Printer* printer) const; void GenerateBuilderHasMethod(io::Printer* printer) const; void GenerateBuilderGetMethod(io::Printer* printer) const; @@ -120,6 +121,7 @@ class ImmutableMessageOneofFieldGenerator void GenerateHasMethod(io::Printer* printer) const; void GenerateGetMethod(io::Printer* printer) const; void GenerateGetOrBuilderMethod(io::Printer* printer) const; + void GenerateWriteFieldMethod(io::Printer* printer) const; void GenerateBuilderHasMethod(io::Printer* printer) const; void GenerateBuilderGetMethod(io::Printer* printer) const; @@ -173,6 +175,7 @@ class RepeatedImmutableMessageFieldGenerator void GenerateGetMethod(io::Printer* printer) const; void GenerateGetOrBuilderListMethod(io::Printer* printer) const; void GenerateGetOrBuilderMethod(io::Printer* printer) const; + void GenerateWriteFieldMethod(io::Printer* printer) const; void GenerateEnsureIsMutableMethod(io::Printer* printer) const; void GenerateBuilderGetListMethod(io::Printer* printer) const;