]> Cypherpunks repositories - gostls13.git/commitdiff
move dereference code out of the ops and into the interpreter loops.
authorRob Pike <r@golang.org>
Thu, 2 Jul 2009 06:04:27 +0000 (23:04 -0700)
committerRob Pike <r@golang.org>
Thu, 2 Jul 2009 06:04:27 +0000 (23:04 -0700)
R=rsc
DELTA=574  (40 added, 149 deleted, 385 changed)
OCL=31017
CL=31019

src/pkg/gob/codec_test.go
src/pkg/gob/decode.go
src/pkg/gob/encode.go

index c976adeb347cd59b3b427db6b95fd0db9f36a3b9..3647589031a771e4b973eda317f90804c177e95a 100644 (file)
@@ -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)
                }
index 67c49d8a7d63e19ab61768f75c5e91cfba0b68f7..4de04966a5ad5c2b240fdbf51e3afc3ef7721668 100644 (file)
@@ -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
index 24cc5094aeced943483b4afcd438a753bfb01707..588e1fa7e272a88f0926637265b29cdf91fed9be 100644 (file)
@@ -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
                }