From 0ae7882b5c31991b8e9c2971c733f456ceec1d68 Mon Sep 17 00:00:00 2001 From: Rob Pike Date: Tue, 7 Jul 2009 21:05:24 -0700 Subject: [PATCH] bug fix: encOpFor etc. need to indirect R=rsc DELTA=28 (7 added, 7 deleted, 14 changed) OCL=31312 CL=31322 --- src/pkg/gob/decode.go | 18 +++++++++--------- src/pkg/gob/encode.go | 20 ++++++++++---------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/pkg/gob/decode.go b/src/pkg/gob/decode.go index b6d9d6fd16..1b3e3104a8 100644 --- a/src/pkg/gob/decode.go +++ b/src/pkg/gob/decode.go @@ -388,7 +388,10 @@ var decOpMap = map[reflect.Type] decOp { func getDecEngine(rt reflect.Type) *decEngine -func decOpFor(typ reflect.Type) decOp { +// Return the decoding op for the base type under rt and +// the indirection count to reach it. +func decOpFor(rt reflect.Type) (decOp, int) { + typ, indir := indirect(rt); op, ok := decOpMap[reflect.Typeof(typ)]; if !ok { // Special cases @@ -398,15 +401,13 @@ func decOpFor(typ reflect.Type) decOp { op = decUint8Array; break; } - elemOp := decOpFor(t.Elem()); - _, elemIndir := indirect(t.Elem()); + elemOp, elemIndir := decOpFor(t.Elem()); op = func(i *decInstr, state *DecState, p unsafe.Pointer) { state.err = decodeSlice(t, state, uintptr(p), elemOp, t.Elem().Size(), i.indir, elemIndir); }; case *reflect.ArrayType: - elemOp := decOpFor(t.Elem()); - _, elemIndir := indirect(t.Elem()); + elemOp, elemIndir := decOpFor(t.Elem()); op = func(i *decInstr, state *DecState, p unsafe.Pointer) { state.err = decodeArray(t, state, uintptr(p), elemOp, t.Elem().Size(), t.Len(), i.indir, elemIndir); }; @@ -420,9 +421,9 @@ func decOpFor(typ reflect.Type) decOp { } } if op == nil { - panicln("decode can't handle type", typ.String()); + panicln("decode can't handle type", rt.String()); } - return op + return op, indir } func compileDec(rt reflect.Type, typ Type) *decEngine { @@ -438,8 +439,7 @@ func compileDec(rt reflect.Type, typ Type) *decEngine { // TODO(r): verify compatibility with corresponding field of data. // For now, assume perfect correspondence between struct and gob. f := srt.Field(fieldnum); - ftyp, indir := indirect(f.Type); - op := decOpFor(ftyp); + op, indir := decOpFor(f.Type); engine.instr[fieldnum] = decInstr{op, fieldnum, indir, uintptr(f.Offset)}; } return engine; diff --git a/src/pkg/gob/encode.go b/src/pkg/gob/encode.go index 484d623dec..f32180c3a9 100644 --- a/src/pkg/gob/encode.go +++ b/src/pkg/gob/encode.go @@ -268,7 +268,6 @@ func encodeStruct(engine *encEngine, w io.Writer, basep uintptr) os.Error { p := unsafe.Pointer(basep+instr.offset); if instr.indir > 0 { if p = encIndirect(p, instr.indir); p == nil { - state.fieldnum = i; continue } } @@ -321,9 +320,13 @@ var encOpMap = map[reflect.Type] encOp { func getEncEngine(rt reflect.Type) *encEngine -func encOpFor(typ reflect.Type) encOp { +// Return the encoding op for the base type under rt and +// the indirection count to reach it. +func encOpFor(rt reflect.Type) (encOp, int) { + typ, indir := indirect(rt); op, ok := encOpMap[reflect.Typeof(typ)]; if !ok { + typ, _ := indirect(rt); // Special cases switch t := typ.(type) { case *reflect.SliceType: @@ -332,8 +335,7 @@ func encOpFor(typ reflect.Type) encOp { break; } // Slices have a header; we decode it to find the underlying array. - elemOp := encOpFor(t.Elem()); - _, indir := indirect(t.Elem()); + elemOp, indir := encOpFor(t.Elem()); op = func(i *encInstr, state *EncState, p unsafe.Pointer) { slice := (*reflect.SliceHeader)(p); if slice.Len == 0 { @@ -344,8 +346,7 @@ func encOpFor(typ reflect.Type) encOp { }; case *reflect.ArrayType: // True arrays have size in the type. - elemOp := encOpFor(t.Elem()); - _, indir := indirect(t.Elem()); + elemOp, indir := encOpFor(t.Elem()); op = func(i *encInstr, state *EncState, p unsafe.Pointer) { state.update(i); state.err = encodeArray(state.w, uintptr(p), elemOp, t.Elem().Size(), t.Len(), indir); @@ -360,9 +361,9 @@ func encOpFor(typ reflect.Type) encOp { } } if op == nil { - panicln("encode can't handle type", typ.String()); + panicln("encode can't handle type", rt.String()); } - return op + return op, indir } // The local Type was compiled from the actual value, so we know @@ -377,8 +378,7 @@ func compileEnc(rt reflect.Type, typ Type) *encEngine { engine.instr = make([]encInstr, srt.NumField()+1); // +1 for terminator for fieldnum := 0; fieldnum < srt.NumField(); fieldnum++ { f := srt.Field(fieldnum); - ftyp, indir := indirect(f.Type); - op := encOpFor(ftyp); + op, indir := encOpFor(f.Type); engine.instr[fieldnum] = encInstr{op, fieldnum, indir, uintptr(f.Offset)}; } engine.instr[srt.NumField()] = encInstr{encStructTerminator, 0, 0, 0};