summaryrefslogtreecommitdiffstats
path: root/llgo/third_party/gofrontend/libgo/go/encoding/gob/decode.go
diff options
context:
space:
mode:
authorPeter Collingbourne <peter@pcc.me.uk>2015-04-05 23:30:42 +0000
committerPeter Collingbourne <peter@pcc.me.uk>2015-04-05 23:30:42 +0000
commit93c73ebcbd73f5436d13ffc41f49a86fc062deb8 (patch)
tree10bf9fb3a1314fc8a1c3b963b4550960718384ad /llgo/third_party/gofrontend/libgo/go/encoding/gob/decode.go
parent7d39641c805bf3263ffb55a23ecf4bbfd37402c0 (diff)
downloadbcm5719-llvm-93c73ebcbd73f5436d13ffc41f49a86fc062deb8.tar.gz
bcm5719-llvm-93c73ebcbd73f5436d13ffc41f49a86fc062deb8.zip
Roll gofrontend to a6e10414311a
This takes us to Go 1.4. Also includes a couple of changes to the test suite, both in the runtime package: - Disable TestSetPanicOnFault. We cannot support this scenario at all, due to LLVM's lack of non-call exceptions. - Tweak TestFinalizerType. This test only passes with two GC runs. Differential Revision: http://reviews.llvm.org/D8828 llvm-svn: 234134
Diffstat (limited to 'llgo/third_party/gofrontend/libgo/go/encoding/gob/decode.go')
-rw-r--r--llgo/third_party/gofrontend/libgo/go/encoding/gob/decode.go724
1 files changed, 312 insertions, 412 deletions
diff --git a/llgo/third_party/gofrontend/libgo/go/encoding/gob/decode.go b/llgo/third_party/gofrontend/libgo/go/encoding/gob/decode.go
index d8513148ec2..a5bef93141b 100644
--- a/llgo/third_party/gofrontend/libgo/go/encoding/gob/decode.go
+++ b/llgo/third_party/gofrontend/libgo/go/encoding/gob/decode.go
@@ -2,19 +2,16 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package gob
+//go:generate go run decgen.go -output dec_helpers.go
-// TODO(rsc): When garbage collector changes, revisit
-// the allocations in this file that use unsafe.Pointer.
+package gob
import (
- "bytes"
"encoding"
"errors"
"io"
"math"
"reflect"
- "unsafe"
)
var (
@@ -23,21 +20,79 @@ var (
errRange = errors.New("gob: bad data: field numbers out of bounds")
)
+type decHelper func(state *decoderState, v reflect.Value, length int, ovfl error) bool
+
// decoderState is the execution state of an instance of the decoder. A new state
// is created for nested objects.
type decoderState struct {
dec *Decoder
// The buffer is stored with an extra indirection because it may be replaced
// if we load a type during decode (when reading an interface value).
- b *bytes.Buffer
+ b *decBuffer
fieldnum int // the last field number read.
buf []byte
next *decoderState // for free list
}
+// decBuffer is an extremely simple, fast implementation of a read-only byte buffer.
+// It is initialized by calling Size and then copying the data into the slice returned by Bytes().
+type decBuffer struct {
+ data []byte
+ offset int // Read offset.
+}
+
+func (d *decBuffer) Read(p []byte) (int, error) {
+ n := copy(p, d.data[d.offset:])
+ if n == 0 && len(p) != 0 {
+ return 0, io.EOF
+ }
+ d.offset += n
+ return n, nil
+}
+
+func (d *decBuffer) Drop(n int) {
+ if n > d.Len() {
+ panic("drop")
+ }
+ d.offset += n
+}
+
+// Size grows the buffer to exactly n bytes, so d.Bytes() will
+// return a slice of length n. Existing data is first discarded.
+func (d *decBuffer) Size(n int) {
+ d.Reset()
+ if cap(d.data) < n {
+ d.data = make([]byte, n)
+ } else {
+ d.data = d.data[0:n]
+ }
+}
+
+func (d *decBuffer) ReadByte() (byte, error) {
+ if d.offset >= len(d.data) {
+ return 0, io.EOF
+ }
+ c := d.data[d.offset]
+ d.offset++
+ return c, nil
+}
+
+func (d *decBuffer) Len() int {
+ return len(d.data) - d.offset
+}
+
+func (d *decBuffer) Bytes() []byte {
+ return d.data[d.offset:]
+}
+
+func (d *decBuffer) Reset() {
+ d.data = d.data[0:0]
+ d.offset = 0
+}
+
// We pass the bytes.Buffer separately for easier testing of the infrastructure
// without requiring a full Decoder.
-func (dec *Decoder) newDecoderState(buf *bytes.Buffer) *decoderState {
+func (dec *Decoder) newDecoderState(buf *decBuffer) *decoderState {
d := dec.freeList
if d == nil {
d = new(decoderState)
@@ -128,175 +183,118 @@ func (state *decoderState) decodeInt() int64 {
}
// decOp is the signature of a decoding operator for a given type.
-type decOp func(i *decInstr, state *decoderState, p unsafe.Pointer)
+type decOp func(i *decInstr, state *decoderState, v reflect.Value)
// The 'instructions' of the decoding machine
type decInstr struct {
- op decOp
- field int // field number of the wire type
- indir int // how many pointer indirections to reach the value in the struct
- offset uintptr // offset in the structure of the field to encode
- ovfl error // error message for overflow/underflow (for arrays, of the elements)
-}
-
-// 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
+ op decOp
+ field int // field number of the wire type
+ index []int // field access indices for destination type
+ ovfl error // error message for overflow/underflow (for arrays, of the elements)
}
// ignoreUint discards a uint value with no destination.
-func ignoreUint(i *decInstr, state *decoderState, p unsafe.Pointer) {
+func ignoreUint(i *decInstr, state *decoderState, v reflect.Value) {
state.decodeUint()
}
// ignoreTwoUints discards a uint value with no destination. It's used to skip
// complex values.
-func ignoreTwoUints(i *decInstr, state *decoderState, p unsafe.Pointer) {
+func ignoreTwoUints(i *decInstr, state *decoderState, v reflect.Value) {
state.decodeUint()
state.decodeUint()
}
-// decBool decodes a uint and stores it as a boolean through p.
-func decBool(i *decInstr, state *decoderState, p unsafe.Pointer) {
- if i.indir > 0 {
- if *(*unsafe.Pointer)(p) == nil {
- *(*unsafe.Pointer)(p) = unsafe.Pointer(new(bool))
+// 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.
+
+// decAlloc takes a value and returns a settable value that can
+// be assigned to. If the value is a pointer, decAlloc guarantees it points to storage.
+// The callers to the individual decoders are expected to have used decAlloc.
+// The individual decoders don't need to it.
+func decAlloc(v reflect.Value) reflect.Value {
+ for v.Kind() == reflect.Ptr {
+ if v.IsNil() {
+ v.Set(reflect.New(v.Type().Elem()))
}
- p = *(*unsafe.Pointer)(p)
+ v = v.Elem()
}
- *(*bool)(p) = state.decodeUint() != 0
+ return v
}
-// decInt8 decodes an integer and stores it as an int8 through p.
-func decInt8(i *decInstr, state *decoderState, p unsafe.Pointer) {
- if i.indir > 0 {
- if *(*unsafe.Pointer)(p) == nil {
- *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int8))
- }
- p = *(*unsafe.Pointer)(p)
- }
+// decBool decodes a uint and stores it as a boolean in value.
+func decBool(i *decInstr, state *decoderState, value reflect.Value) {
+ value.SetBool(state.decodeUint() != 0)
+}
+
+// decInt8 decodes an integer and stores it as an int8 in value.
+func decInt8(i *decInstr, state *decoderState, value reflect.Value) {
v := state.decodeInt()
if v < math.MinInt8 || math.MaxInt8 < v {
error_(i.ovfl)
- } else {
- *(*int8)(p) = int8(v)
}
+ value.SetInt(v)
}
-// decUint8 decodes an unsigned integer and stores it as a uint8 through p.
-func decUint8(i *decInstr, state *decoderState, p unsafe.Pointer) {
- if i.indir > 0 {
- if *(*unsafe.Pointer)(p) == nil {
- *(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint8))
- }
- p = *(*unsafe.Pointer)(p)
- }
+// decUint8 decodes an unsigned integer and stores it as a uint8 in value.
+func decUint8(i *decInstr, state *decoderState, value reflect.Value) {
v := state.decodeUint()
if math.MaxUint8 < v {
error_(i.ovfl)
- } else {
- *(*uint8)(p) = uint8(v)
}
+ value.SetUint(v)
}
-// decInt16 decodes an integer and stores it as an int16 through p.
-func decInt16(i *decInstr, state *decoderState, p unsafe.Pointer) {
- if i.indir > 0 {
- if *(*unsafe.Pointer)(p) == nil {
- *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int16))
- }
- p = *(*unsafe.Pointer)(p)
- }
+// decInt16 decodes an integer and stores it as an int16 in value.
+func decInt16(i *decInstr, state *decoderState, value reflect.Value) {
v := state.decodeInt()
if v < math.MinInt16 || math.MaxInt16 < v {
error_(i.ovfl)
- } else {
- *(*int16)(p) = int16(v)
}
+ value.SetInt(v)
}
-// decUint16 decodes an unsigned integer and stores it as a uint16 through p.
-func decUint16(i *decInstr, state *decoderState, p unsafe.Pointer) {
- if i.indir > 0 {
- if *(*unsafe.Pointer)(p) == nil {
- *(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint16))
- }
- p = *(*unsafe.Pointer)(p)
- }
+// decUint16 decodes an unsigned integer and stores it as a uint16 in value.
+func decUint16(i *decInstr, state *decoderState, value reflect.Value) {
v := state.decodeUint()
if math.MaxUint16 < v {
error_(i.ovfl)
- } else {
- *(*uint16)(p) = uint16(v)
}
+ value.SetUint(v)
}
-// decInt32 decodes an integer and stores it as an int32 through p.
-func decInt32(i *decInstr, state *decoderState, p unsafe.Pointer) {
- if i.indir > 0 {
- if *(*unsafe.Pointer)(p) == nil {
- *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int32))
- }
- p = *(*unsafe.Pointer)(p)
- }
+// decInt32 decodes an integer and stores it as an int32 in value.
+func decInt32(i *decInstr, state *decoderState, value reflect.Value) {
v := state.decodeInt()
if v < math.MinInt32 || math.MaxInt32 < v {
error_(i.ovfl)
- } else {
- *(*int32)(p) = int32(v)
}
+ value.SetInt(v)
}
-// decUint32 decodes an unsigned integer and stores it as a uint32 through p.
-func decUint32(i *decInstr, state *decoderState, p unsafe.Pointer) {
- if i.indir > 0 {
- if *(*unsafe.Pointer)(p) == nil {
- *(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint32))
- }
- p = *(*unsafe.Pointer)(p)
- }
+// decUint32 decodes an unsigned integer and stores it as a uint32 in value.
+func decUint32(i *decInstr, state *decoderState, value reflect.Value) {
v := state.decodeUint()
if math.MaxUint32 < v {
error_(i.ovfl)
- } else {
- *(*uint32)(p) = uint32(v)
}
+ value.SetUint(v)
}
-// decInt64 decodes an integer and stores it as an int64 through p.
-func decInt64(i *decInstr, state *decoderState, p unsafe.Pointer) {
- if i.indir > 0 {
- if *(*unsafe.Pointer)(p) == nil {
- *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int64))
- }
- p = *(*unsafe.Pointer)(p)
- }
- *(*int64)(p) = int64(state.decodeInt())
+// decInt64 decodes an integer and stores it as an int64 in value.
+func decInt64(i *decInstr, state *decoderState, value reflect.Value) {
+ v := state.decodeInt()
+ value.SetInt(v)
}
-// decUint64 decodes an unsigned integer and stores it as a uint64 through p.
-func decUint64(i *decInstr, state *decoderState, p unsafe.Pointer) {
- if i.indir > 0 {
- if *(*unsafe.Pointer)(p) == nil {
- *(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint64))
- }
- p = *(*unsafe.Pointer)(p)
- }
- *(*uint64)(p) = uint64(state.decodeUint())
+// decUint64 decodes an unsigned integer and stores it as a uint64 in value.
+func decUint64(i *decInstr, state *decoderState, value reflect.Value) {
+ v := state.decodeUint()
+ value.SetUint(v)
}
// Floating-point numbers are transmitted as uint64s holding the bits
@@ -304,7 +302,7 @@ func decUint64(i *decInstr, state *decoderState, p unsafe.Pointer) {
// 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 {
+func float64FromBits(u uint64) float64 {
var v uint64
for i := 0; i < 8; i++ {
v <<= 8
@@ -314,128 +312,100 @@ func floatFromBits(u uint64) float64 {
return math.Float64frombits(v)
}
-// storeFloat32 decodes an unsigned integer, treats it as a 32-bit floating-point
-// number, and stores it through p. It's a helper function for float32 and complex64.
-func storeFloat32(i *decInstr, state *decoderState, p unsafe.Pointer) {
- v := floatFromBits(state.decodeUint())
+// float32FromBits decodes an unsigned integer, treats it as a 32-bit floating-point
+// number, and returns it. It's a helper function for float32 and complex64.
+// It returns a float64 because that's what reflection needs, but its return
+// value is known to be accurately representable in a float32.
+func float32FromBits(u uint64, ovfl error) float64 {
+ v := float64FromBits(u)
av := v
if av < 0 {
av = -av
}
// +Inf is OK in both 32- and 64-bit floats. Underflow is always OK.
if math.MaxFloat32 < av && av <= math.MaxFloat64 {
- error_(i.ovfl)
- } else {
- *(*float32)(p) = float32(v)
+ error_(ovfl)
}
+ return v
}
// decFloat32 decodes an unsigned integer, treats it as a 32-bit floating-point
-// number, and stores it through p.
-func decFloat32(i *decInstr, state *decoderState, p unsafe.Pointer) {
- if i.indir > 0 {
- if *(*unsafe.Pointer)(p) == nil {
- *(*unsafe.Pointer)(p) = unsafe.Pointer(new(float32))
- }
- p = *(*unsafe.Pointer)(p)
- }
- storeFloat32(i, state, p)
+// number, and stores it in value.
+func decFloat32(i *decInstr, state *decoderState, value reflect.Value) {
+ value.SetFloat(float32FromBits(state.decodeUint(), i.ovfl))
}
// decFloat64 decodes an unsigned integer, treats it as a 64-bit floating-point
-// number, and stores it through p.
-func decFloat64(i *decInstr, state *decoderState, p unsafe.Pointer) {
- if i.indir > 0 {
- if *(*unsafe.Pointer)(p) == nil {
- *(*unsafe.Pointer)(p) = unsafe.Pointer(new(float64))
- }
- p = *(*unsafe.Pointer)(p)
- }
- *(*float64)(p) = floatFromBits(uint64(state.decodeUint()))
+// number, and stores it in value.
+func decFloat64(i *decInstr, state *decoderState, value reflect.Value) {
+ value.SetFloat(float64FromBits(state.decodeUint()))
}
// decComplex64 decodes a pair of unsigned integers, treats them as a
-// pair of floating point numbers, and stores them as a complex64 through p.
+// pair of floating point numbers, and stores them as a complex64 in value.
// The real part comes first.
-func decComplex64(i *decInstr, state *decoderState, p unsafe.Pointer) {
- if i.indir > 0 {
- if *(*unsafe.Pointer)(p) == nil {
- *(*unsafe.Pointer)(p) = unsafe.Pointer(new(complex64))
- }
- p = *(*unsafe.Pointer)(p)
- }
- storeFloat32(i, state, p)
- storeFloat32(i, state, unsafe.Pointer(uintptr(p)+unsafe.Sizeof(float32(0))))
+func decComplex64(i *decInstr, state *decoderState, value reflect.Value) {
+ real := float32FromBits(state.decodeUint(), i.ovfl)
+ imag := float32FromBits(state.decodeUint(), i.ovfl)
+ value.SetComplex(complex(real, imag))
}
// decComplex128 decodes a pair of unsigned integers, treats them as a
-// pair of floating point numbers, and stores them as a complex128 through p.
+// pair of floating point numbers, and stores them as a complex128 in value.
// The real part comes first.
-func decComplex128(i *decInstr, state *decoderState, p unsafe.Pointer) {
- if i.indir > 0 {
- if *(*unsafe.Pointer)(p) == nil {
- *(*unsafe.Pointer)(p) = unsafe.Pointer(new(complex128))
- }
- p = *(*unsafe.Pointer)(p)
- }
- real := floatFromBits(uint64(state.decodeUint()))
- imag := floatFromBits(uint64(state.decodeUint()))
- *(*complex128)(p) = complex(real, imag)
+func decComplex128(i *decInstr, state *decoderState, value reflect.Value) {
+ real := float64FromBits(state.decodeUint())
+ imag := float64FromBits(state.decodeUint())
+ value.SetComplex(complex(real, imag))
}
-// decUint8Slice decodes a byte slice and stores through p a slice header
+// decUint8Slice decodes a byte slice and stores in value a slice header
// describing the data.
// uint8 slices are encoded as an unsigned count followed by the raw bytes.
-func decUint8Slice(i *decInstr, state *decoderState, p unsafe.Pointer) {
- if i.indir > 0 {
- if *(*unsafe.Pointer)(p) == nil {
- *(*unsafe.Pointer)(p) = unsafe.Pointer(new([]uint8))
- }
- p = *(*unsafe.Pointer)(p)
+func decUint8Slice(i *decInstr, state *decoderState, value reflect.Value) {
+ u := state.decodeUint()
+ n := int(u)
+ if n < 0 || uint64(n) != u {
+ errorf("length of %s exceeds input size (%d bytes)", value.Type(), u)
+ }
+ if n > state.b.Len() {
+ errorf("%s data too long for buffer: %d", value.Type(), n)
}
- n := state.decodeUint()
- if n > uint64(state.b.Len()) {
- errorf("length of []byte exceeds input size (%d bytes)", n)
+ if n > tooBig {
+ errorf("byte slice too big: %d", n)
}
- slice := (*[]uint8)(p)
- if uint64(cap(*slice)) < n {
- *slice = make([]uint8, n)
+ if value.Cap() < n {
+ value.Set(reflect.MakeSlice(value.Type(), n, n))
} else {
- *slice = (*slice)[0:n]
+ value.Set(value.Slice(0, n))
}
- if _, err := state.b.Read(*slice); err != nil {
+ if _, err := state.b.Read(value.Bytes()); err != nil {
errorf("error decoding []byte: %s", err)
}
}
-// decString decodes byte array and stores through p a string header
+// decString decodes byte array and stores in value a string header
// describing the data.
// Strings are encoded as an unsigned count followed by the raw bytes.
-func decString(i *decInstr, state *decoderState, p unsafe.Pointer) {
- if i.indir > 0 {
- if *(*unsafe.Pointer)(p) == nil {
- *(*unsafe.Pointer)(p) = unsafe.Pointer(new(string))
- }
- p = *(*unsafe.Pointer)(p)
+func decString(i *decInstr, state *decoderState, value reflect.Value) {
+ u := state.decodeUint()
+ n := int(u)
+ if n < 0 || uint64(n) != u || n > state.b.Len() {
+ errorf("length of %s exceeds input size (%d bytes)", value.Type(), u)
}
- n := state.decodeUint()
- if n > uint64(state.b.Len()) {
- errorf("string length exceeds input size (%d bytes)", n)
+ if n > state.b.Len() {
+ errorf("%s data too long for buffer: %d", value.Type(), n)
}
- b := make([]byte, n)
- state.b.Read(b)
- // It would be a shame to do the obvious thing here,
- // *(*string)(p) = string(b)
- // because we've already allocated the storage and this would
- // allocate again and copy. So we do this ugly hack, which is even
- // even more unsafe than it looks as it depends the memory
- // representation of a string matching the beginning of the memory
- // representation of a byte slice (a byte slice is longer).
- *(*string)(p) = *(*string)(unsafe.Pointer(&b))
+ // Read the data.
+ data := make([]byte, n)
+ if _, err := state.b.Read(data); err != nil {
+ errorf("error decoding string: %s", err)
+ }
+ value.SetString(string(data))
}
// ignoreUint8Array skips over the data for a byte slice value with no destination.
-func ignoreUint8Array(i *decInstr, state *decoderState, p unsafe.Pointer) {
+func ignoreUint8Array(i *decInstr, state *decoderState, value reflect.Value) {
b := make([]byte, state.decodeUint())
state.b.Read(b)
}
@@ -449,55 +419,29 @@ type decEngine struct {
numInstr int // the number of active instructions
}
-// allocate makes sure storage is available for an object of underlying type rtyp
-// that is indir levels of indirection through p.
-func allocate(rtyp reflect.Type, p unsafe.Pointer, indir int) unsafe.Pointer {
- if indir == 0 {
- return p
- }
- up := p
- if indir > 1 {
- up = decIndirect(up, indir)
- }
- if *(*unsafe.Pointer)(up) == nil {
- // Allocate object.
- *(*unsafe.Pointer)(up) = unsafe.Pointer(reflect.New(rtyp).Pointer())
- }
- 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 in value.
// Such values are preceded by a zero, making them have the memory layout of a
// struct field (although with an illegal field number).
-func (dec *Decoder) decodeSingle(engine *decEngine, ut *userTypeInfo, basep unsafe.Pointer) {
+func (dec *Decoder) decodeSingle(engine *decEngine, ut *userTypeInfo, value reflect.Value) {
state := dec.newDecoderState(&dec.buf)
+ defer dec.freeDecoderState(state)
state.fieldnum = singletonField
- delta := int(state.decodeUint())
- if delta != 0 {
+ if state.decodeUint() != 0 {
errorf("decode: corrupted data: non-zero delta for singleton")
}
instr := &engine.instr[singletonField]
- if instr.indir != ut.indir {
- errorf("internal error: inconsistent indirection instr %d ut %d", instr.indir, ut.indir)
- }
- ptr := basep // offset will be zero
- if instr.indir > 1 {
- ptr = decIndirect(ptr, instr.indir)
- }
- instr.op(instr, state, ptr)
- dec.freeDecoderState(state)
+ instr.op(instr, state, value)
}
-// decodeStruct decodes a top-level struct and stores it through p.
+// decodeStruct decodes a top-level struct and stores it in value.
// Indir is for the value, not the type. At the time of the call it may
// differ from ut.indir, which was computed when the engine was built.
// This state cannot arise for decodeSingle, which is called directly
// from the user's value, not from the innards of an engine.
-func (dec *Decoder) decodeStruct(engine *decEngine, ut *userTypeInfo, p unsafe.Pointer, indir int) {
- p = allocate(ut.base, p, indir)
+func (dec *Decoder) decodeStruct(engine *decEngine, ut *userTypeInfo, value reflect.Value) {
state := dec.newDecoderState(&dec.buf)
+ defer dec.freeDecoderState(state)
state.fieldnum = -1
- basep := p
for state.b.Len() > 0 {
delta := int(state.decodeUint())
if delta < 0 {
@@ -512,19 +456,25 @@ func (dec *Decoder) decodeStruct(engine *decEngine, ut *userTypeInfo, p unsafe.P
break
}
instr := &engine.instr[fieldnum]
- p := unsafe.Pointer(uintptr(basep) + instr.offset)
- if instr.indir > 1 {
- p = decIndirect(p, instr.indir)
+ var field reflect.Value
+ if instr.index != nil {
+ // Otherwise the field is unknown to us and instr.op is an ignore op.
+ field = value.FieldByIndex(instr.index)
+ if field.Kind() == reflect.Ptr {
+ field = decAlloc(field)
+ }
}
- instr.op(instr, state, p)
+ instr.op(instr, state, field)
state.fieldnum = fieldnum
}
- dec.freeDecoderState(state)
}
+var noValue reflect.Value
+
// ignoreStruct discards the data for a struct with no destination.
func (dec *Decoder) ignoreStruct(engine *decEngine) {
state := dec.newDecoderState(&dec.buf)
+ defer dec.freeDecoderState(state)
state.fieldnum = -1
for state.b.Len() > 0 {
delta := int(state.decodeUint())
@@ -539,97 +489,89 @@ func (dec *Decoder) ignoreStruct(engine *decEngine) {
error_(errRange)
}
instr := &engine.instr[fieldnum]
- instr.op(instr, state, unsafe.Pointer(nil))
+ instr.op(instr, state, noValue)
state.fieldnum = fieldnum
}
- dec.freeDecoderState(state)
}
// ignoreSingle discards the data for a top-level non-struct value with no
// destination. It's used when calling Decode with a nil value.
func (dec *Decoder) ignoreSingle(engine *decEngine) {
state := dec.newDecoderState(&dec.buf)
+ defer dec.freeDecoderState(state)
state.fieldnum = singletonField
delta := int(state.decodeUint())
if delta != 0 {
errorf("decode: corrupted data: non-zero delta for singleton")
}
instr := &engine.instr[singletonField]
- instr.op(instr, state, unsafe.Pointer(nil))
- dec.freeDecoderState(state)
+ instr.op(instr, state, noValue)
}
// decodeArrayHelper does the work for decoding arrays and slices.
-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}
+func (dec *Decoder) decodeArrayHelper(state *decoderState, value reflect.Value, elemOp decOp, length int, ovfl error, helper decHelper) {
+ if helper != nil && helper(state, value, length, ovfl) {
+ return
+ }
+ instr := &decInstr{elemOp, 0, nil, ovfl}
+ isPtr := value.Type().Elem().Kind() == reflect.Ptr
for i := 0; i < length; i++ {
if state.b.Len() == 0 {
errorf("decoding array or slice: length exceeds input size (%d elements)", length)
}
- up := p
- if elemIndir > 1 {
- up = decIndirect(up, elemIndir)
+ v := value.Index(i)
+ if isPtr {
+ v = decAlloc(v)
}
- elemOp(instr, state, up)
- p = unsafe.Pointer(uintptr(p) + elemWid)
+ elemOp(instr, state, v)
}
}
-// decodeArray decodes an array and stores it through p, that is, p points to the zeroth element.
+// decodeArray decodes an array and stores it in value.
// 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.
-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 {
- p = allocate(atyp, p, 1) // All but the last level has been allocated by dec.Indirect
- }
+func (dec *Decoder) decodeArray(atyp reflect.Type, state *decoderState, value reflect.Value, elemOp decOp, length int, ovfl error, helper decHelper) {
if n := state.decodeUint(); n != uint64(length) {
errorf("length mismatch in decodeArray")
}
- dec.decodeArrayHelper(state, p, elemOp, elemWid, length, elemIndir, ovfl)
+ dec.decodeArrayHelper(state, value, elemOp, length, ovfl, helper)
}
-// decodeIntoValue is a helper for map decoding. Since maps are decoded using reflection,
-// 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 {
- instr := &decInstr{op, 0, indir, 0, ovfl}
- up := unsafeAddr(v)
- if indir > 1 {
- up = decIndirect(up, indir)
+// decodeIntoValue is a helper for map decoding.
+func decodeIntoValue(state *decoderState, op decOp, isPtr bool, value reflect.Value, ovfl error) reflect.Value {
+ instr := &decInstr{op, 0, nil, ovfl}
+ v := value
+ if isPtr {
+ v = decAlloc(value)
}
- op(instr, state, up)
- return v
+ op(instr, state, v)
+ return value
}
-// decodeMap decodes a map and stores its header through p.
+// decodeMap decodes a map and stores it in value.
// Maps are encoded as a length followed by key:value pairs.
// Because the internals of maps are not visible to us, we must
// use reflection rather than pointer magic.
-func (dec *Decoder) decodeMap(mtyp reflect.Type, state *decoderState, p unsafe.Pointer, keyOp, elemOp decOp, indir, keyIndir, elemIndir int, ovfl error) {
- if indir > 0 {
- p = allocate(mtyp, p, 1) // All but the last level has been allocated by dec.Indirect
- }
- up := unsafe.Pointer(p)
- if *(*unsafe.Pointer)(up) == nil { // maps are represented as a pointer in the runtime
+func (dec *Decoder) decodeMap(mtyp reflect.Type, state *decoderState, value reflect.Value, keyOp, elemOp decOp, ovfl error) {
+ if value.IsNil() {
// Allocate map.
- *(*unsafe.Pointer)(up) = unsafe.Pointer(reflect.MakeMap(mtyp).Pointer())
+ value.Set(reflect.MakeMap(mtyp))
}
- // Maps cannot be accessed by moving addresses around the way
- // that slices etc. can. We must recover a full reflection value for
- // the iteration.
- v := reflect.NewAt(mtyp, unsafe.Pointer(p)).Elem()
n := int(state.decodeUint())
+ keyIsPtr := mtyp.Key().Kind() == reflect.Ptr
+ elemIsPtr := mtyp.Elem().Kind() == reflect.Ptr
for i := 0; i < n; i++ {
- key := decodeIntoValue(state, keyOp, keyIndir, allocValue(mtyp.Key()), ovfl)
- elem := decodeIntoValue(state, elemOp, elemIndir, allocValue(mtyp.Elem()), ovfl)
- v.SetMapIndex(key, elem)
+ key := decodeIntoValue(state, keyOp, keyIsPtr, allocValue(mtyp.Key()), ovfl)
+ elem := decodeIntoValue(state, elemOp, elemIsPtr, allocValue(mtyp.Elem()), ovfl)
+ value.SetMapIndex(key, elem)
}
}
// ignoreArrayHelper does the work for discarding arrays and slices.
func (dec *Decoder) ignoreArrayHelper(state *decoderState, elemOp decOp, length int) {
- instr := &decInstr{elemOp, 0, 0, 0, errors.New("no error")}
+ instr := &decInstr{elemOp, 0, nil, errors.New("no error")}
for i := 0; i < length; i++ {
- elemOp(instr, state, nil)
+ elemOp(instr, state, noValue)
}
}
@@ -644,36 +586,34 @@ func (dec *Decoder) ignoreArray(state *decoderState, elemOp decOp, length int) {
// ignoreMap discards the data for a map value with no destination.
func (dec *Decoder) ignoreMap(state *decoderState, keyOp, elemOp decOp) {
n := int(state.decodeUint())
- keyInstr := &decInstr{keyOp, 0, 0, 0, errors.New("no error")}
- elemInstr := &decInstr{elemOp, 0, 0, 0, errors.New("no error")}
+ keyInstr := &decInstr{keyOp, 0, nil, errors.New("no error")}
+ elemInstr := &decInstr{elemOp, 0, nil, errors.New("no error")}
for i := 0; i < n; i++ {
- keyOp(keyInstr, state, nil)
- elemOp(elemInstr, state, nil)
+ keyOp(keyInstr, state, noValue)
+ elemOp(elemInstr, state, noValue)
}
}
-// decodeSlice decodes a slice and stores the slice header through p.
+// decodeSlice decodes a slice and stores it in value.
// Slices are encoded as an unsigned length followed by the elements.
-func (dec *Decoder) decodeSlice(atyp reflect.Type, state *decoderState, p unsafe.Pointer, elemOp decOp, elemWid uintptr, indir, elemIndir int, ovfl error) {
- nr := state.decodeUint()
- n := int(nr)
- if indir > 0 {
- if *(*unsafe.Pointer)(p) == nil {
- // Allocate the slice header.
- *(*unsafe.Pointer)(p) = unsafe.Pointer(new([]unsafe.Pointer))
- }
- p = *(*unsafe.Pointer)(p)
- }
- // Allocate storage for the slice elements, that is, the underlying array,
- // if the existing slice does not have the capacity.
- // Always write a header at p.
- hdrp := (*reflect.SliceHeader)(p)
- if hdrp.Cap < n {
- hdrp.Data = reflect.MakeSlice(atyp, n, n).Pointer()
- hdrp.Cap = n
+func (dec *Decoder) decodeSlice(state *decoderState, value reflect.Value, elemOp decOp, ovfl error, helper decHelper) {
+ u := state.decodeUint()
+ typ := value.Type()
+ size := uint64(typ.Elem().Size())
+ nBytes := u * size
+ n := int(u)
+ // Take care with overflow in this calculation.
+ if n < 0 || uint64(n) != u || nBytes > tooBig || (size > 0 && nBytes/size != u) {
+ // We don't check n against buffer length here because if it's a slice
+ // of interfaces, there will be buffer reloads.
+ errorf("%s slice too big: %d elements of %d bytes", typ.Elem(), u, size)
+ }
+ if value.Cap() < n {
+ value.Set(reflect.MakeSlice(typ, n, n))
+ } else {
+ value.Set(value.Slice(0, n))
}
- hdrp.Len = n
- dec.decodeArrayHelper(state, unsafe.Pointer(hdrp.Data), elemOp, elemWid, n, elemIndir, ovfl)
+ dec.decodeArrayHelper(state, value, elemOp, n, ovfl, helper)
}
// ignoreSlice skips over the data for a slice value with no destination.
@@ -681,21 +621,10 @@ func (dec *Decoder) ignoreSlice(state *decoderState, elemOp decOp) {
dec.ignoreArrayHelper(state, elemOp, int(state.decodeUint()))
}
-// setInterfaceValue sets an interface value to a concrete value,
-// but first it checks that the assignment will succeed.
-func setInterfaceValue(ivalue reflect.Value, value reflect.Value) {
- if !value.Type().AssignableTo(ivalue.Type()) {
- errorf("%s is not assignable to type %s", value.Type(), ivalue.Type())
- }
- ivalue.Set(value)
-}
-
-// decodeInterface decodes an interface value and stores it through p.
+// decodeInterface decodes an interface value and stores it in 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.
-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.
- ivalue := allocValue(ityp)
+func (dec *Decoder) decodeInterface(ityp reflect.Type, state *decoderState, value reflect.Value) {
// Read the name of the concrete type.
nr := state.decodeUint()
if nr < 0 || nr > 1<<31 { // zero is permissible for anonymous types
@@ -707,13 +636,10 @@ func (dec *Decoder) decodeInterface(ityp reflect.Type, state *decoderState, p un
b := make([]byte, nr)
state.b.Read(b)
name := string(b)
+ // Allocate the destination interface value.
if name == "" {
- // Copy the representation of the nil interface value to the target.
- // This is horribly unsafe and special.
- if indir > 0 {
- p = allocate(ityp, p, 1) // All but the last level has been allocated by dec.Indirect
- }
- *(*[2]uintptr)(unsafe.Pointer(p)) = ivalue.InterfaceData()
+ // Copy the nil interface value to the target.
+ value.Set(reflect.Zero(value.Type()))
return
}
if len(name) > 1024 {
@@ -735,21 +661,18 @@ func (dec *Decoder) decodeInterface(ityp reflect.Type, state *decoderState, p un
// in case we want to ignore the value by skipping it completely).
state.decodeUint()
// Read the concrete value.
- value := allocValue(typ)
- dec.decodeValue(concreteId, value)
+ v := allocValue(typ)
+ dec.decodeValue(concreteId, v)
if dec.err != nil {
error_(dec.err)
}
- // Allocate the destination interface value.
- if indir > 0 {
- p = allocate(ityp, p, 1) // All but the last level has been allocated by dec.Indirect
- }
// Assign the concrete value to the interface.
// Tread carefully; it might not satisfy the interface.
- setInterfaceValue(ivalue, value)
- // Copy the representation of the interface value to the target.
- // This is horribly unsafe and special.
- *(*[2]uintptr)(unsafe.Pointer(p)) = ivalue.InterfaceData()
+ if !typ.AssignableTo(ityp) {
+ errorf("%s is not assignable to type %s", typ, ityp)
+ }
+ // Copy the interface value to the target.
+ value.Set(v)
}
// ignoreInterface discards the data for an interface value with no destination.
@@ -765,12 +688,12 @@ func (dec *Decoder) ignoreInterface(state *decoderState) {
error_(dec.err)
}
// At this point, the decoder buffer contains a delimited value. Just toss it.
- state.b.Next(int(state.decodeUint()))
+ state.b.Drop(int(state.decodeUint()))
}
// decodeGobDecoder decodes something implementing the GobDecoder interface.
// The data is encoded as a byte slice.
-func (dec *Decoder) decodeGobDecoder(ut *userTypeInfo, state *decoderState, v reflect.Value) {
+func (dec *Decoder) decodeGobDecoder(ut *userTypeInfo, state *decoderState, value reflect.Value) {
// Read the bytes for the value.
b := make([]byte, state.decodeUint())
_, err := state.b.Read(b)
@@ -780,11 +703,11 @@ func (dec *Decoder) decodeGobDecoder(ut *userTypeInfo, state *decoderState, v re
// We know it's one of these.
switch ut.externalDec {
case xGob:
- err = v.Interface().(GobDecoder).GobDecode(b)
+ err = value.Interface().(GobDecoder).GobDecode(b)
case xBinary:
- err = v.Interface().(encoding.BinaryUnmarshaler).UnmarshalBinary(b)
+ err = value.Interface().(encoding.BinaryUnmarshaler).UnmarshalBinary(b)
case xText:
- err = v.Interface().(encoding.TextUnmarshaler).UnmarshalText(b)
+ err = value.Interface().(encoding.TextUnmarshaler).UnmarshalText(b)
}
if err != nil {
error_(err)
@@ -832,7 +755,7 @@ var decIgnoreOpMap = map[typeId]decOp{
// decOpFor returns the decoding op for the base type under rt and
// the indirection count to reach it.
-func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProgress map[reflect.Type]*decOp) (*decOp, int) {
+func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProgress map[reflect.Type]*decOp) *decOp {
ut := userType(rt)
// If the type implements GobEncoder, we handle it without further processing.
if ut.externalDec != 0 {
@@ -842,10 +765,9 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg
// If this type is already in progress, it's a recursive type (e.g. map[string]*T).
// Return the pointer to the op we're already building.
if opPtr := inProgress[rt]; opPtr != nil {
- return opPtr, ut.indir
+ return opPtr
}
typ := ut.base
- indir := ut.indir
var op decOp
k := typ.Kind()
if int(k) < len(decOpTable) {
@@ -858,20 +780,21 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg
case reflect.Array:
name = "element of " + name
elemId := dec.wireType[wireId].ArrayT.Elem
- elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name, inProgress)
+ elemOp := dec.decOpFor(elemId, t.Elem(), name, inProgress)
ovfl := overflow(name)
- op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
- state.dec.decodeArray(t, state, p, *elemOp, t.Elem().Size(), t.Len(), i.indir, elemIndir, ovfl)
+ helper := decArrayHelper[t.Elem().Kind()]
+ op = func(i *decInstr, state *decoderState, value reflect.Value) {
+ state.dec.decodeArray(t, state, value, *elemOp, t.Len(), ovfl, helper)
}
case reflect.Map:
keyId := dec.wireType[wireId].MapT.Key
elemId := dec.wireType[wireId].MapT.Elem
- keyOp, keyIndir := dec.decOpFor(keyId, t.Key(), "key of "+name, inProgress)
- elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), "element of "+name, inProgress)
+ keyOp := dec.decOpFor(keyId, t.Key(), "key of "+name, inProgress)
+ elemOp := dec.decOpFor(elemId, t.Elem(), "element of "+name, inProgress)
ovfl := overflow(name)
- op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
- state.dec.decodeMap(t, state, p, *keyOp, *elemOp, i.indir, keyIndir, elemIndir, ovfl)
+ op = func(i *decInstr, state *decoderState, value reflect.Value) {
+ state.dec.decodeMap(t, state, value, *keyOp, *elemOp, ovfl)
}
case reflect.Slice:
@@ -886,32 +809,34 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg
} else {
elemId = dec.wireType[wireId].SliceT.Elem
}
- elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name, inProgress)
+ elemOp := dec.decOpFor(elemId, t.Elem(), name, inProgress)
ovfl := overflow(name)
- op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
- state.dec.decodeSlice(t, state, p, *elemOp, t.Elem().Size(), i.indir, elemIndir, ovfl)
+ helper := decSliceHelper[t.Elem().Kind()]
+ op = func(i *decInstr, state *decoderState, value reflect.Value) {
+ state.dec.decodeSlice(state, value, *elemOp, ovfl, helper)
}
case reflect.Struct:
// Generate a closure that calls out to the engine for the nested type.
- enginePtr, err := dec.getDecEnginePtr(wireId, userType(typ))
+ ut := userType(typ)
+ enginePtr, err := dec.getDecEnginePtr(wireId, ut)
if err != nil {
error_(err)
}
- op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
+ op = func(i *decInstr, state *decoderState, value reflect.Value) {
// indirect through enginePtr to delay evaluation for recursive structs.
- dec.decodeStruct(*enginePtr, userType(typ), p, i.indir)
+ dec.decodeStruct(*enginePtr, ut, value)
}
case reflect.Interface:
- op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
- state.dec.decodeInterface(t, state, p, i.indir)
+ op = func(i *decInstr, state *decoderState, value reflect.Value) {
+ state.dec.decodeInterface(t, state, value)
}
}
}
if op == nil {
errorf("decode can't handle type %s", rt)
}
- return &op, indir
+ return &op
}
// decIgnoreOpFor returns the decoding op for a field that has no destination.
@@ -921,7 +846,7 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId) decOp {
if wireId == tInterface {
// Special case because it's a method: the ignored item might
// define types and we need to record their state in the decoder.
- op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
+ op = func(i *decInstr, state *decoderState, value reflect.Value) {
state.dec.ignoreInterface(state)
}
return op
@@ -934,7 +859,7 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId) decOp {
case wire.ArrayT != nil:
elemId := wire.ArrayT.Elem
elemOp := dec.decIgnoreOpFor(elemId)
- op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
+ op = func(i *decInstr, state *decoderState, value reflect.Value) {
state.dec.ignoreArray(state, elemOp, wire.ArrayT.Len)
}
@@ -943,14 +868,14 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId) decOp {
elemId := dec.wireType[wireId].MapT.Elem
keyOp := dec.decIgnoreOpFor(keyId)
elemOp := dec.decIgnoreOpFor(elemId)
- op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
+ op = func(i *decInstr, state *decoderState, value reflect.Value) {
state.dec.ignoreMap(state, keyOp, elemOp)
}
case wire.SliceT != nil:
elemId := wire.SliceT.Elem
elemOp := dec.decIgnoreOpFor(elemId)
- op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
+ op = func(i *decInstr, state *decoderState, value reflect.Value) {
state.dec.ignoreSlice(state, elemOp)
}
@@ -960,13 +885,13 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId) decOp {
if err != nil {
error_(err)
}
- op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
+ op = func(i *decInstr, state *decoderState, value reflect.Value) {
// indirect through enginePtr to delay evaluation for recursive structs
state.dec.ignoreStruct(*enginePtr)
}
case wire.GobEncoderT != nil, wire.BinaryMarshalerT != nil, wire.TextMarshalerT != nil:
- op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
+ op = func(i *decInstr, state *decoderState, value reflect.Value) {
state.dec.ignoreGobDecoder(state)
}
}
@@ -979,7 +904,7 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId) decOp {
// gobDecodeOpFor returns the op for a type that is known to implement
// GobDecoder.
-func (dec *Decoder) gobDecodeOpFor(ut *userTypeInfo) (*decOp, int) {
+func (dec *Decoder) gobDecodeOpFor(ut *userTypeInfo) *decOp {
rcvrType := ut.user
if ut.decIndir == -1 {
rcvrType = reflect.PtrTo(rcvrType)
@@ -989,25 +914,14 @@ func (dec *Decoder) gobDecodeOpFor(ut *userTypeInfo) (*decOp, int) {
}
}
var op decOp
- op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
- // Caller has gotten us to within one indirection of our value.
- if i.indir > 0 {
- if *(*unsafe.Pointer)(p) == nil {
- *(*unsafe.Pointer)(p) = unsafe.Pointer(reflect.New(ut.base).Pointer())
- }
+ op = func(i *decInstr, state *decoderState, value reflect.Value) {
+ // We now have the base type. We need its address if the receiver is a pointer.
+ if value.Kind() != reflect.Ptr && rcvrType.Kind() == reflect.Ptr {
+ value = value.Addr()
}
- // Now p is a pointer to the base type. Do we need to climb out to
- // get to the receiver type?
- var v reflect.Value
- if ut.decIndir == -1 {
- v = reflect.NewAt(rcvrType, unsafe.Pointer(&p)).Elem()
- } else {
- v = reflect.NewAt(rcvrType, p).Elem()
- }
- state.dec.decodeGobDecoder(ut, state, v)
+ state.dec.decodeGobDecoder(ut, state, value)
}
- return &op, int(ut.indir)
-
+ return &op
}
// compatibleType asks: Are these two gob Types compatible?
@@ -1108,9 +1022,9 @@ func (dec *Decoder) compileSingle(remoteId typeId, ut *userTypeInfo) (engine *de
}
return nil, errors.New("gob: decoding into local type " + name + ", received remote type " + remoteType)
}
- op, indir := dec.decOpFor(remoteId, rt, name, make(map[reflect.Type]*decOp))
+ op := dec.decOpFor(remoteId, rt, name, make(map[reflect.Type]*decOp))
ovfl := errors.New(`value for "` + name + `" out of range`)
- engine.instr[singletonField] = decInstr{*op, singletonField, indir, 0, ovfl}
+ engine.instr[singletonField] = decInstr{*op, singletonField, nil, ovfl}
engine.numInstr = 1
return
}
@@ -1121,7 +1035,7 @@ func (dec *Decoder) compileIgnoreSingle(remoteId typeId) (engine *decEngine, err
engine.instr = make([]decInstr, 1) // one item
op := dec.decIgnoreOpFor(remoteId)
ovfl := overflow(dec.typeString(remoteId))
- engine.instr[0] = decInstr{op, 0, 0, 0, ovfl}
+ engine.instr[0] = decInstr{op, 0, nil, ovfl}
engine.numInstr = 1
return
}
@@ -1164,14 +1078,14 @@ func (dec *Decoder) compileDec(remoteId typeId, ut *userTypeInfo) (engine *decEn
// TODO(r): anonymous names
if !present || !isExported(wireField.Name) {
op := dec.decIgnoreOpFor(wireField.Id)
- engine.instr[fieldnum] = decInstr{op, fieldnum, 0, 0, ovfl}
+ engine.instr[fieldnum] = decInstr{op, fieldnum, nil, ovfl}
continue
}
if !dec.compatibleType(localField.Type, wireField.Id, make(map[reflect.Type]typeId)) {
errorf("wrong type (%s) for received field %s.%s", localField.Type, wireStruct.Name, wireField.Name)
}
- op, indir := dec.decOpFor(wireField.Id, localField.Type, localField.Name, seen)
- engine.instr[fieldnum] = decInstr{*op, fieldnum, indir, uintptr(localField.Offset), ovfl}
+ op := dec.decOpFor(wireField.Id, localField.Type, localField.Name, seen)
+ engine.instr[fieldnum] = decInstr{*op, fieldnum, localField.Index, ovfl}
engine.numInstr++
}
return
@@ -1222,22 +1136,23 @@ func (dec *Decoder) getIgnoreEnginePtr(wireId typeId) (enginePtr **decEngine, er
return
}
-// decodeValue decodes the data stream representing a value and stores it in val.
-func (dec *Decoder) decodeValue(wireId typeId, val reflect.Value) {
+// decodeValue decodes the data stream representing a value and stores it in value.
+func (dec *Decoder) decodeValue(wireId typeId, value reflect.Value) {
defer catchError(&dec.err)
// If the value is nil, it means we should just ignore this item.
- if !val.IsValid() {
+ if !value.IsValid() {
dec.decodeIgnoredValue(wireId)
return
}
// Dereference down to the underlying type.
- ut := userType(val.Type())
+ ut := userType(value.Type())
base := ut.base
var enginePtr **decEngine
enginePtr, dec.err = dec.getDecEnginePtr(wireId, ut)
if dec.err != nil {
return
}
+ value = decAlloc(value)
engine := *enginePtr
if st := base; st.Kind() == reflect.Struct && ut.externalDec == 0 {
if engine.numInstr == 0 && st.NumField() > 0 &&
@@ -1245,9 +1160,9 @@ func (dec *Decoder) decodeValue(wireId typeId, val reflect.Value) {
name := base.Name()
errorf("type mismatch: no fields matched compiling decoder for %s", name)
}
- dec.decodeStruct(engine, ut, unsafeAddr(val), ut.indir)
+ dec.decodeStruct(engine, ut, value)
} else {
- dec.decodeSingle(engine, ut, unsafeAddr(val))
+ dec.decodeSingle(engine, ut, value)
}
}
@@ -1293,21 +1208,6 @@ func init() {
decOpTable[reflect.Uintptr] = uop
}
-// Gob assumes it can call UnsafeAddr on any Value
-// in order to get a pointer it can copy data from.
-// Values that have just been created and do not point
-// into existing structs or slices cannot be addressed,
-// so simulate it by returning a pointer to a copy.
-// Each call allocates once.
-func unsafeAddr(v reflect.Value) unsafe.Pointer {
- if v.CanAddr() {
- return unsafe.Pointer(v.UnsafeAddr())
- }
- x := reflect.New(v.Type()).Elem()
- x.Set(v)
- return unsafe.Pointer(x.UnsafeAddr())
-}
-
// Gob depends on being able to take the address
// of zeroed Values it creates, so use this wrapper instead
// of the standard reflect.Zero.
OpenPOWER on IntegriCloud