From b1e64585b63536c783d04174431c017495a36884 Mon Sep 17 00:00:00 2001 From: Rob Pike Date: Wed, 1 Jul 2009 23:04:27 -0700 Subject: [PATCH] move dereference code out of the ops and into the interpreter loops. R=rsc DELTA=574 (40 added, 149 deleted, 385 changed) OCL=31017 CL=31019 --- src/pkg/gob/codec_test.go | 179 ++++++++++++++++++++------------------ src/pkg/gob/decode.go | 128 +++++++++------------------ src/pkg/gob/encode.go | 132 ++++++---------------------- 3 files changed, 165 insertions(+), 274 deletions(-) diff --git a/src/pkg/gob/codec_test.go b/src/pkg/gob/codec_test.go index c976adeb34..3647589031 100644 --- a/src/pkg/gob/codec_test.go +++ b/src/pkg/gob/codec_test.go @@ -122,6 +122,11 @@ func newEncState(b *bytes.Buffer) *EncState { return state; } +func encAddrOf(state *EncState, instr *encInstr) unsafe.Pointer { + p := unsafe.Pointer(state.base+instr.offset); + return encIndirect(p, instr.indir); +} + // Test instruction execution for encoding. // Do not run the machine yet; instead do individual instructions crafted by hand. func TestScalarEncInstructions(t *testing.T) { @@ -136,17 +141,17 @@ func TestScalarEncInstructions(t *testing.T) { instr := &encInstr{ encBool, 0, 0, 0 }; state := newEncState(b); state.base = uintptr(unsafe.Pointer(&data)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); state.fieldnum = 0; instr.field = 1; instr.indir = 1; instr.offset = uintptr(unsafe.Offsetof(data.b)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); state.fieldnum = 1; instr.field = 2; instr.indir = 2; instr.offset = uintptr(unsafe.Offsetof(data.c)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); if !bytes.Equal(boolResult, b.Data()) { t.Errorf("bool enc instructions: expected % x got % x", boolResult, b.Data()) } @@ -162,17 +167,17 @@ func TestScalarEncInstructions(t *testing.T) { instr := &encInstr{ encInt, 0, 0, 0 }; state := newEncState(b); state.base = uintptr(unsafe.Pointer(&data)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); state.fieldnum = 0; instr.field = 1; instr.indir = 1; instr.offset = uintptr(unsafe.Offsetof(data.b)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); state.fieldnum = 1; instr.field = 2; instr.indir = 2; instr.offset = uintptr(unsafe.Offsetof(data.c)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); if !bytes.Equal(signedResult, b.Data()) { t.Errorf("int enc instructions: expected % x got % x", signedResult, b.Data()) } @@ -188,17 +193,17 @@ func TestScalarEncInstructions(t *testing.T) { instr := &encInstr{ encUint, 0, 0, 0 }; state := newEncState(b); state.base = uintptr(unsafe.Pointer(&data)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); state.fieldnum = 0; instr.field = 1; instr.indir = 1; instr.offset = uintptr(unsafe.Offsetof(data.b)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); state.fieldnum = 1; instr.field = 2; instr.indir = 2; instr.offset = uintptr(unsafe.Offsetof(data.c)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); if !bytes.Equal(unsignedResult, b.Data()) { t.Errorf("uint enc instructions: expected % x got % x", unsignedResult, b.Data()) } @@ -214,17 +219,17 @@ func TestScalarEncInstructions(t *testing.T) { instr := &encInstr{ encInt, 0, 0, 0 }; state := newEncState(b); state.base = uintptr(unsafe.Pointer(&data)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); state.fieldnum = 0; instr.field = 1; instr.indir = 1; instr.offset = uintptr(unsafe.Offsetof(data.b)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); state.fieldnum = 1; instr.field = 2; instr.indir = 2; instr.offset = uintptr(unsafe.Offsetof(data.c)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); if !bytes.Equal(signedResult, b.Data()) { t.Errorf("int8 enc instructions: expected % x got % x", signedResult, b.Data()) } @@ -240,17 +245,17 @@ func TestScalarEncInstructions(t *testing.T) { instr := &encInstr{ encUint, 0, 0, 0 }; state := newEncState(b); state.base = uintptr(unsafe.Pointer(&data)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); state.fieldnum = 0; instr.field = 1; instr.indir = 1; instr.offset = uintptr(unsafe.Offsetof(data.b)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); state.fieldnum = 1; instr.field = 2; instr.indir = 2; instr.offset = uintptr(unsafe.Offsetof(data.c)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); if !bytes.Equal(unsignedResult, b.Data()) { t.Errorf("uint8 enc instructions: expected % x got % x", unsignedResult, b.Data()) } @@ -266,17 +271,17 @@ func TestScalarEncInstructions(t *testing.T) { instr := &encInstr{ encInt16, 0, 0, 0 }; state := newEncState(b); state.base = uintptr(unsafe.Pointer(&data)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); state.fieldnum = 0; instr.field = 1; instr.indir = 1; instr.offset = uintptr(unsafe.Offsetof(data.b)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); state.fieldnum = 1; instr.field = 2; instr.indir = 2; instr.offset = uintptr(unsafe.Offsetof(data.c)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); if !bytes.Equal(signedResult, b.Data()) { t.Errorf("int16 enc instructions: expected % x got % x", signedResult, b.Data()) } @@ -292,17 +297,17 @@ func TestScalarEncInstructions(t *testing.T) { instr := &encInstr{ encUint16, 0, 0, 0 }; state := newEncState(b); state.base = uintptr(unsafe.Pointer(&data)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); state.fieldnum = 0; instr.field = 1; instr.indir = 1; instr.offset = uintptr(unsafe.Offsetof(data.b)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); state.fieldnum = 1; instr.field = 2; instr.indir = 2; instr.offset = uintptr(unsafe.Offsetof(data.c)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); if !bytes.Equal(unsignedResult, b.Data()) { t.Errorf("uint16 enc instructions: expected % x got % x", unsignedResult, b.Data()) } @@ -318,17 +323,17 @@ func TestScalarEncInstructions(t *testing.T) { instr := &encInstr{ encInt32, 0, 0, 0 }; state := newEncState(b); state.base = uintptr(unsafe.Pointer(&data)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); state.fieldnum = 0; instr.field = 1; instr.indir = 1; instr.offset = uintptr(unsafe.Offsetof(data.b)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); state.fieldnum = 1; instr.field = 2; instr.indir = 2; instr.offset = uintptr(unsafe.Offsetof(data.c)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); if !bytes.Equal(signedResult, b.Data()) { t.Errorf("int32 enc instructions: expected % x got % x", signedResult, b.Data()) } @@ -344,17 +349,17 @@ func TestScalarEncInstructions(t *testing.T) { instr := &encInstr{ encUint32, 0, 0, 0 }; state := newEncState(b); state.base = uintptr(unsafe.Pointer(&data)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); state.fieldnum = 0; instr.field = 1; instr.indir = 1; instr.offset = uintptr(unsafe.Offsetof(data.b)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); state.fieldnum = 1; instr.field = 2; instr.indir = 2; instr.offset = uintptr(unsafe.Offsetof(data.c)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); if !bytes.Equal(unsignedResult, b.Data()) { t.Errorf("uint32 enc instructions: expected % x got % x", unsignedResult, b.Data()) } @@ -370,17 +375,17 @@ func TestScalarEncInstructions(t *testing.T) { instr := &encInstr{ encInt64, 0, 0, 0 }; state := newEncState(b); state.base = uintptr(unsafe.Pointer(&data)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); state.fieldnum = 0; instr.field = 1; instr.indir = 1; instr.offset = uintptr(unsafe.Offsetof(data.b)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); state.fieldnum = 1; instr.field = 2; instr.indir = 2; instr.offset = uintptr(unsafe.Offsetof(data.c)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); if !bytes.Equal(signedResult, b.Data()) { t.Errorf("int64 enc instructions: expected % x got % x", signedResult, b.Data()) } @@ -396,17 +401,17 @@ func TestScalarEncInstructions(t *testing.T) { instr := &encInstr{ encUint, 0, 0, 0 }; state := newEncState(b); state.base = uintptr(unsafe.Pointer(&data)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); state.fieldnum = 0; instr.field = 1; instr.indir = 1; instr.offset = uintptr(unsafe.Offsetof(data.b)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); state.fieldnum = 1; instr.field = 2; instr.indir = 2; instr.offset = uintptr(unsafe.Offsetof(data.c)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); if !bytes.Equal(unsignedResult, b.Data()) { t.Errorf("uint64 enc instructions: expected % x got % x", unsignedResult, b.Data()) } @@ -422,17 +427,17 @@ func TestScalarEncInstructions(t *testing.T) { instr := &encInstr{ encFloat, 0, 0, 0 }; state := newEncState(b); state.base = uintptr(unsafe.Pointer(&data)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); state.fieldnum = 0; instr.field = 1; instr.indir = 1; instr.offset = uintptr(unsafe.Offsetof(data.b)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); state.fieldnum = 1; instr.field = 2; instr.indir = 2; instr.offset = uintptr(unsafe.Offsetof(data.c)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); if !bytes.Equal(floatResult, b.Data()) { t.Errorf("float enc instructions: expected % x got % x", floatResult, b.Data()) } @@ -448,17 +453,17 @@ func TestScalarEncInstructions(t *testing.T) { instr := &encInstr{ encFloat32, 0, 0, 0 }; state := newEncState(b); state.base = uintptr(unsafe.Pointer(&data)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); state.fieldnum = 0; instr.field = 1; instr.indir = 1; instr.offset = uintptr(unsafe.Offsetof(data.b)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); state.fieldnum = 1; instr.field = 2; instr.indir = 2; instr.offset = uintptr(unsafe.Offsetof(data.c)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); if !bytes.Equal(floatResult, b.Data()) { t.Errorf("float32 enc instructions: expected % x got % x", floatResult, b.Data()) } @@ -474,17 +479,17 @@ func TestScalarEncInstructions(t *testing.T) { instr := &encInstr{ encFloat64, 0, 0, 0 }; state := newEncState(b); state.base = uintptr(unsafe.Pointer(&data)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); state.fieldnum = 0; instr.field = 1; instr.indir = 1; instr.offset = uintptr(unsafe.Offsetof(data.b)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); state.fieldnum = 1; instr.field = 2; instr.indir = 2; instr.offset = uintptr(unsafe.Offsetof(data.c)); - instr.op(instr, state); + instr.op(instr, state, encAddrOf(state, instr)); if !bytes.Equal(floatResult, b.Data()) { t.Errorf("float64 enc instructions: expected % x got % x", floatResult, b.Data()) } @@ -509,6 +514,12 @@ func newDecState(data []byte) *DecState { return state; } +// derive the address of a field, after indirecting indir times. +func decAddrOf(state *DecState, instr *decInstr) unsafe.Pointer { + p := unsafe.Pointer(state.base+instr.offset); + return decIndirect(p, instr.indir); +} + // Test instruction execution for decoding. // Do not run the machine yet; instead do individual instructions crafted by hand. func TestScalarDecInstructions(t *testing.T) { @@ -520,17 +531,17 @@ func TestScalarDecInstructions(t *testing.T) { state := newDecState(boolResult); state.base = uintptr(unsafe.Pointer(&data)); expectField(0, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); instr.field = 1; instr.indir = 1; instr.offset = uintptr(unsafe.Offsetof(data.b)); expectField(1, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); instr.field = 2; instr.indir = 2; instr.offset = uintptr(unsafe.Offsetof(data.c)); expectField(2, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); if data.a != true { t.Errorf("int a = %v not true", data.a) } @@ -549,17 +560,17 @@ func TestScalarDecInstructions(t *testing.T) { state := newDecState(signedResult); state.base = uintptr(unsafe.Pointer(&data)); expectField(0, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); instr.field = 1; instr.indir = 1; instr.offset = uintptr(unsafe.Offsetof(data.b)); expectField(1, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); instr.field = 2; instr.indir = 2; instr.offset = uintptr(unsafe.Offsetof(data.c)); expectField(2, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); if data.a != 17 { t.Errorf("int a = %v not 17", data.a) } @@ -578,17 +589,17 @@ func TestScalarDecInstructions(t *testing.T) { state := newDecState(unsignedResult); state.base = uintptr(unsafe.Pointer(&data)); expectField(0, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); instr.field = 1; instr.indir = 1; instr.offset = uintptr(unsafe.Offsetof(data.b)); expectField(1, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); instr.field = 2; instr.indir = 2; instr.offset = uintptr(unsafe.Offsetof(data.c)); expectField(2, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); if data.a != 17 { t.Errorf("int a = %v not 17", data.a) } @@ -607,17 +618,17 @@ func TestScalarDecInstructions(t *testing.T) { state := newDecState(signedResult); state.base = uintptr(unsafe.Pointer(&data)); expectField(0, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); instr.field = 1; instr.indir = 1; instr.offset = uintptr(unsafe.Offsetof(data.b)); expectField(1, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); instr.field = 2; instr.indir = 2; instr.offset = uintptr(unsafe.Offsetof(data.c)); expectField(2, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); if data.a != 17 { t.Errorf("int a = %v not 17", data.a) } @@ -636,17 +647,17 @@ func TestScalarDecInstructions(t *testing.T) { state := newDecState(unsignedResult); state.base = uintptr(unsafe.Pointer(&data)); expectField(0, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); instr.field = 1; instr.indir = 1; instr.offset = uintptr(unsafe.Offsetof(data.b)); expectField(1, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); instr.field = 2; instr.indir = 2; instr.offset = uintptr(unsafe.Offsetof(data.c)); expectField(2, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); if data.a != 17 { t.Errorf("int a = %v not 17", data.a) } @@ -665,17 +676,17 @@ func TestScalarDecInstructions(t *testing.T) { state := newDecState(signedResult); state.base = uintptr(unsafe.Pointer(&data)); expectField(0, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); instr.field = 1; instr.indir = 1; instr.offset = uintptr(unsafe.Offsetof(data.b)); expectField(1, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); instr.field = 2; instr.indir = 2; instr.offset = uintptr(unsafe.Offsetof(data.c)); expectField(2, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); if data.a != 17 { t.Errorf("int a = %v not 17", data.a) } @@ -694,17 +705,17 @@ func TestScalarDecInstructions(t *testing.T) { state := newDecState(unsignedResult); state.base = uintptr(unsafe.Pointer(&data)); expectField(0, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); instr.field = 1; instr.indir = 1; instr.offset = uintptr(unsafe.Offsetof(data.b)); expectField(1, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); instr.field = 2; instr.indir = 2; instr.offset = uintptr(unsafe.Offsetof(data.c)); expectField(2, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); if data.a != 17 { t.Errorf("int a = %v not 17", data.a) } @@ -723,17 +734,17 @@ func TestScalarDecInstructions(t *testing.T) { state := newDecState(signedResult); state.base = uintptr(unsafe.Pointer(&data)); expectField(0, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); instr.field = 1; instr.indir = 1; instr.offset = uintptr(unsafe.Offsetof(data.b)); expectField(1, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); instr.field = 2; instr.indir = 2; instr.offset = uintptr(unsafe.Offsetof(data.c)); expectField(2, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); if data.a != 17 { t.Errorf("int a = %v not 17", data.a) } @@ -752,17 +763,17 @@ func TestScalarDecInstructions(t *testing.T) { state := newDecState(unsignedResult); state.base = uintptr(unsafe.Pointer(&data)); expectField(0, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); instr.field = 1; instr.indir = 1; instr.offset = uintptr(unsafe.Offsetof(data.b)); expectField(1, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); instr.field = 2; instr.indir = 2; instr.offset = uintptr(unsafe.Offsetof(data.c)); expectField(2, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); if data.a != 17 { t.Errorf("int a = %v not 17", data.a) } @@ -781,17 +792,17 @@ func TestScalarDecInstructions(t *testing.T) { state := newDecState(signedResult); state.base = uintptr(unsafe.Pointer(&data)); expectField(0, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); instr.field = 1; instr.indir = 1; instr.offset = uintptr(unsafe.Offsetof(data.b)); expectField(1, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); instr.field = 2; instr.indir = 2; instr.offset = uintptr(unsafe.Offsetof(data.c)); expectField(2, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); if data.a != 17 { t.Errorf("int a = %v not 17", data.a) } @@ -810,17 +821,17 @@ func TestScalarDecInstructions(t *testing.T) { state := newDecState(unsignedResult); state.base = uintptr(unsafe.Pointer(&data)); expectField(0, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); instr.field = 1; instr.indir = 1; instr.offset = uintptr(unsafe.Offsetof(data.b)); expectField(1, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); instr.field = 2; instr.indir = 2; instr.offset = uintptr(unsafe.Offsetof(data.c)); expectField(2, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); if data.a != 17 { t.Errorf("int a = %v not 17", data.a) } @@ -839,17 +850,17 @@ func TestScalarDecInstructions(t *testing.T) { state := newDecState(floatResult); state.base = uintptr(unsafe.Pointer(&data)); expectField(0, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); instr.field = 1; instr.indir = 1; instr.offset = uintptr(unsafe.Offsetof(data.b)); expectField(1, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); instr.field = 2; instr.indir = 2; instr.offset = uintptr(unsafe.Offsetof(data.c)); expectField(2, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); if data.a != 17 { t.Errorf("int a = %v not 17", data.a) } @@ -868,17 +879,17 @@ func TestScalarDecInstructions(t *testing.T) { state := newDecState(floatResult); state.base = uintptr(unsafe.Pointer(&data)); expectField(0, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); instr.field = 1; instr.indir = 1; instr.offset = uintptr(unsafe.Offsetof(data.b)); expectField(1, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); instr.field = 2; instr.indir = 2; instr.offset = uintptr(unsafe.Offsetof(data.c)); expectField(2, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); if data.a != 17 { t.Errorf("int a = %v not 17", data.a) } @@ -897,17 +908,17 @@ func TestScalarDecInstructions(t *testing.T) { state := newDecState(floatResult); state.base = uintptr(unsafe.Pointer(&data)); expectField(0, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); instr.field = 1; instr.indir = 1; instr.offset = uintptr(unsafe.Offsetof(data.b)); expectField(1, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); instr.field = 2; instr.indir = 2; instr.offset = uintptr(unsafe.Offsetof(data.c)); expectField(2, state, t); - instr.op(instr, state); + instr.op(instr, state, decAddrOf(state, instr)); if data.a != 17 { t.Errorf("int a = %v not 17", data.a) } diff --git a/src/pkg/gob/decode.go b/src/pkg/gob/decode.go index 67c49d8a7d..4de04966a5 100644 --- a/src/pkg/gob/decode.go +++ b/src/pkg/gob/decode.go @@ -4,6 +4,9 @@ package gob +// TODO(rsc): When garbage collector changes, revisit +// the allocations in this file that use unsafe.Pointer. + import ( "gob"; "io"; @@ -57,9 +60,12 @@ func DecodeInt(state *DecState) int64 { return int64(x >> 1) } +type decInstr struct +type decOp func(i *decInstr, state *DecState, p unsafe.Pointer); + // The 'instructions' of the decoding machine type decInstr struct { - op func(i *decInstr, state *DecState); + op decOp; field int; // field number indir int; // how many pointer indirections to reach the value in the struct offset uintptr; // offset in the structure of the field to encode @@ -84,14 +90,10 @@ func decIndirect(p unsafe.Pointer, indir int) unsafe.Pointer { return p } -func decBool(i *decInstr, state *DecState) { - p := unsafe.Pointer(state.base+i.offset); +func decBool(i *decInstr, state *DecState, p unsafe.Pointer) { if i.indir > 0 { - if i.indir > 1 { - p = decIndirect(p, i.indir); - } if *(*unsafe.Pointer)(p) == nil { - *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int)); + *(*unsafe.Pointer)(p) = unsafe.Pointer(new(bool)); p = *(*unsafe.Pointer)(p); } } @@ -101,12 +103,8 @@ func decBool(i *decInstr, state *DecState) { } } -func decInt(i *decInstr, state *DecState) { - p := unsafe.Pointer(state.base+i.offset); +func decInt(i *decInstr, state *DecState, p unsafe.Pointer) { if i.indir > 0 { - if i.indir > 1 { - p = decIndirect(p, i.indir); - } if *(*unsafe.Pointer)(p) == nil { *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int)); p = *(*unsafe.Pointer)(p); @@ -118,14 +116,10 @@ func decInt(i *decInstr, state *DecState) { } } -func decUint(i *decInstr, state *DecState) { - p := unsafe.Pointer(state.base+i.offset); +func decUint(i *decInstr, state *DecState, p unsafe.Pointer) { if i.indir > 0 { - if i.indir > 1 { - p = decIndirect(p, i.indir); - } if *(*unsafe.Pointer)(p) == nil { - *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int)); + *(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint)); p = *(*unsafe.Pointer)(p); } } @@ -135,14 +129,10 @@ func decUint(i *decInstr, state *DecState) { } } -func decInt8(i *decInstr, state *DecState) { - p := unsafe.Pointer(state.base+i.offset); +func decInt8(i *decInstr, state *DecState, p unsafe.Pointer) { if i.indir > 0 { - if i.indir > 1 { - p = decIndirect(p, i.indir); - } if *(*unsafe.Pointer)(p) == nil { - *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int)); + *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int8)); p = *(*unsafe.Pointer)(p); } } @@ -152,14 +142,10 @@ func decInt8(i *decInstr, state *DecState) { } } -func decUint8(i *decInstr, state *DecState) { - p := unsafe.Pointer(state.base+i.offset); +func decUint8(i *decInstr, state *DecState, p unsafe.Pointer) { if i.indir > 0 { - if i.indir > 1 { - p = decIndirect(p, i.indir); - } if *(*unsafe.Pointer)(p) == nil { - *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int)); + *(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint8)); p = *(*unsafe.Pointer)(p); } } @@ -169,14 +155,10 @@ func decUint8(i *decInstr, state *DecState) { } } -func decInt16(i *decInstr, state *DecState) { - p := unsafe.Pointer(state.base+i.offset); +func decInt16(i *decInstr, state *DecState, p unsafe.Pointer) { if i.indir > 0 { - if i.indir > 1 { - p = decIndirect(p, i.indir); - } if *(*unsafe.Pointer)(p) == nil { - *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int)); + *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int16)); p = *(*unsafe.Pointer)(p); } } @@ -186,14 +168,10 @@ func decInt16(i *decInstr, state *DecState) { } } -func decUint16(i *decInstr, state *DecState) { - p := unsafe.Pointer(state.base+i.offset); +func decUint16(i *decInstr, state *DecState, p unsafe.Pointer) { if i.indir > 0 { - if i.indir > 1 { - p = decIndirect(p, i.indir); - } if *(*unsafe.Pointer)(p) == nil { - *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int)); + *(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint16)); p = *(*unsafe.Pointer)(p); } } @@ -203,14 +181,10 @@ func decUint16(i *decInstr, state *DecState) { } } -func decInt32(i *decInstr, state *DecState) { - p := unsafe.Pointer(state.base+i.offset); +func decInt32(i *decInstr, state *DecState, p unsafe.Pointer) { if i.indir > 0 { - if i.indir > 1 { - p = decIndirect(p, i.indir); - } if *(*unsafe.Pointer)(p) == nil { - *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int)); + *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int32)); p = *(*unsafe.Pointer)(p); } } @@ -220,14 +194,10 @@ func decInt32(i *decInstr, state *DecState) { } } -func decUint32(i *decInstr, state *DecState) { - p := unsafe.Pointer(state.base+i.offset); +func decUint32(i *decInstr, state *DecState, p unsafe.Pointer) { if i.indir > 0 { - if i.indir > 1 { - p = decIndirect(p, i.indir); - } if *(*unsafe.Pointer)(p) == nil { - *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int)); + *(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint32)); p = *(*unsafe.Pointer)(p); } } @@ -237,14 +207,10 @@ func decUint32(i *decInstr, state *DecState) { } } -func decInt64(i *decInstr, state *DecState) { - p := unsafe.Pointer(state.base+i.offset); +func decInt64(i *decInstr, state *DecState, p unsafe.Pointer) { if i.indir > 0 { - if i.indir > 1 { - p = decIndirect(p, i.indir); - } if *(*unsafe.Pointer)(p) == nil { - *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int)); + *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int64)); p = *(*unsafe.Pointer)(p); } } @@ -254,14 +220,10 @@ func decInt64(i *decInstr, state *DecState) { } } -func decUint64(i *decInstr, state *DecState) { - p := unsafe.Pointer(state.base+i.offset); +func decUint64(i *decInstr, state *DecState, p unsafe.Pointer) { if i.indir > 0 { - if i.indir > 1 { - p = decIndirect(p, i.indir); - } if *(*unsafe.Pointer)(p) == nil { - *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int)); + *(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint64)); p = *(*unsafe.Pointer)(p); } } @@ -286,14 +248,10 @@ func floatFromBits(u uint64) float64 { return math.Float64frombits(v); } -func decFloat(i *decInstr, state *DecState) { - p := unsafe.Pointer(state.base+i.offset); +func decFloat(i *decInstr, state *DecState, p unsafe.Pointer) { if i.indir > 0 { - if i.indir > 1 { - p = decIndirect(p, i.indir); - } if *(*unsafe.Pointer)(p) == nil { - *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int)); + *(*unsafe.Pointer)(p) = unsafe.Pointer(new(float)); p = *(*unsafe.Pointer)(p); } } @@ -303,14 +261,10 @@ func decFloat(i *decInstr, state *DecState) { } } -func decFloat32(i *decInstr, state *DecState) { - p := unsafe.Pointer(state.base+i.offset); +func decFloat32(i *decInstr, state *DecState, p unsafe.Pointer) { if i.indir > 0 { - if i.indir > 1 { - p = decIndirect(p, i.indir); - } if *(*unsafe.Pointer)(p) == nil { - *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int)); + *(*unsafe.Pointer)(p) = unsafe.Pointer(new(float32)); p = *(*unsafe.Pointer)(p); } } @@ -320,14 +274,10 @@ func decFloat32(i *decInstr, state *DecState) { } } -func decFloat64(i *decInstr, state *DecState) { - p := unsafe.Pointer(state.base+i.offset); +func decFloat64(i *decInstr, state *DecState, p unsafe.Pointer) { if i.indir > 0 { - if i.indir > 1 { - p = decIndirect(p, i.indir); - } if *(*unsafe.Pointer)(p) == nil { - *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int)); + *(*unsafe.Pointer)(p) = unsafe.Pointer(new(float64)); p = *(*unsafe.Pointer)(p); } } @@ -346,7 +296,7 @@ type decEngine struct { } var decEngineMap = make(map[reflect.Type] *decEngine) -var decOp = map[int] func(*decInstr, *DecState) { +var decOpMap = map[int] decOp { reflect.BoolKind: decBool, reflect.IntKind: decInt, reflect.Int8Kind: decInt8, @@ -386,7 +336,7 @@ func compileDec(rt reflect.Type, typ Type) *decEngine { ftyp = pt.Sub(); indir++; } - op, ok := decOp[ftyp.Kind()]; + op, ok := decOpMap[ftyp.Kind()]; if !ok { panicln("can't handle decode for type", ftyp.String()); } @@ -424,7 +374,11 @@ func (engine *decEngine) decode(r io.Reader, v reflect.Value) os.Error { panicln("TODO(r): need to handle unknown data"); } instr := &engine.instr[fieldnum]; - instr.op(instr, state); + p := unsafe.Pointer(state.base+instr.offset); + if instr.indir > 1 { + p = decIndirect(p, instr.indir); + } + instr.op(instr, state, p); state.fieldnum = fieldnum; } return state.err diff --git a/src/pkg/gob/encode.go b/src/pkg/gob/encode.go index 24cc5094ae..588e1fa7e2 100644 --- a/src/pkg/gob/encode.go +++ b/src/pkg/gob/encode.go @@ -60,9 +60,12 @@ func EncodeInt(state *EncState, i int64){ EncodeUint(state, uint64(x)) } +type encInstr struct +type encOp func(i *encInstr, state *EncState, p unsafe.Pointer) + // The 'instructions' of the encoding machine type encInstr struct { - op func(i *encInstr, state *EncState); + op encOp; field int; // field number indir int; // how many pointer indirections to reach the value in the struct offset uintptr; // offset in the structure of the field to encode @@ -84,13 +87,7 @@ func encIndirect(p unsafe.Pointer, indir int) unsafe.Pointer { return p } -func encBool(i *encInstr, state *EncState) { - p := unsafe.Pointer(state.base+i.offset); - if i.indir > 0 { - if p = encIndirect(p, i.indir); p == nil { - return - } - } +func encBool(i *encInstr, state *EncState, p unsafe.Pointer) { b := *(*bool)(p); if b { EncodeUint(state, uint64(i.field - state.fieldnum)); @@ -98,13 +95,7 @@ func encBool(i *encInstr, state *EncState) { } } -func encInt(i *encInstr, state *EncState) { - p := unsafe.Pointer(state.base+i.offset); - if i.indir > 0 { - if p = encIndirect(p, i.indir); p == nil { - return - } - } +func encInt(i *encInstr, state *EncState, p unsafe.Pointer) { v := int64(*(*int)(p)); if v != 0 { EncodeUint(state, uint64(i.field - state.fieldnum)); @@ -112,13 +103,7 @@ func encInt(i *encInstr, state *EncState) { } } -func encUint(i *encInstr, state *EncState) { - p := unsafe.Pointer(state.base+i.offset); - if i.indir > 0 { - if p = encIndirect(p, i.indir); p == nil { - return - } - } +func encUint(i *encInstr, state *EncState, p unsafe.Pointer) { v := uint64(*(*uint)(p)); if v != 0 { EncodeUint(state, uint64(i.field - state.fieldnum)); @@ -126,13 +111,7 @@ func encUint(i *encInstr, state *EncState) { } } -func encInt8(i *encInstr, state *EncState) { - p := unsafe.Pointer(state.base+i.offset); - if i.indir > 0 { - if p = encIndirect(p, i.indir); p == nil { - return - } - } +func encInt8(i *encInstr, state *EncState, p unsafe.Pointer) { v := int64(*(*int8)(p)); if v != 0 { EncodeUint(state, uint64(i.field - state.fieldnum)); @@ -140,13 +119,7 @@ func encInt8(i *encInstr, state *EncState) { } } -func encUint8(i *encInstr, state *EncState) { - p := unsafe.Pointer(state.base+i.offset); - if i.indir > 0 { - if p = encIndirect(p, i.indir); p == nil { - return - } - } +func encUint8(i *encInstr, state *EncState, p unsafe.Pointer) { v := uint64(*(*uint8)(p)); if v != 0 { EncodeUint(state, uint64(i.field - state.fieldnum)); @@ -154,13 +127,7 @@ func encUint8(i *encInstr, state *EncState) { } } -func encInt16(i *encInstr, state *EncState) { - p := unsafe.Pointer(state.base+i.offset); - if i.indir > 0 { - if p = encIndirect(p, i.indir); p == nil { - return - } - } +func encInt16(i *encInstr, state *EncState, p unsafe.Pointer) { v := int64(*(*int16)(p)); if v != 0 { EncodeUint(state, uint64(i.field - state.fieldnum)); @@ -168,13 +135,7 @@ func encInt16(i *encInstr, state *EncState) { } } -func encUint16(i *encInstr, state *EncState) { - p := unsafe.Pointer(state.base+i.offset); - if i.indir > 0 { - if p = encIndirect(p, i.indir); p == nil { - return - } - } +func encUint16(i *encInstr, state *EncState, p unsafe.Pointer) { v := uint64(*(*uint16)(p)); if v != 0 { EncodeUint(state, uint64(i.field - state.fieldnum)); @@ -182,13 +143,7 @@ func encUint16(i *encInstr, state *EncState) { } } -func encInt32(i *encInstr, state *EncState) { - p := unsafe.Pointer(state.base+i.offset); - if i.indir > 0 { - if p = encIndirect(p, i.indir); p == nil { - return - } - } +func encInt32(i *encInstr, state *EncState, p unsafe.Pointer) { v := int64(*(*int32)(p)); if v != 0 { EncodeUint(state, uint64(i.field - state.fieldnum)); @@ -196,13 +151,7 @@ func encInt32(i *encInstr, state *EncState) { } } -func encUint32(i *encInstr, state *EncState) { - p := unsafe.Pointer(state.base+i.offset); - if i.indir > 0 { - if p = encIndirect(p, i.indir); p == nil { - return - } - } +func encUint32(i *encInstr, state *EncState, p unsafe.Pointer) { v := uint64(*(*uint32)(p)); if v != 0 { EncodeUint(state, uint64(i.field - state.fieldnum)); @@ -210,13 +159,7 @@ func encUint32(i *encInstr, state *EncState) { } } -func encInt64(i *encInstr, state *EncState) { - p := unsafe.Pointer(state.base+i.offset); - if i.indir > 0 { - if p = encIndirect(p, i.indir); p == nil { - return - } - } +func encInt64(i *encInstr, state *EncState, p unsafe.Pointer) { v := *(*int64)(p); if v != 0 { EncodeUint(state, uint64(i.field - state.fieldnum)); @@ -224,13 +167,7 @@ func encInt64(i *encInstr, state *EncState) { } } -func encUint64(i *encInstr, state *EncState) { - p := unsafe.Pointer(state.base+i.offset); - if i.indir > 0 { - if p = encIndirect(p, i.indir); p == nil { - return - } - } +func encUint64(i *encInstr, state *EncState, p unsafe.Pointer) { v := *(*uint64)(p); if v != 0 { EncodeUint(state, uint64(i.field - state.fieldnum)); @@ -254,13 +191,7 @@ func floatBits(f float64) uint64 { return v; } -func encFloat(i *encInstr, state *EncState) { - p := unsafe.Pointer(state.base+i.offset); - if i.indir > 0 { - if p = encIndirect(p, i.indir); p == nil { - return - } - } +func encFloat(i *encInstr, state *EncState, p unsafe.Pointer) { f := float(*(*float)(p)); if f != 0 { v := floatBits(float64(f)); @@ -269,13 +200,7 @@ func encFloat(i *encInstr, state *EncState) { } } -func encFloat32(i *encInstr, state *EncState) { - p := unsafe.Pointer(state.base+i.offset); - if i.indir > 0 { - if p = encIndirect(p, i.indir); p == nil { - return - } - } +func encFloat32(i *encInstr, state *EncState, p unsafe.Pointer) { f := float32(*(*float32)(p)); if f != 0 { v := floatBits(float64(f)); @@ -284,13 +209,7 @@ func encFloat32(i *encInstr, state *EncState) { } } -func encFloat64(i *encInstr, state *EncState) { - p := unsafe.Pointer(state.base+i.offset); - if i.indir > 0 { - if p = encIndirect(p, i.indir); p == nil { - return - } - } +func encFloat64(i *encInstr, state *EncState, p unsafe.Pointer) { f := *(*float64)(p); if f != 0 { v := floatBits(f); @@ -300,7 +219,7 @@ func encFloat64(i *encInstr, state *EncState) { } // The end of a struct is marked by a delta field number of 0. -func encStructTerminator(i *encInstr, state *EncState) { +func encStructTerminator(i *encInstr, state *EncState, p unsafe.Pointer) { EncodeUint(state, 0); } @@ -313,7 +232,7 @@ type encEngine struct { } var encEngineMap = make(map[reflect.Type] *encEngine) -var encOp = map[int] func(*encInstr, *EncState) { +var encOpMap = map[int] encOp { reflect.BoolKind: encBool, reflect.IntKind: encInt, reflect.Int8Kind: encInt8, @@ -352,7 +271,7 @@ func compileEnc(rt reflect.Type, typ Type) *encEngine { ftyp = pt.Sub(); indir++; } - op, ok := encOp[ftyp.Kind()]; + op, ok := encOpMap[ftyp.Kind()]; if !ok { panicln("encode can't handle type", ftyp.String()); } @@ -383,7 +302,14 @@ func (engine *encEngine) encode(w io.Writer, v reflect.Value) os.Error { state.fieldnum = -1; for i := 0; i < len(engine.instr); i++ { instr := &engine.instr[i]; - instr.op(instr, state); + p := unsafe.Pointer(state.base+instr.offset); + if instr.indir > 0 { + if p = encIndirect(p, instr.indir); p == nil { + state.fieldnum = i; + continue + } + } + instr.op(instr, state, p); if state.err != nil { break } -- 2.48.1