1
0
mirror of https://github.com/golang/go synced 2024-09-25 01:20:13 -06:00

encoding/gob: consistently use unsafe.Pointer for pointer values

Fixes #5621.

R=golang-dev, cshapiro, r, fullung
CC=golang-dev
https://golang.org/cl/9988043
This commit is contained in:
Ian Lance Taylor 2013-06-04 06:20:57 -07:00
parent 2c0b00744f
commit 941db1ed39
2 changed files with 38 additions and 39 deletions

View File

@ -450,11 +450,11 @@ type decEngine struct {
// allocate makes sure storage is available for an object of underlying type rtyp // allocate makes sure storage is available for an object of underlying type rtyp
// that is indir levels of indirection through p. // that is indir levels of indirection through p.
func allocate(rtyp reflect.Type, p uintptr, indir int) uintptr { func allocate(rtyp reflect.Type, p unsafe.Pointer, indir int) unsafe.Pointer {
if indir == 0 { if indir == 0 {
return p return p
} }
up := unsafe.Pointer(p) up := p
if indir > 1 { if indir > 1 {
up = decIndirect(up, indir) up = decIndirect(up, indir)
} }
@ -462,13 +462,13 @@ func allocate(rtyp reflect.Type, p uintptr, indir int) uintptr {
// Allocate object. // Allocate object.
*(*unsafe.Pointer)(up) = unsafe.Pointer(reflect.New(rtyp).Pointer()) *(*unsafe.Pointer)(up) = unsafe.Pointer(reflect.New(rtyp).Pointer())
} }
return *(*uintptr)(up) return *(*unsafe.Pointer)(up)
} }
// decodeSingle decodes a top-level value that is not a struct and stores it through p. // decodeSingle decodes a top-level value that is not a struct and stores it through p.
// Such values are preceded by a zero, making them have the memory layout of a // Such values are preceded by a zero, making them have the memory layout of a
// struct field (although with an illegal field number). // struct field (although with an illegal field number).
func (dec *Decoder) decodeSingle(engine *decEngine, ut *userTypeInfo, basep uintptr) { func (dec *Decoder) decodeSingle(engine *decEngine, ut *userTypeInfo, basep unsafe.Pointer) {
state := dec.newDecoderState(&dec.buf) state := dec.newDecoderState(&dec.buf)
state.fieldnum = singletonField state.fieldnum = singletonField
delta := int(state.decodeUint()) delta := int(state.decodeUint())
@ -479,7 +479,7 @@ func (dec *Decoder) decodeSingle(engine *decEngine, ut *userTypeInfo, basep uint
if instr.indir != ut.indir { if instr.indir != ut.indir {
errorf("internal error: inconsistent indirection instr %d ut %d", instr.indir, ut.indir) errorf("internal error: inconsistent indirection instr %d ut %d", instr.indir, ut.indir)
} }
ptr := unsafe.Pointer(basep) // offset will be zero ptr := basep // offset will be zero
if instr.indir > 1 { if instr.indir > 1 {
ptr = decIndirect(ptr, instr.indir) ptr = decIndirect(ptr, instr.indir)
} }
@ -492,7 +492,7 @@ func (dec *Decoder) decodeSingle(engine *decEngine, ut *userTypeInfo, basep uint
// differ from ut.indir, which was computed when the engine was built. // differ from ut.indir, which was computed when the engine was built.
// This state cannot arise for decodeSingle, which is called directly // This state cannot arise for decodeSingle, which is called directly
// from the user's value, not from the innards of an engine. // from the user's value, not from the innards of an engine.
func (dec *Decoder) decodeStruct(engine *decEngine, ut *userTypeInfo, p uintptr, indir int) { func (dec *Decoder) decodeStruct(engine *decEngine, ut *userTypeInfo, p unsafe.Pointer, indir int) {
p = allocate(ut.base, p, indir) p = allocate(ut.base, p, indir)
state := dec.newDecoderState(&dec.buf) state := dec.newDecoderState(&dec.buf)
state.fieldnum = -1 state.fieldnum = -1
@ -511,7 +511,7 @@ func (dec *Decoder) decodeStruct(engine *decEngine, ut *userTypeInfo, p uintptr,
break break
} }
instr := &engine.instr[fieldnum] instr := &engine.instr[fieldnum]
p := unsafe.Pointer(basep + instr.offset) p := unsafe.Pointer(uintptr(basep) + instr.offset)
if instr.indir > 1 { if instr.indir > 1 {
p = decIndirect(p, instr.indir) p = decIndirect(p, instr.indir)
} }
@ -559,25 +559,25 @@ func (dec *Decoder) ignoreSingle(engine *decEngine) {
} }
// decodeArrayHelper does the work for decoding arrays and slices. // decodeArrayHelper does the work for decoding arrays and slices.
func (dec *Decoder) decodeArrayHelper(state *decoderState, p uintptr, elemOp decOp, elemWid uintptr, length, elemIndir int, ovfl error) { func (dec *Decoder) decodeArrayHelper(state *decoderState, p unsafe.Pointer, elemOp decOp, elemWid uintptr, length, elemIndir int, ovfl error) {
instr := &decInstr{elemOp, 0, elemIndir, 0, ovfl} instr := &decInstr{elemOp, 0, elemIndir, 0, ovfl}
for i := 0; i < length; i++ { for i := 0; i < length; i++ {
if state.b.Len() == 0 { if state.b.Len() == 0 {
errorf("decoding array or slice: length exceeds input size (%d elements)", length) errorf("decoding array or slice: length exceeds input size (%d elements)", length)
} }
up := unsafe.Pointer(p) up := p
if elemIndir > 1 { if elemIndir > 1 {
up = decIndirect(up, elemIndir) up = decIndirect(up, elemIndir)
} }
elemOp(instr, state, up) elemOp(instr, state, up)
p += uintptr(elemWid) p = unsafe.Pointer(uintptr(p) + elemWid)
} }
} }
// decodeArray decodes an array and stores it through p, that is, p points to the zeroth element. // decodeArray decodes an array and stores it through p, that is, p points to the zeroth element.
// The length is an unsigned integer preceding the elements. Even though the length is redundant // The length is an unsigned integer preceding the elements. Even though the length is redundant
// (it's part of the type), it's a useful check and is included in the encoding. // (it's part of the type), it's a useful check and is included in the encoding.
func (dec *Decoder) decodeArray(atyp reflect.Type, state *decoderState, p uintptr, elemOp decOp, elemWid uintptr, length, indir, elemIndir int, ovfl error) { func (dec *Decoder) decodeArray(atyp reflect.Type, state *decoderState, p unsafe.Pointer, elemOp decOp, elemWid uintptr, length, indir, elemIndir int, ovfl error) {
if indir > 0 { if indir > 0 {
p = allocate(atyp, p, 1) // All but the last level has been allocated by dec.Indirect p = allocate(atyp, p, 1) // All but the last level has been allocated by dec.Indirect
} }
@ -591,7 +591,7 @@ func (dec *Decoder) decodeArray(atyp reflect.Type, state *decoderState, p uintpt
// unlike the other items we can't use a pointer directly. // unlike the other items we can't use a pointer directly.
func decodeIntoValue(state *decoderState, op decOp, indir int, v reflect.Value, ovfl error) reflect.Value { func decodeIntoValue(state *decoderState, op decOp, indir int, v reflect.Value, ovfl error) reflect.Value {
instr := &decInstr{op, 0, indir, 0, ovfl} instr := &decInstr{op, 0, indir, 0, ovfl}
up := unsafe.Pointer(unsafeAddr(v)) up := unsafeAddr(v)
if indir > 1 { if indir > 1 {
up = decIndirect(up, indir) up = decIndirect(up, indir)
} }
@ -603,7 +603,7 @@ func decodeIntoValue(state *decoderState, op decOp, indir int, v reflect.Value,
// Maps are encoded as a length followed by key:value pairs. // Maps are encoded as a length followed by key:value pairs.
// Because the internals of maps are not visible to us, we must // Because the internals of maps are not visible to us, we must
// use reflection rather than pointer magic. // use reflection rather than pointer magic.
func (dec *Decoder) decodeMap(mtyp reflect.Type, state *decoderState, p uintptr, keyOp, elemOp decOp, indir, keyIndir, elemIndir int, ovfl error) { func (dec *Decoder) decodeMap(mtyp reflect.Type, state *decoderState, p unsafe.Pointer, keyOp, elemOp decOp, indir, keyIndir, elemIndir int, ovfl error) {
if indir > 0 { if indir > 0 {
p = allocate(mtyp, p, 1) // All but the last level has been allocated by dec.Indirect p = allocate(mtyp, p, 1) // All but the last level has been allocated by dec.Indirect
} }
@ -673,7 +673,7 @@ func (dec *Decoder) decodeSlice(atyp reflect.Type, state *decoderState, p uintpt
hdrp.Cap = n hdrp.Cap = n
} }
hdrp.Len = n hdrp.Len = n
dec.decodeArrayHelper(state, hdrp.Data, elemOp, elemWid, n, elemIndir, ovfl) dec.decodeArrayHelper(state, unsafe.Pointer(hdrp.Data), elemOp, elemWid, n, elemIndir, ovfl)
} }
// ignoreSlice skips over the data for a slice value with no destination. // ignoreSlice skips over the data for a slice value with no destination.
@ -693,7 +693,7 @@ func setInterfaceValue(ivalue reflect.Value, value reflect.Value) {
// decodeInterface decodes an interface value and stores it through p. // decodeInterface decodes an interface value and stores it through p.
// Interfaces are encoded as the name of a concrete type followed by a value. // Interfaces are encoded as the name of a concrete type followed by a value.
// If the name is empty, the value is nil and no value is sent. // If the name is empty, the value is nil and no value is sent.
func (dec *Decoder) decodeInterface(ityp reflect.Type, state *decoderState, p uintptr, indir int) { func (dec *Decoder) decodeInterface(ityp reflect.Type, state *decoderState, p unsafe.Pointer, indir int) {
// Create a writable interface reflect.Value. We need one even for the nil case. // Create a writable interface reflect.Value. We need one even for the nil case.
ivalue := allocValue(ityp) ivalue := allocValue(ityp)
// Read the name of the concrete type. // Read the name of the concrete type.
@ -850,7 +850,7 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg
elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name, inProgress) elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name, inProgress)
ovfl := overflow(name) ovfl := overflow(name)
op = func(i *decInstr, state *decoderState, p unsafe.Pointer) { op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
state.dec.decodeArray(t, state, uintptr(p), *elemOp, t.Elem().Size(), t.Len(), i.indir, elemIndir, ovfl) state.dec.decodeArray(t, state, p, *elemOp, t.Elem().Size(), t.Len(), i.indir, elemIndir, ovfl)
} }
case reflect.Map: case reflect.Map:
@ -860,8 +860,7 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg
elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), "element of "+name, inProgress) elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), "element of "+name, inProgress)
ovfl := overflow(name) ovfl := overflow(name)
op = func(i *decInstr, state *decoderState, p unsafe.Pointer) { op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
up := unsafe.Pointer(p) state.dec.decodeMap(t, state, p, *keyOp, *elemOp, i.indir, keyIndir, elemIndir, ovfl)
state.dec.decodeMap(t, state, uintptr(up), *keyOp, *elemOp, i.indir, keyIndir, elemIndir, ovfl)
} }
case reflect.Slice: case reflect.Slice:
@ -890,11 +889,11 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg
} }
op = func(i *decInstr, state *decoderState, p unsafe.Pointer) { op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
// indirect through enginePtr to delay evaluation for recursive structs. // indirect through enginePtr to delay evaluation for recursive structs.
dec.decodeStruct(*enginePtr, userType(typ), uintptr(p), i.indir) dec.decodeStruct(*enginePtr, userType(typ), p, i.indir)
} }
case reflect.Interface: case reflect.Interface:
op = func(i *decInstr, state *decoderState, p unsafe.Pointer) { op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
state.dec.decodeInterface(t, state, uintptr(p), i.indir) state.dec.decodeInterface(t, state, p, i.indir)
} }
} }
} }
@ -1229,9 +1228,9 @@ func (dec *Decoder) decodeValue(wireId typeId, val reflect.Value) {
name := base.Name() name := base.Name()
errorf("type mismatch: no fields matched compiling decoder for %s", name) errorf("type mismatch: no fields matched compiling decoder for %s", name)
} }
dec.decodeStruct(engine, ut, uintptr(unsafeAddr(val)), ut.indir) dec.decodeStruct(engine, ut, unsafeAddr(val), ut.indir)
} else { } else {
dec.decodeSingle(engine, ut, uintptr(unsafeAddr(val))) dec.decodeSingle(engine, ut, unsafeAddr(val))
} }
} }
@ -1283,13 +1282,13 @@ func init() {
// into existing structs or slices cannot be addressed, // into existing structs or slices cannot be addressed,
// so simulate it by returning a pointer to a copy. // so simulate it by returning a pointer to a copy.
// Each call allocates once. // Each call allocates once.
func unsafeAddr(v reflect.Value) uintptr { func unsafeAddr(v reflect.Value) unsafe.Pointer {
if v.CanAddr() { if v.CanAddr() {
return v.UnsafeAddr() return unsafe.Pointer(v.UnsafeAddr())
} }
x := reflect.New(v.Type()).Elem() x := reflect.New(v.Type()).Elem()
x.Set(v) x.Set(v)
return x.UnsafeAddr() return unsafe.Pointer(x.UnsafeAddr())
} }
// Gob depends on being able to take the address // Gob depends on being able to take the address

View File

@ -338,14 +338,14 @@ type encEngine struct {
const singletonField = 0 const singletonField = 0
// encodeSingle encodes a single top-level non-struct value. // encodeSingle encodes a single top-level non-struct value.
func (enc *Encoder) encodeSingle(b *bytes.Buffer, engine *encEngine, basep uintptr) { func (enc *Encoder) encodeSingle(b *bytes.Buffer, engine *encEngine, basep unsafe.Pointer) {
state := enc.newEncoderState(b) state := enc.newEncoderState(b)
state.fieldnum = singletonField state.fieldnum = singletonField
// There is no surrounding struct to frame the transmission, so we must // There is no surrounding struct to frame the transmission, so we must
// generate data even if the item is zero. To do this, set sendZero. // generate data even if the item is zero. To do this, set sendZero.
state.sendZero = true state.sendZero = true
instr := &engine.instr[singletonField] instr := &engine.instr[singletonField]
p := unsafe.Pointer(basep) // offset will be zero p := basep // offset will be zero
if instr.indir > 0 { if instr.indir > 0 {
if p = encIndirect(p, instr.indir); p == nil { if p = encIndirect(p, instr.indir); p == nil {
return return
@ -356,12 +356,12 @@ func (enc *Encoder) encodeSingle(b *bytes.Buffer, engine *encEngine, basep uintp
} }
// encodeStruct encodes a single struct value. // encodeStruct encodes a single struct value.
func (enc *Encoder) encodeStruct(b *bytes.Buffer, engine *encEngine, basep uintptr) { func (enc *Encoder) encodeStruct(b *bytes.Buffer, engine *encEngine, basep unsafe.Pointer) {
state := enc.newEncoderState(b) state := enc.newEncoderState(b)
state.fieldnum = -1 state.fieldnum = -1
for i := 0; i < len(engine.instr); i++ { for i := 0; i < len(engine.instr); i++ {
instr := &engine.instr[i] instr := &engine.instr[i]
p := unsafe.Pointer(basep + instr.offset) p := unsafe.Pointer(uintptr(basep) + instr.offset)
if instr.indir > 0 { if instr.indir > 0 {
if p = encIndirect(p, instr.indir); p == nil { if p = encIndirect(p, instr.indir); p == nil {
continue continue
@ -373,22 +373,22 @@ func (enc *Encoder) encodeStruct(b *bytes.Buffer, engine *encEngine, basep uintp
} }
// encodeArray encodes the array whose 0th element is at p. // encodeArray encodes the array whose 0th element is at p.
func (enc *Encoder) encodeArray(b *bytes.Buffer, p uintptr, op encOp, elemWid uintptr, elemIndir int, length int) { func (enc *Encoder) encodeArray(b *bytes.Buffer, p unsafe.Pointer, op encOp, elemWid uintptr, elemIndir int, length int) {
state := enc.newEncoderState(b) state := enc.newEncoderState(b)
state.fieldnum = -1 state.fieldnum = -1
state.sendZero = true state.sendZero = true
state.encodeUint(uint64(length)) state.encodeUint(uint64(length))
for i := 0; i < length; i++ { for i := 0; i < length; i++ {
elemp := p elemp := p
up := unsafe.Pointer(elemp)
if elemIndir > 0 { if elemIndir > 0 {
if up = encIndirect(up, elemIndir); up == nil { up := encIndirect(elemp, elemIndir)
if up == nil {
errorf("encodeArray: nil element") errorf("encodeArray: nil element")
} }
elemp = uintptr(up) elemp = up
} }
op(nil, state, unsafe.Pointer(elemp)) op(nil, state, elemp)
p += uintptr(elemWid) p = unsafe.Pointer(uintptr(p) + elemWid)
} }
enc.freeEncoderState(state) enc.freeEncoderState(state)
} }
@ -401,7 +401,7 @@ func encodeReflectValue(state *encoderState, v reflect.Value, op encOp, indir in
if !v.IsValid() { if !v.IsValid() {
errorf("encodeReflectValue: nil element") errorf("encodeReflectValue: nil element")
} }
op(nil, state, unsafe.Pointer(unsafeAddr(v))) op(nil, state, unsafeAddr(v))
} }
// encodeMap encodes a map as unsigned count followed by key:value pairs. // encodeMap encodes a map as unsigned count followed by key:value pairs.
@ -582,14 +582,14 @@ func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp
return return
} }
state.update(i) state.update(i)
state.enc.encodeArray(state.b, slice.Data, *elemOp, t.Elem().Size(), indir, int(slice.Len)) state.enc.encodeArray(state.b, unsafe.Pointer(slice.Data), *elemOp, t.Elem().Size(), indir, int(slice.Len))
} }
case reflect.Array: case reflect.Array:
// True arrays have size in the type. // True arrays have size in the type.
elemOp, indir := enc.encOpFor(t.Elem(), inProgress) elemOp, indir := enc.encOpFor(t.Elem(), inProgress)
op = func(i *encInstr, state *encoderState, p unsafe.Pointer) { op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
state.update(i) state.update(i)
state.enc.encodeArray(state.b, uintptr(p), *elemOp, t.Elem().Size(), indir, t.Len()) state.enc.encodeArray(state.b, p, *elemOp, t.Elem().Size(), indir, t.Len())
} }
case reflect.Map: case reflect.Map:
keyOp, keyIndir := enc.encOpFor(t.Key(), inProgress) keyOp, keyIndir := enc.encOpFor(t.Key(), inProgress)
@ -615,7 +615,7 @@ func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp
op = func(i *encInstr, state *encoderState, p unsafe.Pointer) { op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
state.update(i) state.update(i)
// indirect through info to delay evaluation for recursive structs // indirect through info to delay evaluation for recursive structs
state.enc.encodeStruct(state.b, info.encoder, uintptr(p)) state.enc.encodeStruct(state.b, info.encoder, p)
} }
case reflect.Interface: case reflect.Interface:
op = func(i *encInstr, state *encoderState, p unsafe.Pointer) { op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {