Commit 44232227 authored by Dmitriy Vyukov's avatar Dmitriy Vyukov

encoding/gob: remove unnecessary receivers

Encoder compilation must be enc-independent,
because the resulting program is reused across
different encoders.

LGTM=r
R=golang-codereviews, r
CC=golang-codereviews
https://golang.org/cl/115860043
parent 040eeff7
...@@ -470,11 +470,11 @@ var encOpTable = [...]encOp{ ...@@ -470,11 +470,11 @@ var encOpTable = [...]encOp{
// encOpFor returns (a pointer to) the encoding op for the base type under rt and // encOpFor returns (a pointer to) the encoding op for the base type under rt and
// the indirection count to reach it. // the indirection count to reach it.
func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp) (*encOp, int) { func encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp) (*encOp, int) {
ut := userType(rt) ut := userType(rt)
// If the type implements GobEncoder, we handle it without further processing. // If the type implements GobEncoder, we handle it without further processing.
if ut.externalEnc != 0 { if ut.externalEnc != 0 {
return enc.gobEncodeOpFor(ut) return gobEncodeOpFor(ut)
} }
// If this type is already in progress, it's a recursive type (e.g. map[string]*T). // If this type is already in progress, it's a recursive type (e.g. map[string]*T).
// Return the pointer to the op we're already building. // Return the pointer to the op we're already building.
...@@ -498,7 +498,7 @@ func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp ...@@ -498,7 +498,7 @@ func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp
break break
} }
// Slices have a header; we decode it to find the underlying array. // Slices have a header; we decode it to find the underlying array.
elemOp, elemIndir := enc.encOpFor(t.Elem(), inProgress) elemOp, elemIndir := encOpFor(t.Elem(), inProgress)
op = func(i *encInstr, state *encoderState, slice reflect.Value) { op = func(i *encInstr, state *encoderState, slice reflect.Value) {
if !state.sendZero && slice.Len() == 0 { if !state.sendZero && slice.Len() == 0 {
return return
...@@ -508,14 +508,14 @@ func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp ...@@ -508,14 +508,14 @@ func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp
} }
case reflect.Array: case reflect.Array:
// True arrays have size in the type. // True arrays have size in the type.
elemOp, elemIndir := enc.encOpFor(t.Elem(), inProgress) elemOp, elemIndir := encOpFor(t.Elem(), inProgress)
op = func(i *encInstr, state *encoderState, array reflect.Value) { op = func(i *encInstr, state *encoderState, array reflect.Value) {
state.update(i) state.update(i)
state.enc.encodeArray(state.b, array, *elemOp, elemIndir, array.Len()) state.enc.encodeArray(state.b, array, *elemOp, elemIndir, array.Len())
} }
case reflect.Map: case reflect.Map:
keyOp, keyIndir := enc.encOpFor(t.Key(), inProgress) keyOp, keyIndir := encOpFor(t.Key(), inProgress)
elemOp, elemIndir := enc.encOpFor(t.Elem(), inProgress) elemOp, elemIndir := encOpFor(t.Elem(), inProgress)
op = func(i *encInstr, state *encoderState, mv reflect.Value) { op = func(i *encInstr, state *encoderState, mv reflect.Value) {
// We send zero-length (but non-nil) maps because the // We send zero-length (but non-nil) maps because the
// receiver might want to use the map. (Maps don't use append.) // receiver might want to use the map. (Maps don't use append.)
...@@ -527,7 +527,7 @@ func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp ...@@ -527,7 +527,7 @@ func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp
} }
case reflect.Struct: case reflect.Struct:
// Generate a closure that calls out to the engine for the nested type. // Generate a closure that calls out to the engine for the nested type.
enc.getEncEngine(userType(typ)) getEncEngine(userType(typ))
info := mustGetTypeInfo(typ) info := mustGetTypeInfo(typ)
op = func(i *encInstr, state *encoderState, sv reflect.Value) { op = func(i *encInstr, state *encoderState, sv reflect.Value) {
state.update(i) state.update(i)
...@@ -550,9 +550,8 @@ func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp ...@@ -550,9 +550,8 @@ func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp
return &op, indir return &op, indir
} }
// gobEncodeOpFor returns the op for a type that is known to implement // gobEncodeOpFor returns the op for a type that is known to implement GobEncoder.
// GobEncoder. func gobEncodeOpFor(ut *userTypeInfo) (*encOp, int) {
func (enc *Encoder) gobEncodeOpFor(ut *userTypeInfo) (*encOp, int) {
rt := ut.user rt := ut.user
if ut.encIndir == -1 { if ut.encIndir == -1 {
rt = reflect.PtrTo(rt) rt = reflect.PtrTo(rt)
...@@ -580,7 +579,7 @@ func (enc *Encoder) gobEncodeOpFor(ut *userTypeInfo) (*encOp, int) { ...@@ -580,7 +579,7 @@ func (enc *Encoder) gobEncodeOpFor(ut *userTypeInfo) (*encOp, int) {
} }
// compileEnc returns the engine to compile the type. // compileEnc returns the engine to compile the type.
func (enc *Encoder) compileEnc(ut *userTypeInfo) *encEngine { func compileEnc(ut *userTypeInfo) *encEngine {
srt := ut.base srt := ut.base
engine := new(encEngine) engine := new(encEngine)
seen := make(map[reflect.Type]*encOp) seen := make(map[reflect.Type]*encOp)
...@@ -594,7 +593,7 @@ func (enc *Encoder) compileEnc(ut *userTypeInfo) *encEngine { ...@@ -594,7 +593,7 @@ func (enc *Encoder) compileEnc(ut *userTypeInfo) *encEngine {
if !isSent(&f) { if !isSent(&f) {
continue continue
} }
op, indir := enc.encOpFor(f.Type, seen) op, indir := encOpFor(f.Type, seen)
engine.instr = append(engine.instr, encInstr{*op, wireFieldNum, f.Index, indir}) engine.instr = append(engine.instr, encInstr{*op, wireFieldNum, f.Index, indir})
wireFieldNum++ wireFieldNum++
} }
...@@ -604,7 +603,7 @@ func (enc *Encoder) compileEnc(ut *userTypeInfo) *encEngine { ...@@ -604,7 +603,7 @@ func (enc *Encoder) compileEnc(ut *userTypeInfo) *encEngine {
engine.instr = append(engine.instr, encInstr{encStructTerminator, 0, nil, 0}) engine.instr = append(engine.instr, encInstr{encStructTerminator, 0, nil, 0})
} else { } else {
engine.instr = make([]encInstr, 1) engine.instr = make([]encInstr, 1)
op, indir := enc.encOpFor(rt, seen) op, indir := encOpFor(rt, seen)
engine.instr[0] = encInstr{*op, singletonField, nil, indir} engine.instr[0] = encInstr{*op, singletonField, nil, indir}
} }
return engine return engine
...@@ -612,7 +611,7 @@ func (enc *Encoder) compileEnc(ut *userTypeInfo) *encEngine { ...@@ -612,7 +611,7 @@ func (enc *Encoder) compileEnc(ut *userTypeInfo) *encEngine {
// getEncEngine returns the engine to compile the type. // getEncEngine returns the engine to compile the type.
// typeLock must be held (or we're in initialization and guaranteed single-threaded). // typeLock must be held (or we're in initialization and guaranteed single-threaded).
func (enc *Encoder) getEncEngine(ut *userTypeInfo) *encEngine { func getEncEngine(ut *userTypeInfo) *encEngine {
info, err1 := getTypeInfo(ut) info, err1 := getTypeInfo(ut)
if err1 != nil { if err1 != nil {
error_(err1) error_(err1)
...@@ -630,7 +629,7 @@ func (enc *Encoder) getEncEngine(ut *userTypeInfo) *encEngine { ...@@ -630,7 +629,7 @@ func (enc *Encoder) getEncEngine(ut *userTypeInfo) *encEngine {
info.encoder = nil info.encoder = nil
} }
}() }()
info.encoder = enc.compileEnc(ut) info.encoder = compileEnc(ut)
ok = true ok = true
} }
return info.encoder return info.encoder
...@@ -638,15 +637,15 @@ func (enc *Encoder) getEncEngine(ut *userTypeInfo) *encEngine { ...@@ -638,15 +637,15 @@ func (enc *Encoder) getEncEngine(ut *userTypeInfo) *encEngine {
// lockAndGetEncEngine is a function that locks and compiles. // lockAndGetEncEngine is a function that locks and compiles.
// This lets us hold the lock only while compiling, not when encoding. // This lets us hold the lock only while compiling, not when encoding.
func (enc *Encoder) lockAndGetEncEngine(ut *userTypeInfo) *encEngine { func lockAndGetEncEngine(ut *userTypeInfo) *encEngine {
typeLock.Lock() typeLock.Lock()
defer typeLock.Unlock() defer typeLock.Unlock()
return enc.getEncEngine(ut) return getEncEngine(ut)
} }
func (enc *Encoder) encode(b *bytes.Buffer, value reflect.Value, ut *userTypeInfo) { func (enc *Encoder) encode(b *bytes.Buffer, value reflect.Value, ut *userTypeInfo) {
defer catchError(&enc.err) defer catchError(&enc.err)
engine := enc.lockAndGetEncEngine(ut) engine := lockAndGetEncEngine(ut)
indir := ut.indir indir := ut.indir
if ut.externalEnc != 0 { if ut.externalEnc != 0 {
indir = int(ut.encIndir) indir = int(ut.encIndir)
......
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