Commit b9689433 authored by Rob Pike's avatar Rob Pike

scalar decoders

R=rsc
DELTA=897  (728 added, 14 deleted, 155 changed)
OCL=30955
CL=30955
parent 79b2cf92
This diff is collapsed.
...@@ -6,6 +6,7 @@ package gob ...@@ -6,6 +6,7 @@ package gob
import ( import (
"io"; "io";
"math";
"os"; "os";
"unsafe"; "unsafe";
) )
...@@ -52,3 +53,283 @@ func DecodeInt(state *DecState) int64 { ...@@ -52,3 +53,283 @@ func DecodeInt(state *DecState) int64 {
} }
return int64(x >> 1) return int64(x >> 1)
} }
// The 'instructions' of the decoding machine
type decInstr struct {
op func(i *decInstr, state *DecState);
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
}
// Since the encoder writes no zeros, if we arrive at a decoder we have
// a value to extract and store. The field number has already been read
// (it's how we knew to call this decoder).
// Each decoder is responsible for handling any indirections associated
// with the data structure. If any pointer so reached is nil, allocation must
// be done.
// Walk the pointer hierarchy, allocating if we find a nil. Stop one before the end.
func decIndirect(p unsafe.Pointer, indir int) unsafe.Pointer {
for ; indir > 1; indir-- {
if *(*unsafe.Pointer)(p) == nil {
// Allocation required
*(*unsafe.Pointer)(p) = unsafe.Pointer(new(unsafe.Pointer));
}
p = *(*unsafe.Pointer)(p);
}
return p
}
func decBool(i *decInstr, state *DecState) {
p := unsafe.Pointer(state.base+i.offset);
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);
}
}
v := int(DecodeInt(state));
if state.err == nil {
*(*bool)(p) = v != 0;
}
}
func decInt(i *decInstr, state *DecState) {
p := unsafe.Pointer(state.base+i.offset);
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);
}
}
v := int(DecodeInt(state));
if state.err == nil {
*(*int)(p) = v;
}
}
func decUint(i *decInstr, state *DecState) {
p := unsafe.Pointer(state.base+i.offset);
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);
}
}
v := uint(DecodeUint(state));
if state.err == nil {
*(*uint)(p) = v;
}
}
func decInt8(i *decInstr, state *DecState) {
p := unsafe.Pointer(state.base+i.offset);
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);
}
}
v := int8(DecodeInt(state));
if state.err == nil {
*(*int8)(p) = v;
}
}
func decUint8(i *decInstr, state *DecState) {
p := unsafe.Pointer(state.base+i.offset);
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);
}
}
v := uint8(DecodeUint(state));
if state.err == nil {
*(*uint8)(p) = v;
}
}
func decInt16(i *decInstr, state *DecState) {
p := unsafe.Pointer(state.base+i.offset);
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);
}
}
v := int16(DecodeInt(state));
if state.err == nil {
*(*int16)(p) = v;
}
}
func decUint16(i *decInstr, state *DecState) {
p := unsafe.Pointer(state.base+i.offset);
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);
}
}
v := uint16(DecodeUint(state));
if state.err == nil {
*(*uint16)(p) = v;
}
}
func decInt32(i *decInstr, state *DecState) {
p := unsafe.Pointer(state.base+i.offset);
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);
}
}
v := int32(DecodeInt(state));
if state.err == nil {
*(*int32)(p) = v;
}
}
func decUint32(i *decInstr, state *DecState) {
p := unsafe.Pointer(state.base+i.offset);
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);
}
}
v := uint32(DecodeUint(state));
if state.err == nil {
*(*uint32)(p) = v;
}
}
func decInt64(i *decInstr, state *DecState) {
p := unsafe.Pointer(state.base+i.offset);
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);
}
}
v := int64(DecodeInt(state));
if state.err == nil {
*(*int64)(p) = v;
}
}
func decUint64(i *decInstr, state *DecState) {
p := unsafe.Pointer(state.base+i.offset);
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);
}
}
v := uint64(DecodeUint(state));
if state.err == nil {
*(*uint64)(p) = v;
}
}
// Floating-point numbers are transmitted as uint64s holding the bits
// of the underlying representation. They are sent byte-reversed, with
// the exponent end coming out first, so integer floating point numbers
// (for example) transmit more compactly. This routine does the
// unswizzling.
func floatFromBits(u uint64) float64 {
var v uint64;
for i := 0; i < 8; i++ {
v <<= 8;
v |= u & 0xFF;
u >>= 8;
}
return math.Float64frombits(v);
}
func decFloat(i *decInstr, state *DecState) {
p := unsafe.Pointer(state.base+i.offset);
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);
}
}
v := float(floatFromBits(uint64(DecodeUint(state))));
if state.err == nil {
*(*float)(p) = v;
}
}
func decFloat32(i *decInstr, state *DecState) {
p := unsafe.Pointer(state.base+i.offset);
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);
}
}
v := float32(floatFromBits(uint64(DecodeUint(state))));
if state.err == nil {
*(*float32)(p) = v;
}
}
func decFloat64(i *decInstr, state *DecState) {
p := unsafe.Pointer(state.base+i.offset);
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);
}
}
v := floatFromBits(uint64(DecodeUint(state)));
if state.err == nil {
*(*float64)(p) = v;
}
}
...@@ -67,11 +67,20 @@ type encInstr struct { ...@@ -67,11 +67,20 @@ type encInstr struct {
// Otherwise, the output (for a scalar) is the field number, as an encoded integer, // Otherwise, the output (for a scalar) is the field number, as an encoded integer,
// followed by the field data in its appropriate format. // followed by the field data in its appropriate format.
func encBool(i *encInstr, state *EncState) { func encIndirect(p unsafe.Pointer, indir int) unsafe.Pointer {
p := unsafe.Pointer(state.base+i.offset); for ; indir > 0; indir-- {
for indir := i.indir; indir > 0; indir-- {
p = *(*unsafe.Pointer)(p); p = *(*unsafe.Pointer)(p);
if p == nil { if p == nil {
return unsafe.Pointer(nil)
}
}
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 return
} }
} }
...@@ -84,9 +93,8 @@ func encBool(i *encInstr, state *EncState) { ...@@ -84,9 +93,8 @@ func encBool(i *encInstr, state *EncState) {
func encInt(i *encInstr, state *EncState) { func encInt(i *encInstr, state *EncState) {
p := unsafe.Pointer(state.base+i.offset); p := unsafe.Pointer(state.base+i.offset);
for indir := i.indir; indir > 0; indir-- { if i.indir > 0 {
p = *(*unsafe.Pointer)(p); if p = encIndirect(p, i.indir); p == nil {
if p == nil {
return return
} }
} }
...@@ -99,9 +107,8 @@ func encInt(i *encInstr, state *EncState) { ...@@ -99,9 +107,8 @@ func encInt(i *encInstr, state *EncState) {
func encUint(i *encInstr, state *EncState) { func encUint(i *encInstr, state *EncState) {
p := unsafe.Pointer(state.base+i.offset); p := unsafe.Pointer(state.base+i.offset);
for indir := i.indir; indir > 0; indir-- { if i.indir > 0 {
p = *(*unsafe.Pointer)(p); if p = encIndirect(p, i.indir); p == nil {
if p == nil {
return return
} }
} }
...@@ -114,9 +121,8 @@ func encUint(i *encInstr, state *EncState) { ...@@ -114,9 +121,8 @@ func encUint(i *encInstr, state *EncState) {
func encInt8(i *encInstr, state *EncState) { func encInt8(i *encInstr, state *EncState) {
p := unsafe.Pointer(state.base+i.offset); p := unsafe.Pointer(state.base+i.offset);
for indir := i.indir; indir > 0; indir-- { if i.indir > 0 {
p = *(*unsafe.Pointer)(p); if p = encIndirect(p, i.indir); p == nil {
if p == nil {
return return
} }
} }
...@@ -129,9 +135,8 @@ func encInt8(i *encInstr, state *EncState) { ...@@ -129,9 +135,8 @@ func encInt8(i *encInstr, state *EncState) {
func encUint8(i *encInstr, state *EncState) { func encUint8(i *encInstr, state *EncState) {
p := unsafe.Pointer(state.base+i.offset); p := unsafe.Pointer(state.base+i.offset);
for indir := i.indir; indir > 0; indir-- { if i.indir > 0 {
p = *(*unsafe.Pointer)(p); if p = encIndirect(p, i.indir); p == nil {
if p == nil {
return return
} }
} }
...@@ -144,9 +149,8 @@ func encUint8(i *encInstr, state *EncState) { ...@@ -144,9 +149,8 @@ func encUint8(i *encInstr, state *EncState) {
func encInt16(i *encInstr, state *EncState) { func encInt16(i *encInstr, state *EncState) {
p := unsafe.Pointer(state.base+i.offset); p := unsafe.Pointer(state.base+i.offset);
for indir := i.indir; indir > 0; indir-- { if i.indir > 0 {
p = *(*unsafe.Pointer)(p); if p = encIndirect(p, i.indir); p == nil {
if p == nil {
return return
} }
} }
...@@ -159,9 +163,8 @@ func encInt16(i *encInstr, state *EncState) { ...@@ -159,9 +163,8 @@ func encInt16(i *encInstr, state *EncState) {
func encUint16(i *encInstr, state *EncState) { func encUint16(i *encInstr, state *EncState) {
p := unsafe.Pointer(state.base+i.offset); p := unsafe.Pointer(state.base+i.offset);
for indir := i.indir; indir > 0; indir-- { if i.indir > 0 {
p = *(*unsafe.Pointer)(p); if p = encIndirect(p, i.indir); p == nil {
if p == nil {
return return
} }
} }
...@@ -174,9 +177,8 @@ func encUint16(i *encInstr, state *EncState) { ...@@ -174,9 +177,8 @@ func encUint16(i *encInstr, state *EncState) {
func encInt32(i *encInstr, state *EncState) { func encInt32(i *encInstr, state *EncState) {
p := unsafe.Pointer(state.base+i.offset); p := unsafe.Pointer(state.base+i.offset);
for indir := i.indir; indir > 0; indir-- { if i.indir > 0 {
p = *(*unsafe.Pointer)(p); if p = encIndirect(p, i.indir); p == nil {
if p == nil {
return return
} }
} }
...@@ -189,9 +191,8 @@ func encInt32(i *encInstr, state *EncState) { ...@@ -189,9 +191,8 @@ func encInt32(i *encInstr, state *EncState) {
func encUint32(i *encInstr, state *EncState) { func encUint32(i *encInstr, state *EncState) {
p := unsafe.Pointer(state.base+i.offset); p := unsafe.Pointer(state.base+i.offset);
for indir := i.indir; indir > 0; indir-- { if i.indir > 0 {
p = *(*unsafe.Pointer)(p); if p = encIndirect(p, i.indir); p == nil {
if p == nil {
return return
} }
} }
...@@ -204,9 +205,8 @@ func encUint32(i *encInstr, state *EncState) { ...@@ -204,9 +205,8 @@ func encUint32(i *encInstr, state *EncState) {
func encInt64(i *encInstr, state *EncState) { func encInt64(i *encInstr, state *EncState) {
p := unsafe.Pointer(state.base+i.offset); p := unsafe.Pointer(state.base+i.offset);
for indir := i.indir; indir > 0; indir-- { if i.indir > 0 {
p = *(*unsafe.Pointer)(p); if p = encIndirect(p, i.indir); p == nil {
if p == nil {
return return
} }
} }
...@@ -219,9 +219,8 @@ func encInt64(i *encInstr, state *EncState) { ...@@ -219,9 +219,8 @@ func encInt64(i *encInstr, state *EncState) {
func encUint64(i *encInstr, state *EncState) { func encUint64(i *encInstr, state *EncState) {
p := unsafe.Pointer(state.base+i.offset); p := unsafe.Pointer(state.base+i.offset);
for indir := i.indir; indir > 0; indir-- { if i.indir > 0 {
p = *(*unsafe.Pointer)(p); if p = encIndirect(p, i.indir); p == nil {
if p == nil {
return return
} }
} }
...@@ -250,9 +249,8 @@ func floatBits(f float64) uint64 { ...@@ -250,9 +249,8 @@ func floatBits(f float64) uint64 {
func encFloat(i *encInstr, state *EncState) { func encFloat(i *encInstr, state *EncState) {
p := unsafe.Pointer(state.base+i.offset); p := unsafe.Pointer(state.base+i.offset);
for indir := i.indir; indir > 0; indir-- { if i.indir > 0 {
p = *(*unsafe.Pointer)(p); if p = encIndirect(p, i.indir); p == nil {
if p == nil {
return return
} }
} }
...@@ -266,9 +264,8 @@ func encFloat(i *encInstr, state *EncState) { ...@@ -266,9 +264,8 @@ func encFloat(i *encInstr, state *EncState) {
func encFloat32(i *encInstr, state *EncState) { func encFloat32(i *encInstr, state *EncState) {
p := unsafe.Pointer(state.base+i.offset); p := unsafe.Pointer(state.base+i.offset);
for indir := i.indir; indir > 0; indir-- { if i.indir > 0 {
p = *(*unsafe.Pointer)(p); if p = encIndirect(p, i.indir); p == nil {
if p == nil {
return return
} }
} }
...@@ -282,9 +279,8 @@ func encFloat32(i *encInstr, state *EncState) { ...@@ -282,9 +279,8 @@ func encFloat32(i *encInstr, state *EncState) {
func encFloat64(i *encInstr, state *EncState) { func encFloat64(i *encInstr, state *EncState) {
p := unsafe.Pointer(state.base+i.offset); p := unsafe.Pointer(state.base+i.offset);
for indir := i.indir; indir > 0; indir-- { if i.indir > 0 {
p = *(*unsafe.Pointer)(p); if p = encIndirect(p, i.indir); p == nil {
if p == nil {
return return
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment