internal/impl: omit isInit func when not needed
When generating the fast-path functions for a message, group, repeated
message, or repeated group field, check to see if the field message type
requires initialization checks. If not, leave the isInit func unset.
This permits the fast-path isInitialized to skip over these fields
entirely.
Change-Id: Icb5c380077d2216c4215bb0ebc16408e905aaece
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/214179
Reviewed-by: Joe Tsai <joetsai@google.com>
diff --git a/internal/impl/codec_field.go b/internal/impl/codec_field.go
index 366034c..3f3957c 100644
--- a/internal/impl/codec_field.go
+++ b/internal/impl/codec_field.go
@@ -164,7 +164,7 @@
func makeMessageFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
if mi := getMessageInfo(ft); mi != nil {
- return pointerCoderFuncs{
+ funcs := pointerCoderFuncs{
size: func(p pointer, tagsize int, opts marshalOptions) int {
return sizeMessageInfo(p, mi, tagsize, opts)
},
@@ -174,10 +174,13 @@
unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
return consumeMessageInfo(b, p, mi, wtyp, opts)
},
- isInit: func(p pointer) error {
- return mi.isInitializedPointer(p.Elem())
- },
}
+ if needsInitCheck(mi.Desc) {
+ funcs.isInit = func(p pointer) error {
+ return mi.isInitializedPointer(p.Elem())
+ }
+ }
+ return funcs
} else {
return pointerCoderFuncs{
size: func(p pointer, tagsize int, opts marshalOptions) int {
@@ -308,7 +311,7 @@
func makeGroupFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
num := fd.Number()
if mi := getMessageInfo(ft); mi != nil {
- return pointerCoderFuncs{
+ funcs := pointerCoderFuncs{
size: func(p pointer, tagsize int, opts marshalOptions) int {
return sizeGroupType(p, mi, tagsize, opts)
},
@@ -318,10 +321,13 @@
unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
return consumeGroupType(b, p, mi, num, wtyp, opts)
},
- isInit: func(p pointer) error {
- return mi.isInitializedPointer(p.Elem())
- },
}
+ if needsInitCheck(mi.Desc) {
+ funcs.isInit = func(p pointer) error {
+ return mi.isInitializedPointer(p.Elem())
+ }
+ }
+ return funcs
} else {
return pointerCoderFuncs{
size: func(p pointer, tagsize int, opts marshalOptions) int {
@@ -392,7 +398,7 @@
func makeMessageSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
if mi := getMessageInfo(ft); mi != nil {
- return pointerCoderFuncs{
+ funcs := pointerCoderFuncs{
size: func(p pointer, tagsize int, opts marshalOptions) int {
return sizeMessageSliceInfo(p, mi, tagsize, opts)
},
@@ -402,10 +408,13 @@
unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
return consumeMessageSliceInfo(b, p, mi, wtyp, opts)
},
- isInit: func(p pointer) error {
- return isInitMessageSliceInfo(p, mi)
- },
}
+ if needsInitCheck(mi.Desc) {
+ funcs.isInit = func(p pointer) error {
+ return isInitMessageSliceInfo(p, mi)
+ }
+ }
+ return funcs
}
return pointerCoderFuncs{
size: func(p pointer, tagsize int, opts marshalOptions) int {
@@ -644,7 +653,7 @@
func makeGroupSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
num := fd.Number()
if mi := getMessageInfo(ft); mi != nil {
- return pointerCoderFuncs{
+ funcs := pointerCoderFuncs{
size: func(p pointer, tagsize int, opts marshalOptions) int {
return sizeGroupSliceInfo(p, mi, tagsize, opts)
},
@@ -654,10 +663,13 @@
unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
return consumeGroupSliceInfo(b, p, num, wtyp, mi, opts)
},
- isInit: func(p pointer) error {
- return isInitMessageSliceInfo(p, mi)
- },
}
+ if needsInitCheck(mi.Desc) {
+ funcs.isInit = func(p pointer) error {
+ return isInitMessageSliceInfo(p, mi)
+ }
+ }
+ return funcs
}
return pointerCoderFuncs{
size: func(p pointer, tagsize int, opts marshalOptions) int {