gob: compute information about a user's type once.

Other than maybe cleaning the code up a bit, this has
little practical effect for now, but lays the foundation
for remembering the method set of a type, which can
be expensive.

R=rsc
CC=golang-dev
https://golang.org/cl/4193041
This commit is contained in:
Rob Pike 2011-02-22 12:31:57 -08:00
parent 556506e869
commit 14b6a47748
5 changed files with 101 additions and 57 deletions

View file

@ -384,10 +384,10 @@ func (enc *Encoder) encodeInterface(b *bytes.Buffer, iv *reflect.InterfaceValue)
return
}
typ, _ := indirect(iv.Elem().Type())
name, ok := concreteTypeToName[typ]
ut := userType(iv.Elem().Type())
name, ok := concreteTypeToName[ut.base]
if !ok {
errorf("gob: type not registered for interface: %s", typ)
errorf("gob: type not registered for interface: %s", ut.base)
}
// Send the name.
state.encodeUint(uint64(len(name)))
@ -396,14 +396,14 @@ func (enc *Encoder) encodeInterface(b *bytes.Buffer, iv *reflect.InterfaceValue)
error(err)
}
// Define the type id if necessary.
enc.sendTypeDescriptor(enc.writer(), state, typ)
enc.sendTypeDescriptor(enc.writer(), state, ut)
// Send the type id.
enc.sendTypeId(state, typ)
enc.sendTypeId(state, ut)
// Encode the value into a new buffer. Any nested type definitions
// should be written to b, before the encoded value.
enc.pushWriter(b)
data := new(bytes.Buffer)
err = enc.encode(data, iv.Elem())
err = enc.encode(data, iv.Elem(), ut)
if err != nil {
error(err)
}
@ -437,7 +437,9 @@ var encOpMap = []encOp{
// Return the encoding op for the base type under rt and
// the indirection count to reach it.
func (enc *Encoder) encOpFor(rt reflect.Type) (encOp, int) {
typ, indir := indirect(rt)
ut := userType(rt)
typ := ut.base
indir := ut.indir
var op encOp
k := typ.Kind()
if int(k) < len(encOpMap) {
@ -559,14 +561,12 @@ func (enc *Encoder) lockAndGetEncEngine(rt reflect.Type) *encEngine {
return enc.getEncEngine(rt)
}
func (enc *Encoder) encode(b *bytes.Buffer, value reflect.Value) (err os.Error) {
func (enc *Encoder) encode(b *bytes.Buffer, value reflect.Value, ut *userTypeInfo) (err os.Error) {
defer catchError(&err)
// Dereference down to the underlying object.
rt, indir := indirect(value.Type())
for i := 0; i < indir; i++ {
for i := 0; i < ut.indir; i++ {
value = reflect.Indirect(value)
}
engine := enc.lockAndGetEncEngine(rt)
engine := enc.lockAndGetEncEngine(ut.base)
if value.Type().Kind() == reflect.Struct {
enc.encodeStruct(b, engine, value.Addr())
} else {