Commit 04feb76f authored by Max Cai's avatar Max Cai

Avoid class initializers to help ProGuard.

Class initializers prevent ProGuard from inlining any methods
because it thinks the class initializer may have side effects.
This is true for static methods, but instance methods can still
be inlined, because to have an instance you will have touched
the class and any class initializers would have run. But
ProGuard only starts inlining instance methods of classes with
class initializers from v4.11b6, and Android uses v4.4 now.

This change tries to avoid the class initializers as much as
possible, by delaying the initialization of the empty array and
some fields' saved defaults until when they're needed. However,
if the message hosts any extensions, they must be public static
final and therefore introducing the class initializer. In that
case we won't bother with lazy initialization.

Change-Id: I00d8296f6eb0023112b93ee135cdb28dbd52b0b8
parent 482bf524
...@@ -45,6 +45,18 @@ public final class InternalNano { ...@@ -45,6 +45,18 @@ public final class InternalNano {
private InternalNano() {} private InternalNano() {}
/**
* An object to provide synchronization when lazily initializing static fields
* of {@link MessageNano} subclasses.
* <p>
* To enable earlier versions of ProGuard to inline short methods from a
* generated MessageNano subclass to the call sites, that class must not have
* a class initializer, which will be created if there is any static variable
* initializers. To lazily initialize the static variables in a thread-safe
* manner, the initialization code will synchronize on this object.
*/
public static final Object LAZY_INIT_LOCK = new Object();
/** /**
* Helper called by generated code to construct default values for string * Helper called by generated code to construct default values for string
* fields. * fields.
......
...@@ -62,7 +62,7 @@ public final class MessageNanoPrinter { ...@@ -62,7 +62,7 @@ public final class MessageNanoPrinter {
StringBuffer buf = new StringBuffer(); StringBuffer buf = new StringBuffer();
try { try {
print(null, message.getClass(), message, new StringBuffer(), buf); print(null, message, new StringBuffer(), buf);
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
return "Error printing proto: " + e.getMessage(); return "Error printing proto: " + e.getMessage();
} }
...@@ -70,33 +70,32 @@ public final class MessageNanoPrinter { ...@@ -70,33 +70,32 @@ public final class MessageNanoPrinter {
} }
/** /**
* Function that will print the given message/class into the StringBuffer. * Function that will print the given message/field into the StringBuffer.
* Meant to be called recursively. * Meant to be called recursively.
* *
* @param identifier the identifier to use, or {@code null} if this is the root message to * @param identifier the identifier to use, or {@code null} if this is the root message to
* print. * print.
* @param clazz the class of {@code message}. * @param object the value to print. May in fact be a primitive value or byte array and not a
* @param message the value to print. May in fact be a primitive value or byte array and not a
* message. * message.
* @param indentBuf the indentation each line should begin with. * @param indentBuf the indentation each line should begin with.
* @param buf the output buffer. * @param buf the output buffer.
*/ */
private static void print(String identifier, Class<?> clazz, Object message, private static void print(String identifier, Object object,
StringBuffer indentBuf, StringBuffer buf) throws IllegalAccessException { StringBuffer indentBuf, StringBuffer buf) throws IllegalAccessException {
if (message == null) { if (object == null) {
// This can happen if... // This can happen if...
// - we're about to print a message, String, or byte[], but it not present; // - we're about to print a message, String, or byte[], but it not present;
// - we're about to print a primitive, but "reftype" optional style is enabled, and // - we're about to print a primitive, but "reftype" optional style is enabled, and
// the field is unset. // the field is unset.
// In both cases the appropriate behavior is to output nothing. // In both cases the appropriate behavior is to output nothing.
} else if (MessageNano.class.isAssignableFrom(clazz)) { // Nano proto message } else if (object instanceof MessageNano) { // Nano proto message
int origIndentBufLength = indentBuf.length(); int origIndentBufLength = indentBuf.length();
if (identifier != null) { if (identifier != null) {
buf.append(indentBuf).append(deCamelCaseify(identifier)).append(" <\n"); buf.append(indentBuf).append(deCamelCaseify(identifier)).append(" <\n");
indentBuf.append(INDENT); indentBuf.append(INDENT);
} }
for (Field field : clazz.getFields()) { for (Field field : object.getClass().getFields()) {
// Proto fields are public, non-static variables that do not begin or end with '_' // Proto fields are public, non-static variables that do not begin or end with '_'
int modifiers = field.getModifiers(); int modifiers = field.getModifiers();
String fieldName = field.getName(); String fieldName = field.getName();
...@@ -106,24 +105,24 @@ public final class MessageNanoPrinter { ...@@ -106,24 +105,24 @@ public final class MessageNanoPrinter {
continue; continue;
} }
Class <?> fieldType = field.getType(); Class<?> fieldType = field.getType();
Object value = field.get(message); Object value = field.get(object);
if (fieldType.isArray()) { if (fieldType.isArray()) {
Class<?> arrayType = fieldType.getComponentType(); Class<?> arrayType = fieldType.getComponentType();
// bytes is special since it's not repeated, but is represented by an array // bytes is special since it's not repeated, but is represented by an array
if (arrayType == byte.class) { if (arrayType == byte.class) {
print(fieldName, fieldType, value, indentBuf, buf); print(fieldName, value, indentBuf, buf);
} else { } else {
int len = value == null ? 0 : Array.getLength(value); int len = value == null ? 0 : Array.getLength(value);
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
Object elem = Array.get(value, i); Object elem = Array.get(value, i);
print(fieldName, arrayType, elem, indentBuf, buf); print(fieldName, elem, indentBuf, buf);
} }
} }
} else { } else {
print(fieldName, fieldType, value, indentBuf, buf); print(fieldName, value, indentBuf, buf);
} }
} }
if (identifier != null) { if (identifier != null) {
...@@ -134,13 +133,13 @@ public final class MessageNanoPrinter { ...@@ -134,13 +133,13 @@ public final class MessageNanoPrinter {
// Non-null primitive value // Non-null primitive value
identifier = deCamelCaseify(identifier); identifier = deCamelCaseify(identifier);
buf.append(indentBuf).append(identifier).append(": "); buf.append(indentBuf).append(identifier).append(": ");
if (message instanceof String) { if (object instanceof String) {
String stringMessage = sanitizeString((String) message); String stringMessage = sanitizeString((String) object);
buf.append("\"").append(stringMessage).append("\""); buf.append("\"").append(stringMessage).append("\"");
} else if (message instanceof byte[]) { } else if (object instanceof byte[]) {
appendQuotedBytes((byte[]) message, buf); appendQuotedBytes((byte[]) object, buf);
} else { } else {
buf.append(message); buf.append(object);
} }
buf.append("\n"); buf.append("\n");
} }
......
...@@ -87,7 +87,7 @@ EnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params) ...@@ -87,7 +87,7 @@ EnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
EnumFieldGenerator::~EnumFieldGenerator() {} EnumFieldGenerator::~EnumFieldGenerator() {}
void EnumFieldGenerator:: void EnumFieldGenerator::
GenerateMembers(io::Printer* printer) const { GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
printer->Print(variables_, printer->Print(variables_,
"public $type$ $name$;\n"); "public $type$ $name$;\n");
...@@ -214,7 +214,7 @@ AccessorEnumFieldGenerator(const FieldDescriptor* descriptor, ...@@ -214,7 +214,7 @@ AccessorEnumFieldGenerator(const FieldDescriptor* descriptor,
AccessorEnumFieldGenerator::~AccessorEnumFieldGenerator() {} AccessorEnumFieldGenerator::~AccessorEnumFieldGenerator() {}
void AccessorEnumFieldGenerator:: void AccessorEnumFieldGenerator::
GenerateMembers(io::Printer* printer) const { GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
printer->Print(variables_, printer->Print(variables_,
"private int $name$_;\n" "private int $name$_;\n"
"public int get$capitalized_name$() {\n" "public int get$capitalized_name$() {\n"
...@@ -291,7 +291,7 @@ RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, const Params& para ...@@ -291,7 +291,7 @@ RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, const Params& para
RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {} RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
void RepeatedEnumFieldGenerator:: void RepeatedEnumFieldGenerator::
GenerateMembers(io::Printer* printer) const { GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
printer->Print(variables_, printer->Print(variables_,
"public $type$[] $name$;\n"); "public $type$[] $name$;\n");
} }
......
...@@ -46,11 +46,12 @@ namespace javanano { ...@@ -46,11 +46,12 @@ namespace javanano {
class EnumFieldGenerator : public FieldGenerator { class EnumFieldGenerator : public FieldGenerator {
public: public:
explicit EnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params); explicit EnumFieldGenerator(
const FieldDescriptor* descriptor, const Params& params);
~EnumFieldGenerator(); ~EnumFieldGenerator();
// implements FieldGenerator --------------------------------------- // implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer, bool lazy_init) const;
void GenerateClearCode(io::Printer* printer) const; void GenerateClearCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const;
...@@ -72,7 +73,7 @@ class AccessorEnumFieldGenerator : public FieldGenerator { ...@@ -72,7 +73,7 @@ class AccessorEnumFieldGenerator : public FieldGenerator {
~AccessorEnumFieldGenerator(); ~AccessorEnumFieldGenerator();
// implements FieldGenerator --------------------------------------- // implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer, bool lazy_init) const;
void GenerateClearCode(io::Printer* printer) const; void GenerateClearCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const;
...@@ -89,11 +90,12 @@ class AccessorEnumFieldGenerator : public FieldGenerator { ...@@ -89,11 +90,12 @@ class AccessorEnumFieldGenerator : public FieldGenerator {
class RepeatedEnumFieldGenerator : public FieldGenerator { class RepeatedEnumFieldGenerator : public FieldGenerator {
public: public:
explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params); explicit RepeatedEnumFieldGenerator(
const FieldDescriptor* descriptor, const Params& params);
~RepeatedEnumFieldGenerator(); ~RepeatedEnumFieldGenerator();
// implements FieldGenerator --------------------------------------- // implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer, bool lazy_init) const;
void GenerateClearCode(io::Printer* printer) const; void GenerateClearCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const;
void GenerateMergingCodeFromPacked(io::Printer* printer) const; void GenerateMergingCodeFromPacked(io::Printer* printer) const;
......
...@@ -46,6 +46,19 @@ namespace javanano { ...@@ -46,6 +46,19 @@ namespace javanano {
FieldGenerator::~FieldGenerator() {} FieldGenerator::~FieldGenerator() {}
bool FieldGenerator::SavedDefaultNeeded() const {
// No saved default for this field by default.
// Subclasses whose instances may need saved defaults will override this
// and return the appropriate value.
return false;
}
void FieldGenerator::GenerateInitSavedDefaultCode(io::Printer* printer) const {
// No saved default for this field by default.
// Subclasses whose instances may need saved defaults will override this
// and generate the appropriate init code to the printer.
}
void FieldGenerator::GenerateMergingCodeFromPacked(io::Printer* printer) const { void FieldGenerator::GenerateMergingCodeFromPacked(io::Printer* printer) const {
// Reaching here indicates a bug. Cases are: // Reaching here indicates a bug. Cases are:
// - This FieldGenerator should support packing, but this method should be // - This FieldGenerator should support packing, but this method should be
...@@ -56,24 +69,26 @@ void FieldGenerator::GenerateMergingCodeFromPacked(io::Printer* printer) const { ...@@ -56,24 +69,26 @@ void FieldGenerator::GenerateMergingCodeFromPacked(io::Printer* printer) const {
<< "called on field generator that does not support packing."; << "called on field generator that does not support packing.";
} }
FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor, const Params &params) // =============================================
FieldGeneratorMap::FieldGeneratorMap(
const Descriptor* descriptor, const Params &params)
: descriptor_(descriptor), : descriptor_(descriptor),
field_generators_( field_generators_(
new scoped_ptr<FieldGenerator>[descriptor->field_count()]), new scoped_ptr<FieldGenerator>[descriptor->field_count()]) {
extension_generators_(
new scoped_ptr<FieldGenerator>[descriptor->extension_count()]) {
int next_has_bit_index = 0; int next_has_bit_index = 0;
bool saved_defaults_needed = false;
// Construct all the FieldGenerators. // Construct all the FieldGenerators.
for (int i = 0; i < descriptor->field_count(); i++) { for (int i = 0; i < descriptor->field_count(); i++) {
field_generators_[i].reset( FieldGenerator* field_generator = MakeGenerator(
MakeGenerator(descriptor->field(i), params, &next_has_bit_index)); descriptor->field(i), params, &next_has_bit_index);
} saved_defaults_needed = saved_defaults_needed
for (int i = 0; i < descriptor->extension_count(); i++) { || field_generator->SavedDefaultNeeded();
extension_generators_[i].reset( field_generators_[i].reset(field_generator);
MakeGenerator(descriptor->extension(i), params, &next_has_bit_index));
} }
total_bits_ = next_has_bit_index; total_bits_ = next_has_bit_index;
saved_defaults_needed_ = saved_defaults_needed;
} }
FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field, FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field,
...@@ -122,10 +137,6 @@ const FieldGenerator& FieldGeneratorMap::get( ...@@ -122,10 +137,6 @@ const FieldGenerator& FieldGeneratorMap::get(
return *field_generators_[field->index()]; return *field_generators_[field->index()];
} }
const FieldGenerator& FieldGeneratorMap::get_extension(int index) const {
return *extension_generators_[index];
}
} // namespace javanano } // namespace javanano
} // namespace compiler } // namespace compiler
} // namespace protobuf } // namespace protobuf
......
...@@ -53,11 +53,23 @@ namespace javanano { ...@@ -53,11 +53,23 @@ namespace javanano {
class FieldGenerator { class FieldGenerator {
public: public:
//FieldGenerator() {}
FieldGenerator(const Params& params) : params_(params) {} FieldGenerator(const Params& params) : params_(params) {}
virtual ~FieldGenerator(); virtual ~FieldGenerator();
virtual void GenerateMembers(io::Printer* printer) const = 0; virtual bool SavedDefaultNeeded() const;
virtual void GenerateInitSavedDefaultCode(io::Printer* printer) const;
// Generates code for Java fields and methods supporting this field.
// If this field needs a saved default (SavedDefaultNeeded() is true),
// then @lazy_init controls how the static field for that default value
// and its initialization code should be generated. If @lazy_init is
// true, the static field is not declared final and the initialization
// code is generated only when GenerateInitSavedDefaultCode is called;
// otherwise, the static field is declared final and initialized inline.
// GenerateInitSavedDefaultCode will not be called in the latter case.
virtual void GenerateMembers(
io::Printer* printer, bool lazy_init) const = 0;
virtual void GenerateClearCode(io::Printer* printer) const = 0; virtual void GenerateClearCode(io::Printer* printer) const = 0;
virtual void GenerateMergingCode(io::Printer* printer) const = 0; virtual void GenerateMergingCode(io::Printer* printer) const = 0;
...@@ -84,14 +96,14 @@ class FieldGeneratorMap { ...@@ -84,14 +96,14 @@ class FieldGeneratorMap {
~FieldGeneratorMap(); ~FieldGeneratorMap();
const FieldGenerator& get(const FieldDescriptor* field) const; const FieldGenerator& get(const FieldDescriptor* field) const;
const FieldGenerator& get_extension(int index) const;
int total_bits() const { return total_bits_; } int total_bits() const { return total_bits_; }
bool saved_defaults_needed() const { return saved_defaults_needed_; }
private: private:
const Descriptor* descriptor_; const Descriptor* descriptor_;
scoped_array<scoped_ptr<FieldGenerator> > field_generators_; scoped_array<scoped_ptr<FieldGenerator> > field_generators_;
scoped_array<scoped_ptr<FieldGenerator> > extension_generators_;
int total_bits_; int total_bits_;
bool saved_defaults_needed_;
static FieldGenerator* MakeGenerator(const FieldDescriptor* field, static FieldGenerator* MakeGenerator(const FieldDescriptor* field,
const Params &params, int* next_has_bit_index); const Params &params, int* next_has_bit_index);
......
...@@ -261,9 +261,7 @@ string FieldConstantName(const FieldDescriptor *field) { ...@@ -261,9 +261,7 @@ string FieldConstantName(const FieldDescriptor *field) {
} }
string FieldDefaultConstantName(const FieldDescriptor *field) { string FieldDefaultConstantName(const FieldDescriptor *field) {
string name = field->name() + "_DEFAULT"; return "_" + RenameJavaKeywords(UnderscoresToCamelCase(field)) + "Default";
UpperString(&name);
return name;
} }
JavaType GetJavaType(FieldDescriptor::Type field_type) { JavaType GetJavaType(FieldDescriptor::Type field_type) {
......
...@@ -155,14 +155,6 @@ void MessageGenerator::Generate(io::Printer* printer) { ...@@ -155,14 +155,6 @@ void MessageGenerator::Generate(io::Printer* printer) {
" com.google.protobuf.nano.MessageNano {\n"); " com.google.protobuf.nano.MessageNano {\n");
} }
printer->Indent(); printer->Indent();
printer->Print(
"\n"
"public static final $classname$[] EMPTY_ARRAY = {};\n"
"\n"
"public $classname$() {\n"
" clear();\n"
"}\n",
"classname", descriptor_->name());
// Nested types and extensions // Nested types and extensions
for (int i = 0; i < descriptor_->extension_count(); i++) { for (int i = 0; i < descriptor_->extension_count(); i++) {
...@@ -177,6 +169,42 @@ void MessageGenerator::Generate(io::Printer* printer) { ...@@ -177,6 +169,42 @@ void MessageGenerator::Generate(io::Printer* printer) {
MessageGenerator(descriptor_->nested_type(i), params_).Generate(printer); MessageGenerator(descriptor_->nested_type(i), params_).Generate(printer);
} }
// Lazy initialization of otherwise static final fields can help prevent the
// class initializer from being generated. We want to prevent it because it
// stops ProGuard from inlining any methods in this class into call sites and
// therefore reducing the method count. However, extensions are best kept as
// public static final fields with initializers, so with their existence we
// won't bother with lazy initialization.
bool lazy_init = descriptor_->extension_count() == 0;
// Empty array
if (lazy_init) {
printer->Print(
"\n"
"private static volatile $classname$[] _emptyArray;\n"
"public static $classname$[] emptyArray() {\n"
" // Lazily initializes the empty array\n"
" if (_emptyArray == null) {\n"
" synchronized (\n"
" com.google.protobuf.nano.InternalNano.LAZY_INIT_LOCK) {\n"
" if (_emptyArray == null) {\n"
" _emptyArray = new $classname$[0];\n"
" }\n"
" }\n"
" }\n"
" return _emptyArray;\n"
"}\n",
"classname", descriptor_->name());
} else {
printer->Print(
"\n"
"private static final $classname$[] EMPTY_ARRAY = {};\n"
"public static $classname$[] emptyArray() {\n"
" return EMPTY_ARRAY;\n"
"}\n",
"classname", descriptor_->name());
}
// Integers for bit fields // Integers for bit fields
int totalInts = (field_generators_.total_bits() + 31) / 32; int totalInts = (field_generators_.total_bits() + 31) / 32;
if (totalInts > 0) { if (totalInts > 0) {
...@@ -187,13 +215,57 @@ void MessageGenerator::Generate(io::Printer* printer) { ...@@ -187,13 +215,57 @@ void MessageGenerator::Generate(io::Printer* printer) {
} }
} }
// Fields // Fields and maybe their default values
for (int i = 0; i < descriptor_->field_count(); i++) { for (int i = 0; i < descriptor_->field_count(); i++) {
printer->Print("\n"); printer->Print("\n");
PrintFieldComment(printer, descriptor_->field(i)); PrintFieldComment(printer, descriptor_->field(i));
field_generators_.get(descriptor_->field(i)).GenerateMembers(printer); field_generators_.get(descriptor_->field(i)).GenerateMembers(
printer, lazy_init);
}
// Constructor, with lazy init code if needed
if (lazy_init && field_generators_.saved_defaults_needed()) {
printer->Print(
"\n"
"private static volatile boolean _classInitialized;\n"
"\n"
"public $classname$() {\n"
" // Lazily initializes the field defaults\n"
" if (!_classInitialized) {\n"
" synchronized (\n"
" com.google.protobuf.nano.InternalNano.LAZY_INIT_LOCK) {\n"
" if (!_classInitialized) {\n",
"classname", descriptor_->name());
printer->Indent();
printer->Indent();
printer->Indent();
printer->Indent();
for (int i = 0; i < descriptor_->field_count(); i++) {
field_generators_.get(descriptor_->field(i))
.GenerateInitSavedDefaultCode(printer);
}
printer->Outdent();
printer->Outdent();
printer->Outdent();
printer->Outdent();
printer->Print(
" _classInitialized = true;\n"
" }\n"
" }\n"
" }\n"
" clear();\n"
"}\n");
} else {
printer->Print(
"\n"
"public $classname$() {\n"
" clear();\n"
"}\n",
"classname", descriptor_->name());
} }
// Other methods in this class
GenerateClear(printer); GenerateClear(printer);
if (params_.generate_equals()) { if (params_.generate_equals()) {
......
...@@ -82,7 +82,7 @@ MessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params) ...@@ -82,7 +82,7 @@ MessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
MessageFieldGenerator::~MessageFieldGenerator() {} MessageFieldGenerator::~MessageFieldGenerator() {}
void MessageFieldGenerator:: void MessageFieldGenerator::
GenerateMembers(io::Printer* printer) const { GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
printer->Print(variables_, printer->Print(variables_,
"public $type$ $name$;\n"); "public $type$ $name$;\n");
} }
...@@ -158,7 +158,7 @@ RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, const Params& p ...@@ -158,7 +158,7 @@ RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, const Params& p
RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {} RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
void RepeatedMessageFieldGenerator:: void RepeatedMessageFieldGenerator::
GenerateMembers(io::Printer* printer) const { GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
printer->Print(variables_, printer->Print(variables_,
"public $type$[] $name$;\n"); "public $type$[] $name$;\n");
} }
...@@ -166,7 +166,7 @@ GenerateMembers(io::Printer* printer) const { ...@@ -166,7 +166,7 @@ GenerateMembers(io::Printer* printer) const {
void RepeatedMessageFieldGenerator:: void RepeatedMessageFieldGenerator::
GenerateClearCode(io::Printer* printer) const { GenerateClearCode(io::Printer* printer) const {
printer->Print(variables_, printer->Print(variables_,
"$name$ = $type$.EMPTY_ARRAY;\n"); "$name$ = $type$.emptyArray();\n");
} }
void RepeatedMessageFieldGenerator:: void RepeatedMessageFieldGenerator::
......
...@@ -46,11 +46,12 @@ namespace javanano { ...@@ -46,11 +46,12 @@ namespace javanano {
class MessageFieldGenerator : public FieldGenerator { class MessageFieldGenerator : public FieldGenerator {
public: public:
explicit MessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params); explicit MessageFieldGenerator(
const FieldDescriptor* descriptor, const Params& params);
~MessageFieldGenerator(); ~MessageFieldGenerator();
// implements FieldGenerator --------------------------------------- // implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer, bool lazy_init) const;
void GenerateClearCode(io::Printer* printer) const; void GenerateClearCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const;
...@@ -72,7 +73,7 @@ class RepeatedMessageFieldGenerator : public FieldGenerator { ...@@ -72,7 +73,7 @@ class RepeatedMessageFieldGenerator : public FieldGenerator {
~RepeatedMessageFieldGenerator(); ~RepeatedMessageFieldGenerator();
// implements FieldGenerator --------------------------------------- // implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer, bool lazy_init) const;
void GenerateClearCode(io::Printer* printer) const; void GenerateClearCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const;
......
...@@ -251,35 +251,41 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, const Params param ...@@ -251,35 +251,41 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, const Params param
} else { } else {
(*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor)); (*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor));
} }
(*variables)["default"] = DefaultValue(params, descriptor); // Deals with defaults. For C++-string types (string and bytes),
(*variables)["default_constant"] = FieldDefaultConstantName(descriptor); // we might need to have the generated code do the unicode decoding
// For C++-string types (string and bytes), we might need to have // (see comments in InternalNano.java for gory details.). We would
// the generated code do the unicode decoding (see comments in // like to do this once into a static field and re-use that from
// InternalNano.java for gory details.). We would like to do this
// once into a "private static final" field and re-use that from
// then on. // then on.
if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_STRING && if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
!descriptor->default_value_string().empty() && !descriptor->default_value_string().empty() &&
!params.use_reference_types_for_primitives()) { !params.use_reference_types_for_primitives()) {
string default_value;
if (descriptor->type() == FieldDescriptor::TYPE_BYTES) { if (descriptor->type() == FieldDescriptor::TYPE_BYTES) {
default_value = strings::Substitute( (*variables)["default"] = DefaultValue(params, descriptor);
(*variables)["default_constant"] = FieldDefaultConstantName(descriptor);
(*variables)["default_constant_value"] = strings::Substitute(
"com.google.protobuf.nano.InternalNano.bytesDefaultValue(\"$0\")", "com.google.protobuf.nano.InternalNano.bytesDefaultValue(\"$0\")",
CEscape(descriptor->default_value_string())); CEscape(descriptor->default_value_string()));
(*variables)["default_copy_if_needed"] = (*variables)["default"] + ".clone()"; (*variables)["default_copy_if_needed"] =
(*variables)["default"] + ".clone()";
} else if (AllAscii(descriptor->default_value_string())) {
// All chars are ASCII. In this case directly referencing a
// CEscape()'d string literal works fine.
(*variables)["default"] =
"\"" + CEscape(descriptor->default_value_string()) + "\"";
(*variables)["default_copy_if_needed"] = (*variables)["default"];
} else { } else {
if (AllAscii(descriptor->default_value_string())) { // Strings where some chars are non-ASCII. We need to save the
// All chars are ASCII. In this case CEscape() works fine. // default value.
default_value = "\"" + CEscape(descriptor->default_value_string()) + "\""; (*variables)["default"] = DefaultValue(params, descriptor);
} else { (*variables)["default_constant"] = FieldDefaultConstantName(descriptor);
default_value = strings::Substitute( (*variables)["default_constant_value"] = strings::Substitute(
"com.google.protobuf.nano.InternalNano.stringDefaultValue(\"$0\")", "com.google.protobuf.nano.InternalNano.stringDefaultValue(\"$0\")",
CEscape(descriptor->default_value_string())); CEscape(descriptor->default_value_string()));
}
(*variables)["default_copy_if_needed"] = (*variables)["default"]; (*variables)["default_copy_if_needed"] = (*variables)["default"];
} }
(*variables)["default_constant_value"] = default_value;
} else { } else {
// Non-string, non-bytes field. Defaults are literals.
(*variables)["default"] = DefaultValue(params, descriptor);
(*variables)["default_copy_if_needed"] = (*variables)["default"]; (*variables)["default_copy_if_needed"] = (*variables)["default"];
} }
(*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor)); (*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor));
...@@ -306,12 +312,29 @@ PrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params) ...@@ -306,12 +312,29 @@ PrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {} PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
bool PrimitiveFieldGenerator::SavedDefaultNeeded() const {
return variables_.find("default_constant") != variables_.end();
}
void PrimitiveFieldGenerator::GenerateInitSavedDefaultCode(io::Printer* printer) const {
if (variables_.find("default_constant") != variables_.end()) {
printer->Print(variables_,
"$default_constant$ = $default_constant_value$;\n");
}
}
void PrimitiveFieldGenerator:: void PrimitiveFieldGenerator::
GenerateMembers(io::Printer* printer) const { GenerateMembers(io::Printer* printer, bool lazy_init) const {
if (variables_.find("default_constant_value") != variables_.end()) { if (variables_.find("default_constant") != variables_.end()) {
// Those primitive types that need a saved default. // Those primitive types that need a saved default.
printer->Print(variables_, if (lazy_init) {
"private static final $type$ $default_constant$ = $default_constant_value$;\n"); printer->Print(variables_,
"private static $type$ $default_constant$;\n");
} else {
printer->Print(variables_,
"private static final $type$ $default_constant$ =\n"
" $default_constant_value$;\n");
}
} }
printer->Print(variables_, printer->Print(variables_,
...@@ -514,11 +537,30 @@ AccessorPrimitiveFieldGenerator(const FieldDescriptor* descriptor, ...@@ -514,11 +537,30 @@ AccessorPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
AccessorPrimitiveFieldGenerator::~AccessorPrimitiveFieldGenerator() {} AccessorPrimitiveFieldGenerator::~AccessorPrimitiveFieldGenerator() {}
bool AccessorPrimitiveFieldGenerator::SavedDefaultNeeded() const {
return variables_.find("default_constant") != variables_.end();
}
void AccessorPrimitiveFieldGenerator:: void AccessorPrimitiveFieldGenerator::
GenerateMembers(io::Printer* printer) const { GenerateInitSavedDefaultCode(io::Printer* printer) const {
if (variables_.find("default_constant_value") != variables_.end()) { if (variables_.find("default_constant") != variables_.end()) {
printer->Print(variables_, printer->Print(variables_,
"private static final $type$ $default_constant$ = $default_constant_value$;\n"); "$default_constant$ = $default_constant_value$;\n");
}
}
void AccessorPrimitiveFieldGenerator::
GenerateMembers(io::Printer* printer, bool lazy_init) const {
if (variables_.find("default_constant") != variables_.end()) {
// Those primitive types that need a saved default.
if (lazy_init) {
printer->Print(variables_,
"private static $type$ $default_constant$;\n");
} else {
printer->Print(variables_,
"private static final $type$ $default_constant$ =\n"
" $default_constant_value$;\n");
}
} }
printer->Print(variables_, printer->Print(variables_,
"private $type$ $name$_;\n" "private $type$ $name$_;\n"
...@@ -671,7 +713,7 @@ RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& ...@@ -671,7 +713,7 @@ RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params&
RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {} RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
void RepeatedPrimitiveFieldGenerator:: void RepeatedPrimitiveFieldGenerator::
GenerateMembers(io::Printer* printer) const { GenerateMembers(io::Printer* printer, bool /*unused init_defaults*/) const {
printer->Print(variables_, printer->Print(variables_,
"public $type$[] $name$;\n"); "public $type$[] $name$;\n");
} }
......
...@@ -46,11 +46,14 @@ namespace javanano { ...@@ -46,11 +46,14 @@ namespace javanano {
class PrimitiveFieldGenerator : public FieldGenerator { class PrimitiveFieldGenerator : public FieldGenerator {
public: public:
explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params &params); explicit PrimitiveFieldGenerator(
const FieldDescriptor* descriptor, const Params &params);
~PrimitiveFieldGenerator(); ~PrimitiveFieldGenerator();
// implements FieldGenerator --------------------------------------- // implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const; bool SavedDefaultNeeded() const;
void GenerateInitSavedDefaultCode(io::Printer* printer) const;
void GenerateMembers(io::Printer* printer, bool lazy_init) const;
void GenerateClearCode(io::Printer* printer) const; void GenerateClearCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const;
...@@ -69,12 +72,14 @@ class PrimitiveFieldGenerator : public FieldGenerator { ...@@ -69,12 +72,14 @@ class PrimitiveFieldGenerator : public FieldGenerator {
class AccessorPrimitiveFieldGenerator : public FieldGenerator { class AccessorPrimitiveFieldGenerator : public FieldGenerator {
public: public:
explicit AccessorPrimitiveFieldGenerator( const FieldDescriptor* descriptor, explicit AccessorPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
const Params &params, int has_bit_index); const Params &params, int has_bit_index);
~AccessorPrimitiveFieldGenerator(); ~AccessorPrimitiveFieldGenerator();
// implements FieldGenerator --------------------------------------- // implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const; bool SavedDefaultNeeded() const;
void GenerateInitSavedDefaultCode(io::Printer* printer) const;
void GenerateMembers(io::Printer* printer, bool lazy_init) const;
void GenerateClearCode(io::Printer* printer) const; void GenerateClearCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const;
...@@ -95,7 +100,7 @@ class RepeatedPrimitiveFieldGenerator : public FieldGenerator { ...@@ -95,7 +100,7 @@ class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
~RepeatedPrimitiveFieldGenerator(); ~RepeatedPrimitiveFieldGenerator();
// implements FieldGenerator --------------------------------------- // implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer, bool lazy_init) const;
void GenerateClearCode(io::Printer* printer) const; void GenerateClearCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const;
void GenerateMergingCodeFromPacked(io::Printer* printer) const; void GenerateMergingCodeFromPacked(io::Printer* printer) const;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment