goprotobuf: Avoid reflect+interface conversion for Marshaler/Unmarshaler check.
R=r
CC=golang-dev, rsc
http://codereview.appspot.com/5824045
diff --git a/proto/decode.go b/proto/decode.go
index 17f95f2..f259b7d 100644
--- a/proto/decode.go
+++ b/proto/decode.go
@@ -354,8 +354,7 @@
fieldnum, ok := prop.tags[tag]
if !ok {
// Maybe it's an extension?
- o.ptr = base // copy the address here to avoid a heap allocation.
- iv := reflect.NewAt(t, unsafe.Pointer(&o.ptr)).Elem().Interface()
+ iv := reflect.NewAt(st, unsafe.Pointer(base)).Interface()
if e, ok := iv.(extendableProto); ok && isExtensionField(e, int32(tag)) {
if err = o.skip(st, tag, wire); err == nil {
e.ExtensionMap()[int32(tag)] = Extension{enc: append([]byte(nil), o.buf[oi:o.index]...)}
@@ -654,13 +653,13 @@
ptr := (**struct{})(unsafe.Pointer(base + p.offset))
typ := p.stype.Elem()
bas := reflect.New(typ).Pointer()
- structv := unsafe.Pointer(bas)
- *ptr = (*struct{})(structv)
+ structp := unsafe.Pointer(bas)
+ *ptr = (*struct{})(structp)
// If the object can unmarshal itself, let it.
- iv := reflect.NewAt(p.stype, unsafe.Pointer(ptr)).Elem().Interface()
- if u, ok := iv.(Unmarshaler); ok {
- return u.Unmarshal(raw)
+ if p.isMarshaler {
+ iv := reflect.NewAt(p.stype.Elem(), structp).Interface()
+ return iv.(Unmarshaler).Unmarshal(raw)
}
obuf := o.buf
@@ -693,8 +692,8 @@
typ := p.stype.Elem()
bas := reflect.New(typ).Pointer()
- structv := unsafe.Pointer(bas)
- y = append(y, (*struct{})(structv))
+ structp := unsafe.Pointer(bas)
+ y = append(y, (*struct{})(structp))
*v = y
if is_group {
@@ -708,9 +707,9 @@
}
// If the object can unmarshal itself, let it.
- iv := reflect.NewAt(p.stype, unsafe.Pointer(&y[len(y)-1])).Elem().Interface()
- if u, ok := iv.(Unmarshaler); ok {
- return u.Unmarshal(raw)
+ if p.isUnmarshaler {
+ iv := reflect.NewAt(typ, structp).Interface()
+ return iv.(Unmarshaler).Unmarshal(raw)
}
obuf := o.buf