From 885b612f74f133678bf82808c589331e4c59dad9 Mon Sep 17 00:00:00 2001 From: Jisi Liu Date: Sat, 28 Feb 2015 14:51:22 -0800 Subject: Down integrate from Google internal branch for C++ and Java. - Maps for C++ lite - C++ Arena optimizations. - Java Lite runtime code size optimization. Change-Id: I7537a4357c1cb385d23f9e8aa7ffdfeefe079f13 --- src/google/protobuf/compiler/java/java_field.h | 1 + src/google/protobuf/compiler/java/java_helpers.cc | 4 +- src/google/protobuf/compiler/java/java_helpers.h | 10 + .../compiler/java/java_lazy_message_field.cc | 10 +- .../protobuf/compiler/java/java_map_field.cc | 101 +++++--- src/google/protobuf/compiler/java/java_map_field.h | 1 + src/google/protobuf/compiler/java/java_message.cc | 284 +++++++++++++++------ src/google/protobuf/compiler/java/java_message.h | 2 +- .../protobuf/compiler/java/java_primitive_field.cc | 3 + .../compiler/java/java_shared_code_generator.cc | 2 +- .../protobuf/compiler/java/java_string_field.cc | 2 +- 11 files changed, 290 insertions(+), 130 deletions(-) (limited to 'src/google/protobuf/compiler/java') diff --git a/src/google/protobuf/compiler/java/java_field.h b/src/google/protobuf/compiler/java/java_field.h index e8d6f3a2..1cf360c1 100644 --- a/src/google/protobuf/compiler/java/java_field.h +++ b/src/google/protobuf/compiler/java/java_field.h @@ -83,6 +83,7 @@ class ImmutableFieldGenerator { virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0; virtual void GenerateFieldBuilderInitializationCode(io::Printer* printer) const = 0; + virtual void GenerateStaticInitializationCode(io::Printer* printer) const {} virtual void GenerateEqualsCode(io::Printer* printer) const = 0; virtual void GenerateHashCode(io::Printer* printer) const = 0; diff --git a/src/google/protobuf/compiler/java/java_helpers.cc b/src/google/protobuf/compiler/java/java_helpers.cc index 23685385..e24894b1 100644 --- a/src/google/protobuf/compiler/java/java_helpers.cc +++ b/src/google/protobuf/compiler/java/java_helpers.cc @@ -690,8 +690,8 @@ const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) { for (int i = 0; i < descriptor->field_count(); i++) { fields[i] = descriptor->field(i); } - sort(fields, fields + descriptor->field_count(), - FieldOrderingByNumber()); + std::sort(fields, fields + descriptor->field_count(), + FieldOrderingByNumber()); return fields; } diff --git a/src/google/protobuf/compiler/java/java_helpers.h b/src/google/protobuf/compiler/java/java_helpers.h index d957fdc4..62efbefa 100644 --- a/src/google/protobuf/compiler/java/java_helpers.h +++ b/src/google/protobuf/compiler/java/java_helpers.h @@ -297,6 +297,16 @@ struct ExtensionRangeOrdering { // and return it. The caller should delete the returned array. const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor); +// Does this message class have any packed fields? +inline bool HasPackedFields(const Descriptor* descriptor) { + for (int i = 0; i < descriptor->field_count(); i++) { + if (descriptor->field(i)->is_packed()) { + return true; + } + } + return false; +} + // Check a message type and its sub-message types recursively to see if any of // them has a required field. Return true if a required field is found. bool HasRequiredFields(const Descriptor* descriptor); diff --git a/src/google/protobuf/compiler/java/java_lazy_message_field.cc b/src/google/protobuf/compiler/java/java_lazy_message_field.cc index 21cab7db..6e29a40b 100644 --- a/src/google/protobuf/compiler/java/java_lazy_message_field.cc +++ b/src/google/protobuf/compiler/java/java_lazy_message_field.cc @@ -243,9 +243,8 @@ GenerateBuildingCode(io::Printer* printer) const { "}\n"); printer->Print(variables_, - "result.$name$_.setByteString(\n" - " $name$_.toByteString(),\n" - " $name$_.getExtensionRegistry());\n"); + "result.$name$_.set(\n" + " $name$_);\n"); } void ImmutableLazyMessageFieldGenerator:: @@ -425,9 +424,8 @@ GenerateBuildingCode(io::Printer* printer) const { printer->Print(variables_, "result.$oneof_name$_ = new $lazy_type$();\n" - "(($lazy_type$) result.$oneof_name$_).setByteString(\n" - " (($lazy_type$) $oneof_name$_).toByteString(),\n" - " (($lazy_type$) $oneof_name$_).getExtensionRegistry());\n"); + "(($lazy_type$) result.$oneof_name$_).set(\n" + " (($lazy_type$) $oneof_name$_));\n"); printer->Outdent(); printer->Print("}\n"); } diff --git a/src/google/protobuf/compiler/java/java_map_field.cc b/src/google/protobuf/compiler/java/java_map_field.cc index 2986f51f..cf1ef589 100644 --- a/src/google/protobuf/compiler/java/java_map_field.cc +++ b/src/google/protobuf/compiler/java/java_map_field.cc @@ -197,26 +197,39 @@ GenerateInterfaceMembers(io::Printer* printer) const { } } +void ImmutableMapFieldGenerator:: +GenerateStaticInitializationCode(io::Printer* printer) const { + printer->Print( + variables_, + "$name$DefaultEntry =\n" + " com.google.protobuf.MapEntry$lite$\n" + " .<$type_parameters$>newDefaultInstance(\n" + " $descriptor$\n" + " $key_wire_type$,\n" + " $key_default_value$,\n" + " $value_wire_type$,\n" + " $value_default_value$);\n" + "\n"); +} + void ImmutableMapFieldGenerator:: GenerateMembers(io::Printer* printer) const { printer->Print( variables_, "private static final com.google.protobuf.MapEntry$lite$<\n" - " $type_parameters$> $name$DefaultEntry =\n" - " com.google.protobuf.MapEntry$lite$\n" - " .<$type_parameters$>newDefaultInstance(\n" - " $descriptor$\n" - " $key_wire_type$,\n" - " $key_default_value$,\n" - " $value_wire_type$,\n" - " $value_default_value$);\n"); + " $type_parameters$> $name$DefaultEntry;\n"); printer->Print( variables_, "private com.google.protobuf.MapField$lite$<\n" - " $type_parameters$> $name$_ =\n" - " com.google.protobuf.MapField$lite$.emptyMapField(\n" - " $map_field_parameter$);\n" - "\n"); + " $type_parameters$> $name$_;\n" + "private com.google.protobuf.MapField$lite$<$type_parameters$>\n" + "internalGet$capitalized_name$() {\n" + " if ($name$_ == null) {\n" + " return com.google.protobuf.MapField$lite$.emptyMapField(\n" + " $map_field_parameter$);\n" + " }\n" + " return $name$_;\n" + "}\n"); if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) { printer->Print( variables_, @@ -233,7 +246,7 @@ GenerateMembers(io::Printer* printer) const { "$deprecation$\n" "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n" "get$capitalized_name$Value() {\n" - " return $name$_.getMap();\n" + " return internalGet$capitalized_name$().getMap();\n" "}\n"); } WriteFieldDocComment(printer, descriptor_); @@ -244,7 +257,8 @@ GenerateMembers(io::Printer* printer) const { "get$capitalized_name$() {\n" " return new com.google.protobuf.Internal.MapAdapter<\n" " $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n" - " $name$_.getMap(), $name$ValueConverter);\n" + " internalGet$capitalized_name$().getMap(),\n" + " $name$ValueConverter);\n" "}\n"); } else { WriteFieldDocComment(printer, descriptor_); @@ -252,7 +266,7 @@ GenerateMembers(io::Printer* printer) const { variables_, "$deprecation$\n" "public java.util.Map<$type_parameters$> get$capitalized_name$() {\n" - " return $name$_.getMap();\n" + " return internalGet$capitalized_name$().getMap();\n" "}\n"); } } @@ -262,10 +276,24 @@ GenerateBuilderMembers(io::Printer* printer) const { printer->Print( variables_, "private com.google.protobuf.MapField$lite$<\n" - " $type_parameters$> $name$_ =\n" - " com.google.protobuf.MapField$lite$.newMapField(\n" - " $map_field_parameter$);\n" - "\n"); + " $type_parameters$> $name$_;\n" + "private com.google.protobuf.MapField$lite$<$type_parameters$>\n" + "internalGet$capitalized_name$() {\n" + " if ($name$_ == null) {\n" + " return com.google.protobuf.MapField$lite$.emptyMapField(\n" + " $map_field_parameter$);\n" + " }\n" + " return $name$_;\n" + "}\n" + "private com.google.protobuf.MapField$lite$<$type_parameters$>\n" + "internalGetMutable$capitalized_name$() {\n" + " $on_changed$;\n" + " if ($name$_ == null) {\n" + " $name$_ = com.google.protobuf.MapField$lite$.newMapField(\n" + " $map_field_parameter$);\n" + " }\n" + " return $name$_;\n" + "}\n"); if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) { WriteFieldDocComment(printer, descriptor_); printer->Print( @@ -275,7 +303,8 @@ GenerateBuilderMembers(io::Printer* printer) const { "get$capitalized_name$() {\n" " return new com.google.protobuf.Internal.MapAdapter<\n" " $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n" - " $name$_.getMap(), $name$ValueConverter);\n" + " internalGet$capitalized_name$().getMap(),\n" + " $name$ValueConverter);\n" "}\n"); WriteFieldDocComment(printer, descriptor_); printer->Print( @@ -283,10 +312,10 @@ GenerateBuilderMembers(io::Printer* printer) const { "$deprecation$\n" "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n" "getMutable$capitalized_name$() {\n" - " $on_changed$\n" " return new com.google.protobuf.Internal.MapAdapter<\n" " $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n" - " $name$_.getMutableMap(), $name$ValueConverter);\n" + " internalGetMutable$capitalized_name$().getMutableMap(),\n" + " $name$ValueConverter);\n" "}\n"); if (SupportUnknownEnumValue(descriptor_->file())) { WriteFieldDocComment(printer, descriptor_); @@ -295,7 +324,7 @@ GenerateBuilderMembers(io::Printer* printer) const { "$deprecation$\n" "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n" "get$capitalized_name$Value() {\n" - " return $name$_.getMap();\n" + " return internalGet$capitalized_name$().getMap();\n" "}\n"); WriteFieldDocComment(printer, descriptor_); printer->Print( @@ -303,8 +332,7 @@ GenerateBuilderMembers(io::Printer* printer) const { "$deprecation$\n" "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n" "getMutable$capitalized_name$Value() {\n" - " $on_changed$\n" - " return $name$_.getMutableMap();\n" + " return internalGetMutable$capitalized_name$().getMutableMap();\n" "}\n"); } } else { @@ -312,15 +340,14 @@ GenerateBuilderMembers(io::Printer* printer) const { printer->Print( variables_, "public java.util.Map<$type_parameters$> get$capitalized_name$() {\n" - " return $name$_.getMap();\n" + " return internalGet$capitalized_name$().getMap();\n" "}\n"); WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, "public java.util.Map<$type_parameters$>\n" "getMutable$capitalized_name$() {\n" - " $on_changed$\n" - " return $name$_.getMutableMap();\n" + " return internalGetMutable$capitalized_name$().getMutableMap();\n" "}\n"); } } @@ -339,14 +366,15 @@ void ImmutableMapFieldGenerator:: GenerateBuilderClearCode(io::Printer* printer) const { printer->Print( variables_, - "$name$_.clear();\n"); + "internalGetMutable$capitalized_name$().clear();\n"); } void ImmutableMapFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { printer->Print( variables_, - "$name$_.mergeFrom(other.$name$_);\n"); + "internalGetMutable$capitalized_name$().mergeFrom(\n" + " other.internalGet$capitalized_name$());\n"); } void ImmutableMapFieldGenerator:: @@ -356,7 +384,7 @@ GenerateBuildingCode(io::Printer* printer) const { // We do a copy of the map field to ensure that the built result is // immutable. Implementation of this copy() method can do copy-on-write // to defer this copy until further modifications are made on the field. - "result.$name$_ = $name$_.copy();\n"); + "result.$name$_ = internalGet$capitalized_name$().copy();\n"); } void ImmutableMapFieldGenerator:: @@ -402,7 +430,7 @@ GenerateSerializationCode(io::Printer* printer) const { printer->Print( variables_, "for (java.util.Map.Entry<$type_parameters$> entry\n" - " : $name$_.getMap().entrySet()) {\n" + " : internalGet$capitalized_name$().getMap().entrySet()) {\n" " com.google.protobuf.MapEntry$lite$<$type_parameters$>\n" " $name$ = $name$DefaultEntry.newBuilderForType()\n" " .setKey(entry.getKey())\n" @@ -417,7 +445,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print( variables_, "for (java.util.Map.Entry<$type_parameters$> entry\n" - " : $name$_.getMap().entrySet()) {\n" + " : internalGet$capitalized_name$().getMap().entrySet()) {\n" " com.google.protobuf.MapEntry$lite$<$type_parameters$>\n" " $name$ = $name$DefaultEntry.newBuilderForType()\n" " .setKey(entry.getKey())\n" @@ -432,16 +460,17 @@ void ImmutableMapFieldGenerator:: GenerateEqualsCode(io::Printer* printer) const { printer->Print( variables_, - "result = result && $name$_.equals(other.$name$_);\n"); + "result = result && internalGet$capitalized_name$().equals(\n" + " other.internalGet$capitalized_name$());\n"); } void ImmutableMapFieldGenerator:: GenerateHashCode(io::Printer* printer) const { printer->Print( variables_, - "if (!$name$_.getMap().isEmpty()) {\n" + "if (!internalGet$capitalized_name$().getMap().isEmpty()) {\n" " hash = (37 * hash) + $constant_name$;\n" - " hash = (53 * hash) + $name$_.hashCode();\n" + " hash = (53 * hash) + internalGet$capitalized_name$().hashCode();\n" "}\n"); } diff --git a/src/google/protobuf/compiler/java/java_map_field.h b/src/google/protobuf/compiler/java/java_map_field.h index 80a94f45..3e6dd973 100644 --- a/src/google/protobuf/compiler/java/java_map_field.h +++ b/src/google/protobuf/compiler/java/java_map_field.h @@ -60,6 +60,7 @@ class ImmutableMapFieldGenerator : public ImmutableFieldGenerator { void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializedSizeCode(io::Printer* printer) const; void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; + void GenerateStaticInitializationCode(io::Printer* printer) const; void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCode(io::Printer* printer) const; diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc index 1171b718..e982a17b 100644 --- a/src/google/protobuf/compiler/java/java_message.cc +++ b/src/google/protobuf/compiler/java/java_message.cc @@ -234,7 +234,8 @@ void ImmutableMessageGenerator::GenerateInterface(io::Printer* printer) { "public interface $classname$OrBuilder extends \n" " $extra_interfaces$\n" " com.google.protobuf.GeneratedMessageLite.\n" - " ExtendableMessageOrBuilder<$classname$> {\n", + " ExtendableMessageOrBuilder<\n" + " $classname$, $classname$.Builder> {\n", "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), "classname", descriptor_->name()); } @@ -285,22 +286,41 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { // The builder_type stores the super type name of the nested Builder class. string builder_type; if (descriptor_->extension_range_count() > 0) { - printer->Print(variables, - "public $static$final class $classname$ extends\n" - " com.google.protobuf.GeneratedMessage$lite$.ExtendableMessage<\n" - " $classname$> implements\n" - " $extra_interfaces$\n" - " $classname$OrBuilder {\n"); + if (HasDescriptorMethods(descriptor_)) { + printer->Print(variables, + "public $static$final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessage.ExtendableMessage<\n" + " $classname$> implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n"); + } else { + printer->Print(variables, + "public $static$final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessageLite.ExtendableMessage<\n" + " $classname$, $classname$.Builder> implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n"); + } builder_type = strings::Substitute( - "com.google.protobuf.GeneratedMessage$1.ExtendableBuilder<$0, ?>", - name_resolver_->GetImmutableClassName(descriptor_), - variables["lite"]); + "com.google.protobuf.GeneratedMessage$1.ExtendableBuilder<$0, ?>", + name_resolver_->GetImmutableClassName(descriptor_), + variables["lite"]); } else { - printer->Print(variables, - "public $static$final class $classname$ extends\n" - " com.google.protobuf.GeneratedMessage$lite$ implements\n" - " $extra_interfaces$\n" - " $classname$OrBuilder {\n"); + if (HasDescriptorMethods(descriptor_)) { + printer->Print(variables, + "public $static$final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessage implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n"); + } else { + printer->Print(variables, + "public $static$final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessageLite<\n" + " $classname$, $classname$.Builder> implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n"); + } + builder_type = strings::Substitute( "com.google.protobuf.GeneratedMessage$0.Builder", variables["lite"]); @@ -349,7 +369,7 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { GenerateParsingConstructor(printer); } - GenerateDescriptorMethods(printer); + GenerateDescriptorMethods(printer, false); GenerateParser(printer); // Nested types @@ -481,7 +501,7 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { // Carefully initialize the default instance in such a way that it doesn't // conflict with other initialization. printer->Print( - "private static final $classname$ defaultInstance;", + "private static final $classname$ defaultInstance;\n", "classname", name_resolver_->GetImmutableClassName(descriptor_)); if (HasDescriptorMethods(descriptor_)) { printer->Print( @@ -494,15 +514,11 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { // LITE_RUNTIME only has one constructor. printer->Print( "static {\n" - " try {\n" - " defaultInstance = new $classname$(\n" - " com.google.protobuf.Internal\n" - " .EMPTY_CODED_INPUT_STREAM,\n" - " com.google.protobuf.ExtensionRegistryLite\n" - " .getEmptyRegistry());\n" - " } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n" - " throw new ExceptionInInitializerError(e);\n" - " }\n" + " defaultInstance = new $classname$(\n" + " com.google.protobuf.Internal\n" + " .EMPTY_CODED_INPUT_STREAM,\n" + " com.google.protobuf.ExtensionRegistryLite\n" + " .getEmptyRegistry());\n" "}\n" "\n", "classname", descriptor_->name()); @@ -511,12 +527,30 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { "public static $classname$ getDefaultInstance() {\n" " return defaultInstance;\n" "}\n" - "\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + + if (HasDescriptorMethods(descriptor_)) { + // LITE_RUNTIME implements this at the GeneratedMessageLite level. + printer->Print( "public $classname$ getDefaultInstanceForType() {\n" " return defaultInstance;\n" "}\n" "\n", "classname", name_resolver_->GetImmutableClassName(descriptor_)); + } else { + // LITE_RUNTIME uses this to implement the *ForType methods at the + // GeneratedMessageLite level. + printer->Print( + "static {" + " com.google.protobuf.GeneratedMessageLite.onLoad(\n" + " $classname$.class, new com.google.protobuf.GeneratedMessageLite\n" + " .PrototypeHolder<$classname$, Builder>(\n" + " defaultInstance, PARSER));" + "}\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + } // Extensions must be declared after the defaultInstance is initialized // because the defaultInstance is used by the extension to lazily retrieve @@ -526,6 +560,19 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { .Generate(printer); } + // Some fields also have static members that must be initialized after we + // have the default instance available. + printer->Print( + "static {\n"); + printer->Indent(); + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(descriptor_->field(i)) + .GenerateStaticInitializationCode(printer); + } + printer->Outdent(); + printer->Print( + "}\n"); + printer->Outdent(); printer->Print("}\n\n"); } @@ -542,37 +589,55 @@ GenerateMessageSerializationMethods(io::Printer* printer) { for (int i = 0; i < descriptor_->extension_range_count(); ++i) { sorted_extensions.push_back(descriptor_->extension_range(i)); } - sort(sorted_extensions.begin(), sorted_extensions.end(), - ExtensionRangeOrdering()); + std::sort(sorted_extensions.begin(), sorted_extensions.end(), + ExtensionRangeOrdering()); printer->Print( "public void writeTo(com.google.protobuf.CodedOutputStream output)\n" " throws java.io.IOException {\n"); printer->Indent(); - // writeTo(CodedOutputStream output) might be invoked without - // getSerializedSize() ever being called, but we need the memoized - // sizes in case this message has packed fields. Rather than emit checks for - // each packed field, just call getSerializedSize() up front for all messages. - // In most cases, getSerializedSize() will have already been called anyway by - // one of the wrapper writeTo() methods, making this call cheap. - printer->Print( - "getSerializedSize();\n"); + if (HasPackedFields(descriptor_)) { + // writeTo(CodedOutputStream output) might be invoked without + // getSerializedSize() ever being called, but we need the memoized + // sizes in case this message has packed fields. Rather than emit checks for + // each packed field, just call getSerializedSize() up front. + // In most cases, getSerializedSize() will have already been called anyway + // by one of the wrapper writeTo() methods, making this call cheap. + printer->Print( + "getSerializedSize();\n"); + } if (descriptor_->extension_range_count() > 0) { if (descriptor_->options().message_set_wire_format()) { - printer->Print( - "com.google.protobuf.GeneratedMessage$lite$\n" - " .ExtendableMessage<$classname$>.ExtensionWriter extensionWriter =\n" - " newMessageSetExtensionWriter();\n", - "lite", HasDescriptorMethods(descriptor_) ? "" : "Lite", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "com.google.protobuf.GeneratedMessage\n" + " .ExtendableMessage<$classname$>.ExtensionWriter\n" + " extensionWriter = newMessageSetExtensionWriter();\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + } else { + printer->Print( + "com.google.protobuf.GeneratedMessageLite\n" + " .ExtendableMessage<$classname$, $classname$.Builder>\n" + " .ExtensionWriter extensionWriter =\n" + " newMessageSetExtensionWriter();\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + } } else { - printer->Print( - "com.google.protobuf.GeneratedMessage$lite$\n" - " .ExtendableMessage<$classname$>.ExtensionWriter extensionWriter =\n" - " newExtensionWriter();\n", - "lite", HasDescriptorMethods(descriptor_) ? "" : "Lite", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "com.google.protobuf.GeneratedMessage\n" + " .ExtendableMessage<$classname$>.ExtensionWriter\n" + " extensionWriter = newExtensionWriter();\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + } else { + printer->Print( + "com.google.protobuf.GeneratedMessageLite\n" + " .ExtendableMessage<$classname$, $classname$.Builder>\n" + " .ExtensionWriter extensionWriter =\n" + " newExtensionWriter();\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + } } } @@ -727,13 +792,23 @@ void ImmutableMessageGenerator::GenerateSerializeOneExtensionRange( // =================================================================== void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) { + if (HasDescriptorMethods(descriptor_)) { + // LITE_RUNTIME implements this at the GeneratedMessageLite level. + printer->Print( + "public Builder newBuilderForType() { return newBuilder(); }\n"); + } + printer->Print( - "public static Builder newBuilder() { return new Builder(); }\n" - "public Builder newBuilderForType() { return newBuilder(); }\n" + "public static Builder newBuilder() {\n" + " return defaultInstance.toBuilder();\n" + "}\n" "public static Builder newBuilder($classname$ prototype) {\n" - " return newBuilder().mergeFrom(prototype);\n" + " return defaultInstance.toBuilder().mergeFrom(prototype);\n" + "}\n" + "public Builder toBuilder() {\n" + " return this == defaultInstance\n" + " ? new Builder() : new Builder().mergeFrom(this);\n" "}\n" - "public Builder toBuilder() { return newBuilder(this); }\n" "\n", "classname", name_resolver_->GetImmutableClassName(descriptor_)); @@ -792,7 +867,7 @@ void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) { } printer->Indent(); - GenerateDescriptorMethods(printer); + GenerateDescriptorMethods(printer, true); GenerateCommonBuilderMethods(printer); if (HasGeneratedMethods(descriptor_)) { @@ -876,7 +951,7 @@ void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) { } void ImmutableMessageGenerator:: -GenerateDescriptorMethods(io::Printer* printer) { +GenerateDescriptorMethods(io::Printer* printer, bool is_builder) { if (HasDescriptorMethods(descriptor_)) { if (!descriptor_->options().no_standard_descriptor_accessor()) { printer->Print( @@ -909,9 +984,9 @@ GenerateDescriptorMethods(io::Printer* printer) { const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); printer->Print( "case $number$:\n" - " return $name$_;\n", + " return internalGet$capitalized_name$();\n", "number", SimpleItoa(field->number()), - "name", info->name); + "capitalized_name", info->capitalized_name); } printer->Print( "default:\n" @@ -922,6 +997,34 @@ GenerateDescriptorMethods(io::Printer* printer) { printer->Print( " }\n" "}\n"); + if (is_builder) { + printer->Print( + "@SuppressWarnings({\"rawtypes\"})\n" + "protected com.google.protobuf.MapField internalGetMutableMapField(\n" + " int number) {\n" + " switch (number) {\n"); + printer->Indent(); + printer->Indent(); + for (int i = 0; i < map_fields.size(); ++i) { + const FieldDescriptor* field = map_fields[i]; + const FieldGeneratorInfo* info = + context_->GetFieldGeneratorInfo(field); + printer->Print( + "case $number$:\n" + " return internalGetMutable$capitalized_name$();\n", + "number", SimpleItoa(field->number()), + "capitalized_name", info->capitalized_name); + } + printer->Print( + "default:\n" + " throw new RuntimeException(\n" + " \"Invalid map field number: \" + number);\n"); + printer->Outdent(); + printer->Outdent(); + printer->Print( + " }\n" + "}\n"); + } } printer->Print( "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" @@ -959,7 +1062,7 @@ GenerateCommonBuilderMethods(io::Printer* printer) { "classname", name_resolver_->GetImmutableClassName(descriptor_)); } else { // LITE runtime passes along the default instance to implement - // getDefaultInstanceForType() at the GneratedMessageLite level. + // getDefaultInstanceForType() at the GeneratedMessageLite level. printer->Print( "// Construct using $classname$.newBuilder()\n" "private Builder() {\n" @@ -1062,22 +1165,17 @@ GenerateCommonBuilderMethods(io::Printer* printer) { if (HasDescriptorMethods(descriptor_)) { printer->Print( "public $classname$ buildPartial() {\n" - " $classname$ result = new $classname$(this);\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + " $classname$ result = new $classname$(this);\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); } else { // LITE_RUNTIME only provides a single message constructor. printer->Print( "public $classname$ buildPartial() {\n" - " $classname$ result = null;\n" - " try {\n" - " result = new $classname$(\n" - " com.google.protobuf.Internal\n" - " .EMPTY_CODED_INPUT_STREAM,\n" - " com.google.protobuf.ExtensionRegistryLite\n" - " .getEmptyRegistry());\n" - " } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n" - " throw new RuntimeException(e);\n" - " }\n" + " $classname$ result = new $classname$(\n" + " com.google.protobuf.Internal\n" + " .EMPTY_CODED_INPUT_STREAM,\n" + " com.google.protobuf.ExtensionRegistryLite\n" + " .getEmptyRegistry());\n" " result.unknownFields = this.unknownFields;\n", "classname", name_resolver_->GetImmutableClassName(descriptor_)); @@ -1271,6 +1369,12 @@ GenerateBuilderParsingMethods(io::Printer* printer) { void ImmutableMessageGenerator::GenerateIsInitialized( io::Printer* printer, UseMemoization useMemoization) { + // LITE_RUNTIME avoids generating isInitialized if it's not needed. + if (!HasDescriptorMethods(descriptor_) + && !HasRequiredFields(descriptor_)) { + return; + } + bool memoization = useMemoization == MEMOIZE; if (memoization) { // Memoizes whether the protocol buffer is fully initialized (has all @@ -1558,8 +1662,7 @@ GenerateParsingConstructor(io::Printer* printer) { printer->Print( "private $classname$(\n" " com.google.protobuf.CodedInputStream input,\n" - " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" - " throws com.google.protobuf.InvalidProtocolBufferException {\n", + " com.google.protobuf.ExtensionRegistryLite extensionRegistry) {\n", "classname", descriptor_->name()); printer->Indent(); @@ -1695,10 +1798,11 @@ GenerateParsingConstructor(io::Printer* printer) { printer->Outdent(); printer->Print( "} catch (com.google.protobuf.InvalidProtocolBufferException e) {\n" - " throw e.setUnfinishedMessage(this);\n" + " throw new RuntimeException(e.setUnfinishedMessage(this));\n" "} catch (java.io.IOException e) {\n" - " throw new com.google.protobuf.InvalidProtocolBufferException(\n" - " e.getMessage()).setUnfinishedMessage(this);\n" + " throw new RuntimeException(\n" + " new com.google.protobuf.InvalidProtocolBufferException(\n" + " e.getMessage()).setUnfinishedMessage(this));\n" "} finally {\n"); printer->Indent(); @@ -1747,8 +1851,19 @@ void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) { " throws com.google.protobuf.InvalidProtocolBufferException {\n", "classname", descriptor_->name()); if (HasGeneratedMethods(descriptor_)) { + // The parsing constructor throws an InvalidProtocolBufferException via a + // RuntimeException to aid in method pruning. We unwrap it here. printer->Print( - " return new $classname$(input, extensionRegistry);\n", + " try {\n" + " return new $classname$(input, extensionRegistry);\n" + " } catch (RuntimeException e) {\n" + " if (e.getCause() instanceof\n" + " com.google.protobuf.InvalidProtocolBufferException) {\n" + " throw (com.google.protobuf.InvalidProtocolBufferException)\n" + " e.getCause();\n" + " }\n" + " throw e;\n" + " }\n", "classname", descriptor_->name()); } else { // When parsing constructor isn't generated, use builder to parse messages. @@ -1775,13 +1890,16 @@ void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) { "};\n" "\n"); - printer->Print( - "@java.lang.Override\n" - "public com.google.protobuf.Parser<$classname$> getParserForType() {\n" - " return PARSER;\n" - "}\n" - "\n", - "classname", descriptor_->name()); + if (HasDescriptorMethods(descriptor_)) { + // LITE_RUNTIME implements this at the GeneratedMessageLite level. + printer->Print( + "@java.lang.Override\n" + "public com.google.protobuf.Parser<$classname$> getParserForType() {\n" + " return PARSER;\n" + "}\n" + "\n", + "classname", descriptor_->name()); + } } // =================================================================== diff --git a/src/google/protobuf/compiler/java/java_message.h b/src/google/protobuf/compiler/java/java_message.h index 91eb2876..016fdd5d 100644 --- a/src/google/protobuf/compiler/java/java_message.h +++ b/src/google/protobuf/compiler/java/java_message.h @@ -117,7 +117,7 @@ class ImmutableMessageGenerator : public MessageGenerator { void GenerateBuilder(io::Printer* printer); void GenerateCommonBuilderMethods(io::Printer* printer); - void GenerateDescriptorMethods(io::Printer* printer); + void GenerateDescriptorMethods(io::Printer* printer, bool is_builder); void GenerateBuilderParsingMethods(io::Printer* printer); void GenerateIsInitialized(io::Printer* printer, UseMemoization useMemoization); diff --git a/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc index e331d7a4..48757c60 100644 --- a/src/google/protobuf/compiler/java/java_primitive_field.cc +++ b/src/google/protobuf/compiler/java/java_primitive_field.cc @@ -772,6 +772,9 @@ GenerateParsingDoneCode(io::Printer* printer) const { void RepeatedImmutablePrimitiveFieldGenerator:: GenerateSerializationCode(io::Printer* printer) const { if (descriptor_->options().packed()) { + // We invoke getSerializedSize in writeTo for messages that have packed + // fields in ImmutableMessageGenerator::GenerateMessageSerializationMethods. + // That makes it safe to rely on the memoized size here. printer->Print(variables_, "if (get$capitalized_name$List().size() > 0) {\n" " output.writeRawVarint32($tag$);\n" diff --git a/src/google/protobuf/compiler/java/java_shared_code_generator.cc b/src/google/protobuf/compiler/java/java_shared_code_generator.cc index 2e61ea8a..70177367 100644 --- a/src/google/protobuf/compiler/java/java_shared_code_generator.cc +++ b/src/google/protobuf/compiler/java/java_shared_code_generator.cc @@ -171,7 +171,7 @@ void SharedCodeGenerator::GenerateDescriptors(io::Printer* printer) { string classname = FileJavaPackage(file_->dependency(i)) + "." + name_resolver_->GetDescriptorClassName( file_->dependency(i)); - dependencies.push_back(make_pair(filename, classname)); + dependencies.push_back(std::make_pair(filename, classname)); } } diff --git a/src/google/protobuf/compiler/java/java_string_field.cc b/src/google/protobuf/compiler/java/java_string_field.cc index 1c9302af..8aa5699c 100644 --- a/src/google/protobuf/compiler/java/java_string_field.cc +++ b/src/google/protobuf/compiler/java/java_string_field.cc @@ -667,7 +667,7 @@ GenerateParsingCode(io::Printer* printer) const { printer->Print(variables_, "String s = input.readStringRequireUtf8();\n" "$set_oneof_case_message$;\n" - "$oneof_name$_ = s;\n}\n"); + "$oneof_name$_ = s;\n"); } else if (!HasDescriptorMethods(descriptor_->file())) { // Lite runtime should attempt to reduce allocations by attempting to // construct the string directly from the input stream buffer. This avoids -- cgit v1.2.3