Joe Tsai | eeca8bb | 2018-12-04 16:24:22 -0800 | [diff] [blame] | 1 | // Copyright 2012 The Go Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style |
| 3 | // license that can be found in the LICENSE file. |
| 4 | |
| 5 | // +build !purego |
| 6 | |
| 7 | package protoV1 |
| 8 | |
| 9 | import ( |
| 10 | "reflect" |
| 11 | "sync/atomic" |
| 12 | "unsafe" |
| 13 | |
| 14 | "github.com/golang/protobuf/protoapi" |
| 15 | ) |
| 16 | |
| 17 | // A field identifies a field in a struct, accessible from a pointer. |
| 18 | // In this implementation, a field is identified by its byte offset from the start of the struct. |
| 19 | type field uintptr |
| 20 | |
| 21 | // toField returns a field equivalent to the given reflect field. |
| 22 | func toField(f *reflect.StructField) field { |
| 23 | return field(f.Offset) |
| 24 | } |
| 25 | |
| 26 | // invalidField is an invalid field identifier. |
| 27 | const invalidField = ^field(0) |
| 28 | |
| 29 | // zeroField is a noop when calling pointer.offset. |
| 30 | const zeroField = field(0) |
| 31 | |
| 32 | // IsValid reports whether the field identifier is valid. |
| 33 | func (f field) IsValid() bool { |
| 34 | return f != invalidField |
| 35 | } |
| 36 | |
| 37 | // The pointer type below is for the new table-driven encoder/decoder. |
| 38 | // The implementation here uses unsafe.Pointer to create a generic pointer. |
| 39 | // In pointer_reflect.go we use reflect instead of unsafe to implement |
| 40 | // the same (but slower) interface. |
| 41 | type pointer struct { |
| 42 | p unsafe.Pointer |
| 43 | } |
| 44 | |
| 45 | // toPointer converts an interface of pointer type to a pointer |
| 46 | // that points to the same target. |
| 47 | func toPointer(i *Message) pointer { |
| 48 | // Super-tricky - read pointer out of data word of interface value. |
| 49 | // Saves ~25ns over the equivalent: |
| 50 | // return valToPointer(reflect.ValueOf(*i)) |
| 51 | return pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]} |
| 52 | } |
| 53 | |
| 54 | // valToPointer converts v to a pointer. v must be of pointer type. |
| 55 | func valToPointer(v reflect.Value) pointer { |
| 56 | return pointer{p: unsafe.Pointer(v.Pointer())} |
| 57 | } |
| 58 | |
| 59 | // offset converts from a pointer to a structure to a pointer to |
| 60 | // one of its fields. |
| 61 | func (p pointer) offset(f field) pointer { |
| 62 | // For safety, we should panic if !f.IsValid, however calling panic causes |
| 63 | // this to no longer be inlineable, which is a serious performance cost. |
| 64 | /* |
| 65 | if !f.IsValid() { |
| 66 | panic("invalid field") |
| 67 | } |
| 68 | */ |
| 69 | return pointer{p: unsafe.Pointer(uintptr(p.p) + uintptr(f))} |
| 70 | } |
| 71 | |
| 72 | func (p pointer) isNil() bool { |
| 73 | return p.p == nil |
| 74 | } |
| 75 | |
| 76 | func (p pointer) toInt64() *int64 { |
| 77 | return (*int64)(p.p) |
| 78 | } |
| 79 | func (p pointer) toInt64Ptr() **int64 { |
| 80 | return (**int64)(p.p) |
| 81 | } |
| 82 | func (p pointer) toInt64Slice() *[]int64 { |
| 83 | return (*[]int64)(p.p) |
| 84 | } |
| 85 | func (p pointer) toInt32() *int32 { |
| 86 | return (*int32)(p.p) |
| 87 | } |
| 88 | |
| 89 | // See pointer_reflect.go for why toInt32Ptr/Slice doesn't exist. |
| 90 | /* |
| 91 | func (p pointer) toInt32Ptr() **int32 { |
| 92 | return (**int32)(p.p) |
| 93 | } |
| 94 | func (p pointer) toInt32Slice() *[]int32 { |
| 95 | return (*[]int32)(p.p) |
| 96 | } |
| 97 | */ |
| 98 | func (p pointer) setInt32Ptr(v int32) { |
| 99 | *(**int32)(p.p) = &v |
| 100 | } |
| 101 | |
| 102 | // TODO: Can we get rid of appendInt32Slice and use setInt32Slice instead? |
| 103 | func (p pointer) appendInt32Slice(v int32) { |
| 104 | s := (*[]int32)(p.p) |
| 105 | *s = append(*s, v) |
| 106 | } |
| 107 | |
| 108 | func (p pointer) toUint64() *uint64 { |
| 109 | return (*uint64)(p.p) |
| 110 | } |
| 111 | func (p pointer) toUint64Ptr() **uint64 { |
| 112 | return (**uint64)(p.p) |
| 113 | } |
| 114 | func (p pointer) toUint64Slice() *[]uint64 { |
| 115 | return (*[]uint64)(p.p) |
| 116 | } |
| 117 | func (p pointer) toUint32() *uint32 { |
| 118 | return (*uint32)(p.p) |
| 119 | } |
| 120 | func (p pointer) toUint32Ptr() **uint32 { |
| 121 | return (**uint32)(p.p) |
| 122 | } |
| 123 | func (p pointer) toUint32Slice() *[]uint32 { |
| 124 | return (*[]uint32)(p.p) |
| 125 | } |
| 126 | func (p pointer) toBool() *bool { |
| 127 | return (*bool)(p.p) |
| 128 | } |
| 129 | func (p pointer) toBoolPtr() **bool { |
| 130 | return (**bool)(p.p) |
| 131 | } |
| 132 | func (p pointer) toBoolSlice() *[]bool { |
| 133 | return (*[]bool)(p.p) |
| 134 | } |
| 135 | func (p pointer) toFloat64() *float64 { |
| 136 | return (*float64)(p.p) |
| 137 | } |
| 138 | func (p pointer) toFloat64Ptr() **float64 { |
| 139 | return (**float64)(p.p) |
| 140 | } |
| 141 | func (p pointer) toFloat64Slice() *[]float64 { |
| 142 | return (*[]float64)(p.p) |
| 143 | } |
| 144 | func (p pointer) toFloat32() *float32 { |
| 145 | return (*float32)(p.p) |
| 146 | } |
| 147 | func (p pointer) toFloat32Ptr() **float32 { |
| 148 | return (**float32)(p.p) |
| 149 | } |
| 150 | func (p pointer) toFloat32Slice() *[]float32 { |
| 151 | return (*[]float32)(p.p) |
| 152 | } |
| 153 | func (p pointer) toString() *string { |
| 154 | return (*string)(p.p) |
| 155 | } |
| 156 | func (p pointer) toStringPtr() **string { |
| 157 | return (**string)(p.p) |
| 158 | } |
| 159 | func (p pointer) toStringSlice() *[]string { |
| 160 | return (*[]string)(p.p) |
| 161 | } |
| 162 | func (p pointer) toBytes() *[]byte { |
| 163 | return (*[]byte)(p.p) |
| 164 | } |
| 165 | func (p pointer) toBytesSlice() *[][]byte { |
| 166 | return (*[][]byte)(p.p) |
| 167 | } |
| 168 | func (p pointer) toExtensions() *protoapi.XXX_InternalExtensions { |
| 169 | return (*protoapi.XXX_InternalExtensions)(p.p) |
| 170 | } |
| 171 | func (p pointer) toOldExtensions() *map[int32]protoapi.ExtensionField { |
| 172 | return (*map[int32]protoapi.ExtensionField)(p.p) |
| 173 | } |
| 174 | |
| 175 | // getPointer loads the pointer at p and returns it. |
| 176 | func (p pointer) getPointer() pointer { |
| 177 | return pointer{p: *(*unsafe.Pointer)(p.p)} |
| 178 | } |
| 179 | |
| 180 | // setPointer stores the pointer q at p. |
| 181 | func (p pointer) setPointer(q pointer) { |
| 182 | *(*unsafe.Pointer)(p.p) = q.p |
| 183 | } |
| 184 | |
| 185 | // append q to the slice pointed to by p. |
| 186 | func (p pointer) appendPointer(q pointer) { |
| 187 | s := (*[]unsafe.Pointer)(p.p) |
| 188 | *s = append(*s, q.p) |
| 189 | } |
| 190 | |
| 191 | // asPointerTo returns a reflect.Value that is a pointer to an |
| 192 | // object of type t stored at p. |
| 193 | func (p pointer) asPointerTo(t reflect.Type) reflect.Value { |
| 194 | return reflect.NewAt(t, p.p) |
| 195 | } |
| 196 | |
| 197 | func atomicLoadUnmarshalInfo(p **unmarshalInfo) *unmarshalInfo { |
| 198 | return (*unmarshalInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p)))) |
| 199 | } |
| 200 | func atomicStoreUnmarshalInfo(p **unmarshalInfo, v *unmarshalInfo) { |
| 201 | atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v)) |
| 202 | } |