aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJon Skeet <skeet@pobox.com>2015-06-17 14:59:10 +0100
committerJon Skeet <skeet@pobox.com>2015-06-17 14:59:10 +0100
commit828b7e61d0443832d99002fbda12a359e5f9f221 (patch)
tree1f271cdb345b968dba08947b9319ba7d738f3476 /src
parentfb1547b3884ace3be6acf9e947686d627ff90179 (diff)
downloadprotobuf-828b7e61d0443832d99002fbda12a359e5f9f221.tar.gz
protobuf-828b7e61d0443832d99002fbda12a359e5f9f221.tar.bz2
protobuf-828b7e61d0443832d99002fbda12a359e5f9f221.zip
Use the fact that we know the tag size and bytes at codegen time to optimize.
Diffstat (limited to 'src')
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_enum_field.cc10
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_field_base.cc15
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_message_field.cc6
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_primitive_field.cc23
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc22
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc8
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc21
-rw-r--r--src/google/protobuf/wire_format.h2
8 files changed, 77 insertions, 30 deletions
diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc
index 19fd50cf..af34f50c 100644
--- a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc
@@ -61,7 +61,8 @@ void EnumFieldGenerator::GenerateParsingCode(io::Printer* printer) {
void EnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
printer->Print(variables_,
"if ($has_property_check$) {\n"
- " output.WriteEnum($number$, (int) $property_name$);\n"
+ " output.WriteRawTag($tag_bytes$);\n"
+ " output.WriteEnum((int) $property_name$);\n"
"}\n");
}
@@ -69,7 +70,7 @@ void EnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
printer->Print(
variables_,
"if ($has_property_check$) {\n"
- " size += pb::CodedOutputStream.ComputeEnumSize($number$, (int) $property_name$);\n"
+ " size += $tag_size$ + pb::CodedOutputStream.ComputeEnumSize((int) $property_name$);\n"
"}\n");
}
@@ -93,7 +94,8 @@ void EnumOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
printer->Print(
variables_,
"if ($has_property_check$) {\n"
- " output.WriteEnum($number$, (int) $property_name$);\n"
+ " output.WriteRawTag($tag_bytes$);\n"
+ " output.WriteEnum((int) $property_name$);\n"
"}\n");
}
@@ -101,7 +103,7 @@ void EnumOneofFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
printer->Print(
variables_,
"if ($has_property_check$) {\n"
- " size += pb::CodedOutputStream.ComputeEnumSize($number$, (int) $property_name$);\n"
+ " size += $tag_size$ + pb::CodedOutputStream.ComputeEnumSize((int) $property_name$);\n"
"}\n");
}
diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.cc b/src/google/protobuf/compiler/csharp/csharp_field_base.cc
index ec0d51ca..54f281ee 100644
--- a/src/google/protobuf/compiler/csharp/csharp_field_base.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_field_base.cc
@@ -35,6 +35,7 @@
#include <google/protobuf/compiler/plugin.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/stubs/strutil.h>
@@ -55,8 +56,18 @@ void FieldGeneratorBase::SetCommonFieldVariables(
// Note: this will be valid even though the tag emitted for packed and unpacked versions of
// repeated fields varies by wire format. The wire format is encoded in the bottom 3 bits, which
// never effects the tag size.
- int tagSize = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type());
- (*variables)["tag_size"] = SimpleItoa(tagSize);
+ int tag_size = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type());
+ uint tag = internal::WireFormat::MakeTag(descriptor_);
+ uint8 tag_array[5];
+ io::CodedOutputStream::WriteTagToArray(tag, tag_array);
+ string tag_bytes = SimpleItoa(tag_array[0]);
+ for (int i = 1; i < tag_size; i++) {
+ tag_bytes += ", " + SimpleItoa(tag_array[i]);
+ }
+
+ (*variables)["tag_size"] = SimpleItoa(tag_size);
+ (*variables)["tag_bytes"] = tag_bytes;
+
(*variables)["property_name"] = property_name();
(*variables)["type_name"] = type_name();
(*variables)["name"] = name();
diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_message_field.cc
index 804a5ae2..bd67aa0f 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_message_field.cc
@@ -92,11 +92,11 @@ void MessageFieldGenerator::GenerateParsingCode(io::Printer* printer) {
}
void MessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
- // TODO(jonskeet): Why are we using array access instead of a literal here?
printer->Print(
variables_,
"if ($has_property_check$) {\n"
- " output.WriteMessage($number$, $property_name$);\n"
+ " output.WriteRawTag($tag_bytes$);\n"
+ " output.WriteMessage($property_name$);\n"
"}\n");
}
@@ -104,7 +104,7 @@ void MessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
printer->Print(
variables_,
"if ($has_property_check$) {\n"
- " size += pb::CodedOutputStream.ComputeMessageSize($number$, $property_name$);\n"
+ " size += $tag_size$ + pb::CodedOutputStream.ComputeMessageSize($property_name$);\n"
"}\n");
}
diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
index 0164cdca..5820eb37 100644
--- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
@@ -105,16 +105,29 @@ void PrimitiveFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
printer->Print(
variables_,
"if ($has_property_check$) {\n"
- " output.Write$capitalized_type_name$($number$, $property_name$);\n"
+ " output.WriteRawTag($tag_bytes$);\n"
+ " output.Write$capitalized_type_name$($property_name$);\n"
"}\n");
}
void PrimitiveFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
printer->Print(
variables_,
- "if ($has_property_check$) {\n"
- " size += pb::CodedOutputStream.Compute$capitalized_type_name$Size($number$, $property_name$);\n"
- "}\n");
+ "if ($has_property_check$) {\n");
+ printer->Indent();
+ int fixedSize = GetFixedSize(descriptor_->type());
+ if (fixedSize == -1) {
+ printer->Print(
+ variables_,
+ "size += $tag_size$ + pb::CodedOutputStream.Compute$capitalized_type_name$Size($property_name$);\n");
+ } else {
+ printer->Print(
+ "size += $tag_size$ + $fixed_size$;\n",
+ "fixed_size", SimpleItoa(fixedSize),
+ "tag_size", variables_["tag_size"]);
+ }
+ printer->Outdent();
+ printer->Print("}\n");
}
void PrimitiveFieldGenerator::WriteHash(io::Printer* printer) {
@@ -173,7 +186,7 @@ void PrimitiveOneofFieldGenerator::WriteToString(io::Printer* printer) {
void PrimitiveOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) {
printer->Print(
variables_,
- "$property_name$ = input.Read$capitalized_type_name$()\n;");
+ "$property_name$ = input.Read$capitalized_type_name$();\n");
}
} // namespace csharp
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
index 22dec710..c78aaef6 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
@@ -82,9 +82,20 @@ void RepeatedEnumFieldGenerator::GenerateParsingCode(io::Printer* printer) {
void RepeatedEnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
printer->Print(
variables_,
- "if ($name$_.Count > 0) {\n"
- " output.Write$packed$EnumArray($number$, $name$_);\n"
- "}\n");
+ "if ($name$_.Count > 0) {\n");
+ printer->Indent();
+ if (descriptor_->is_packed()) {
+ printer->Print(
+ variables_,
+ "output.WriteRawTag($tag_bytes$);\n"
+ "output.WritePackedEnumArray($name$_);\n");
+ } else {
+ printer->Print(
+ variables_,
+ "output.Write$capitalized_type_name$Array($number$, $name$_);\n");
+ }
+ printer->Outdent();
+ printer->Print("}\n");
}
void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
@@ -97,14 +108,13 @@ void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer
printer->Print(
variables_,
"foreach ($type_name$ element in $name$_) {\n"
- " dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element);\n"
+ " dataSize += pb::CodedOutputStream.ComputeEnumSize((int) element);\n"
"}\n"
"size += dataSize;\n");
int tagSize = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type());
if (descriptor_->is_packed()) {
printer->Print(
- "size += $tag_size$;\n"
- "size += pb::CodedOutputStream.ComputeRawVarint32Size((uint) dataSize);\n",
+ "size += $tag_size$ + pb::CodedOutputStream.ComputeRawVarint32Size((uint) dataSize);\n",
"tag_size", SimpleItoa(tagSize));
} else {
printer->Print(
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
index 4b570d3b..3553fe12 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
@@ -79,8 +79,8 @@ void RepeatedMessageFieldGenerator::GenerateParsingCode(io::Printer* printer) {
}
void RepeatedMessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
- // TODO(jonskeet): Originally, this checked for Count > 0 first.
- // The Write* call should make that cheap though - no need to generate it every time.
+ // TODO(jonskeet): Bake the foreach loop into the generated code? We lose the
+ // advantage of knowing the tag bytes this way :(
printer->Print(
variables_,
"if ($name$_.Count > 0) {\n"
@@ -89,13 +89,13 @@ void RepeatedMessageFieldGenerator::GenerateSerializationCode(io::Printer* print
}
void RepeatedMessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
- // TODO(jonskeet): Put this into CodedOutputStream.
printer->Print(
variables_,
"if ($name$_.Count > 0) {\n"
" foreach ($type_name$ element in $name$_) {\n"
- " size += pb::CodedOutputStream.ComputeMessageSize($number$, element);\n"
+ " size += pb::CodedOutputStream.ComputeMessageSize(element);\n"
" }\n"
+ " size += $tag_size$ * $name$_.Count;\n"
"}\n");
}
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
index a5457785..fe8a4364 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
@@ -82,9 +82,20 @@ void RepeatedPrimitiveFieldGenerator::GenerateSerializationCode(
io::Printer* printer) {
printer->Print(
variables_,
- "if ($name$_.Count > 0) {\n"
- " output.Write$packed$$capitalized_type_name$Array($number$, $name$_);\n"
- "}\n");
+ "if ($name$_.Count > 0) {\n");
+ printer->Indent();
+ if (descriptor_->is_packed()) {
+ printer->Print(
+ variables_,
+ "output.WriteRawTag($tag_bytes$);\n"
+ "output.WritePacked$capitalized_type_name$Array($name$_);\n");
+ } else {
+ printer->Print(
+ variables_,
+ "output.Write$capitalized_type_name$Array($number$, $name$_);\n");
+ }
+ printer->Outdent();
+ printer->Print("}\n");
}
void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode(
@@ -100,7 +111,7 @@ void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode(
printer->Print(
variables_,
"foreach ($type_name$ element in $name$_) {\n"
- " dataSize += pb::CodedOutputStream.Compute$capitalized_type_name$SizeNoTag(element);\n"
+ " dataSize += pb::CodedOutputStream.Compute$capitalized_type_name$Size(element);\n"
"}\n");
} else {
printer->Print(
@@ -111,7 +122,7 @@ void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode(
int tagSize = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type());
if (descriptor_->is_packed()) {
printer->Print(
- "size += $tag_size$ + pb::CodedOutputStream.ComputeInt32SizeNoTag(dataSize);\n",
+ "size += $tag_size$ + pb::CodedOutputStream.ComputeInt32Size(dataSize);\n",
"tag_size", SimpleItoa(tagSize));
} else {
printer->Print(
diff --git a/src/google/protobuf/wire_format.h b/src/google/protobuf/wire_format.h
index 8de491a6..84270fee 100644
--- a/src/google/protobuf/wire_format.h
+++ b/src/google/protobuf/wire_format.h
@@ -290,7 +290,7 @@ class LIBPROTOBUF_EXPORT UnknownFieldSetFieldSkipper : public FieldSkipper {
inline WireFormatLite::WireType WireFormat::WireTypeForField(
const FieldDescriptor* field) {
- if (field->options().packed()) {
+ if (field->is_packed()) {
return WireFormatLite::WIRETYPE_LENGTH_DELIMITED;
} else {
return WireTypeForFieldType(field->type());