xref: /aosp_15_r20/external/golang-protobuf/internal/impl/pointer_unsafe.go (revision 1c12ee1efe575feb122dbf939ff15148a3b3e8f2)
1*1c12ee1eSDan Willemsen// Copyright 2018 The Go Authors. All rights reserved.
2*1c12ee1eSDan Willemsen// Use of this source code is governed by a BSD-style
3*1c12ee1eSDan Willemsen// license that can be found in the LICENSE file.
4*1c12ee1eSDan Willemsen
5*1c12ee1eSDan Willemsen//go:build !purego && !appengine
6*1c12ee1eSDan Willemsen// +build !purego,!appengine
7*1c12ee1eSDan Willemsen
8*1c12ee1eSDan Willemsenpackage impl
9*1c12ee1eSDan Willemsen
10*1c12ee1eSDan Willemsenimport (
11*1c12ee1eSDan Willemsen	"reflect"
12*1c12ee1eSDan Willemsen	"sync/atomic"
13*1c12ee1eSDan Willemsen	"unsafe"
14*1c12ee1eSDan Willemsen)
15*1c12ee1eSDan Willemsen
16*1c12ee1eSDan Willemsenconst UnsafeEnabled = true
17*1c12ee1eSDan Willemsen
18*1c12ee1eSDan Willemsen// Pointer is an opaque pointer type.
19*1c12ee1eSDan Willemsentype Pointer unsafe.Pointer
20*1c12ee1eSDan Willemsen
21*1c12ee1eSDan Willemsen// offset represents the offset to a struct field, accessible from a pointer.
22*1c12ee1eSDan Willemsen// The offset is the byte offset to the field from the start of the struct.
23*1c12ee1eSDan Willemsentype offset uintptr
24*1c12ee1eSDan Willemsen
25*1c12ee1eSDan Willemsen// offsetOf returns a field offset for the struct field.
26*1c12ee1eSDan Willemsenfunc offsetOf(f reflect.StructField, x exporter) offset {
27*1c12ee1eSDan Willemsen	return offset(f.Offset)
28*1c12ee1eSDan Willemsen}
29*1c12ee1eSDan Willemsen
30*1c12ee1eSDan Willemsen// IsValid reports whether the offset is valid.
31*1c12ee1eSDan Willemsenfunc (f offset) IsValid() bool { return f != invalidOffset }
32*1c12ee1eSDan Willemsen
33*1c12ee1eSDan Willemsen// invalidOffset is an invalid field offset.
34*1c12ee1eSDan Willemsenvar invalidOffset = ^offset(0)
35*1c12ee1eSDan Willemsen
36*1c12ee1eSDan Willemsen// zeroOffset is a noop when calling pointer.Apply.
37*1c12ee1eSDan Willemsenvar zeroOffset = offset(0)
38*1c12ee1eSDan Willemsen
39*1c12ee1eSDan Willemsen// pointer is a pointer to a message struct or field.
40*1c12ee1eSDan Willemsentype pointer struct{ p unsafe.Pointer }
41*1c12ee1eSDan Willemsen
42*1c12ee1eSDan Willemsen// pointerOf returns p as a pointer.
43*1c12ee1eSDan Willemsenfunc pointerOf(p Pointer) pointer {
44*1c12ee1eSDan Willemsen	return pointer{p: unsafe.Pointer(p)}
45*1c12ee1eSDan Willemsen}
46*1c12ee1eSDan Willemsen
47*1c12ee1eSDan Willemsen// pointerOfValue returns v as a pointer.
48*1c12ee1eSDan Willemsenfunc pointerOfValue(v reflect.Value) pointer {
49*1c12ee1eSDan Willemsen	return pointer{p: unsafe.Pointer(v.Pointer())}
50*1c12ee1eSDan Willemsen}
51*1c12ee1eSDan Willemsen
52*1c12ee1eSDan Willemsen// pointerOfIface returns the pointer portion of an interface.
53*1c12ee1eSDan Willemsenfunc pointerOfIface(v interface{}) pointer {
54*1c12ee1eSDan Willemsen	type ifaceHeader struct {
55*1c12ee1eSDan Willemsen		Type unsafe.Pointer
56*1c12ee1eSDan Willemsen		Data unsafe.Pointer
57*1c12ee1eSDan Willemsen	}
58*1c12ee1eSDan Willemsen	return pointer{p: (*ifaceHeader)(unsafe.Pointer(&v)).Data}
59*1c12ee1eSDan Willemsen}
60*1c12ee1eSDan Willemsen
61*1c12ee1eSDan Willemsen// IsNil reports whether the pointer is nil.
62*1c12ee1eSDan Willemsenfunc (p pointer) IsNil() bool {
63*1c12ee1eSDan Willemsen	return p.p == nil
64*1c12ee1eSDan Willemsen}
65*1c12ee1eSDan Willemsen
66*1c12ee1eSDan Willemsen// Apply adds an offset to the pointer to derive a new pointer
67*1c12ee1eSDan Willemsen// to a specified field. The pointer must be valid and pointing at a struct.
68*1c12ee1eSDan Willemsenfunc (p pointer) Apply(f offset) pointer {
69*1c12ee1eSDan Willemsen	if p.IsNil() {
70*1c12ee1eSDan Willemsen		panic("invalid nil pointer")
71*1c12ee1eSDan Willemsen	}
72*1c12ee1eSDan Willemsen	return pointer{p: unsafe.Pointer(uintptr(p.p) + uintptr(f))}
73*1c12ee1eSDan Willemsen}
74*1c12ee1eSDan Willemsen
75*1c12ee1eSDan Willemsen// AsValueOf treats p as a pointer to an object of type t and returns the value.
76*1c12ee1eSDan Willemsen// It is equivalent to reflect.ValueOf(p.AsIfaceOf(t))
77*1c12ee1eSDan Willemsenfunc (p pointer) AsValueOf(t reflect.Type) reflect.Value {
78*1c12ee1eSDan Willemsen	return reflect.NewAt(t, p.p)
79*1c12ee1eSDan Willemsen}
80*1c12ee1eSDan Willemsen
81*1c12ee1eSDan Willemsen// AsIfaceOf treats p as a pointer to an object of type t and returns the value.
82*1c12ee1eSDan Willemsen// It is equivalent to p.AsValueOf(t).Interface()
83*1c12ee1eSDan Willemsenfunc (p pointer) AsIfaceOf(t reflect.Type) interface{} {
84*1c12ee1eSDan Willemsen	// TODO: Use tricky unsafe magic to directly create ifaceHeader.
85*1c12ee1eSDan Willemsen	return p.AsValueOf(t).Interface()
86*1c12ee1eSDan Willemsen}
87*1c12ee1eSDan Willemsen
88*1c12ee1eSDan Willemsenfunc (p pointer) Bool() *bool                           { return (*bool)(p.p) }
89*1c12ee1eSDan Willemsenfunc (p pointer) BoolPtr() **bool                       { return (**bool)(p.p) }
90*1c12ee1eSDan Willemsenfunc (p pointer) BoolSlice() *[]bool                    { return (*[]bool)(p.p) }
91*1c12ee1eSDan Willemsenfunc (p pointer) Int32() *int32                         { return (*int32)(p.p) }
92*1c12ee1eSDan Willemsenfunc (p pointer) Int32Ptr() **int32                     { return (**int32)(p.p) }
93*1c12ee1eSDan Willemsenfunc (p pointer) Int32Slice() *[]int32                  { return (*[]int32)(p.p) }
94*1c12ee1eSDan Willemsenfunc (p pointer) Int64() *int64                         { return (*int64)(p.p) }
95*1c12ee1eSDan Willemsenfunc (p pointer) Int64Ptr() **int64                     { return (**int64)(p.p) }
96*1c12ee1eSDan Willemsenfunc (p pointer) Int64Slice() *[]int64                  { return (*[]int64)(p.p) }
97*1c12ee1eSDan Willemsenfunc (p pointer) Uint32() *uint32                       { return (*uint32)(p.p) }
98*1c12ee1eSDan Willemsenfunc (p pointer) Uint32Ptr() **uint32                   { return (**uint32)(p.p) }
99*1c12ee1eSDan Willemsenfunc (p pointer) Uint32Slice() *[]uint32                { return (*[]uint32)(p.p) }
100*1c12ee1eSDan Willemsenfunc (p pointer) Uint64() *uint64                       { return (*uint64)(p.p) }
101*1c12ee1eSDan Willemsenfunc (p pointer) Uint64Ptr() **uint64                   { return (**uint64)(p.p) }
102*1c12ee1eSDan Willemsenfunc (p pointer) Uint64Slice() *[]uint64                { return (*[]uint64)(p.p) }
103*1c12ee1eSDan Willemsenfunc (p pointer) Float32() *float32                     { return (*float32)(p.p) }
104*1c12ee1eSDan Willemsenfunc (p pointer) Float32Ptr() **float32                 { return (**float32)(p.p) }
105*1c12ee1eSDan Willemsenfunc (p pointer) Float32Slice() *[]float32              { return (*[]float32)(p.p) }
106*1c12ee1eSDan Willemsenfunc (p pointer) Float64() *float64                     { return (*float64)(p.p) }
107*1c12ee1eSDan Willemsenfunc (p pointer) Float64Ptr() **float64                 { return (**float64)(p.p) }
108*1c12ee1eSDan Willemsenfunc (p pointer) Float64Slice() *[]float64              { return (*[]float64)(p.p) }
109*1c12ee1eSDan Willemsenfunc (p pointer) String() *string                       { return (*string)(p.p) }
110*1c12ee1eSDan Willemsenfunc (p pointer) StringPtr() **string                   { return (**string)(p.p) }
111*1c12ee1eSDan Willemsenfunc (p pointer) StringSlice() *[]string                { return (*[]string)(p.p) }
112*1c12ee1eSDan Willemsenfunc (p pointer) Bytes() *[]byte                        { return (*[]byte)(p.p) }
113*1c12ee1eSDan Willemsenfunc (p pointer) BytesPtr() **[]byte                    { return (**[]byte)(p.p) }
114*1c12ee1eSDan Willemsenfunc (p pointer) BytesSlice() *[][]byte                 { return (*[][]byte)(p.p) }
115*1c12ee1eSDan Willemsenfunc (p pointer) WeakFields() *weakFields               { return (*weakFields)(p.p) }
116*1c12ee1eSDan Willemsenfunc (p pointer) Extensions() *map[int32]ExtensionField { return (*map[int32]ExtensionField)(p.p) }
117*1c12ee1eSDan Willemsen
118*1c12ee1eSDan Willemsenfunc (p pointer) Elem() pointer {
119*1c12ee1eSDan Willemsen	return pointer{p: *(*unsafe.Pointer)(p.p)}
120*1c12ee1eSDan Willemsen}
121*1c12ee1eSDan Willemsen
122*1c12ee1eSDan Willemsen// PointerSlice loads []*T from p as a []pointer.
123*1c12ee1eSDan Willemsen// The value returned is aliased with the original slice.
124*1c12ee1eSDan Willemsen// This behavior differs from the implementation in pointer_reflect.go.
125*1c12ee1eSDan Willemsenfunc (p pointer) PointerSlice() []pointer {
126*1c12ee1eSDan Willemsen	// Super-tricky - p should point to a []*T where T is a
127*1c12ee1eSDan Willemsen	// message type. We load it as []pointer.
128*1c12ee1eSDan Willemsen	return *(*[]pointer)(p.p)
129*1c12ee1eSDan Willemsen}
130*1c12ee1eSDan Willemsen
131*1c12ee1eSDan Willemsen// AppendPointerSlice appends v to p, which must be a []*T.
132*1c12ee1eSDan Willemsenfunc (p pointer) AppendPointerSlice(v pointer) {
133*1c12ee1eSDan Willemsen	*(*[]pointer)(p.p) = append(*(*[]pointer)(p.p), v)
134*1c12ee1eSDan Willemsen}
135*1c12ee1eSDan Willemsen
136*1c12ee1eSDan Willemsen// SetPointer sets *p to v.
137*1c12ee1eSDan Willemsenfunc (p pointer) SetPointer(v pointer) {
138*1c12ee1eSDan Willemsen	*(*unsafe.Pointer)(p.p) = (unsafe.Pointer)(v.p)
139*1c12ee1eSDan Willemsen}
140*1c12ee1eSDan Willemsen
141*1c12ee1eSDan Willemsen// Static check that MessageState does not exceed the size of a pointer.
142*1c12ee1eSDan Willemsenconst _ = uint(unsafe.Sizeof(unsafe.Pointer(nil)) - unsafe.Sizeof(MessageState{}))
143*1c12ee1eSDan Willemsen
144*1c12ee1eSDan Willemsenfunc (Export) MessageStateOf(p Pointer) *messageState {
145*1c12ee1eSDan Willemsen	// Super-tricky - see documentation on MessageState.
146*1c12ee1eSDan Willemsen	return (*messageState)(unsafe.Pointer(p))
147*1c12ee1eSDan Willemsen}
148*1c12ee1eSDan Willemsenfunc (ms *messageState) pointer() pointer {
149*1c12ee1eSDan Willemsen	// Super-tricky - see documentation on MessageState.
150*1c12ee1eSDan Willemsen	return pointer{p: unsafe.Pointer(ms)}
151*1c12ee1eSDan Willemsen}
152*1c12ee1eSDan Willemsenfunc (ms *messageState) messageInfo() *MessageInfo {
153*1c12ee1eSDan Willemsen	mi := ms.LoadMessageInfo()
154*1c12ee1eSDan Willemsen	if mi == nil {
155*1c12ee1eSDan Willemsen		panic("invalid nil message info; this suggests memory corruption due to a race or shallow copy on the message struct")
156*1c12ee1eSDan Willemsen	}
157*1c12ee1eSDan Willemsen	return mi
158*1c12ee1eSDan Willemsen}
159*1c12ee1eSDan Willemsenfunc (ms *messageState) LoadMessageInfo() *MessageInfo {
160*1c12ee1eSDan Willemsen	return (*MessageInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&ms.atomicMessageInfo))))
161*1c12ee1eSDan Willemsen}
162*1c12ee1eSDan Willemsenfunc (ms *messageState) StoreMessageInfo(mi *MessageInfo) {
163*1c12ee1eSDan Willemsen	atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&ms.atomicMessageInfo)), unsafe.Pointer(mi))
164*1c12ee1eSDan Willemsen}
165*1c12ee1eSDan Willemsen
166*1c12ee1eSDan Willemsentype atomicNilMessage struct{ p unsafe.Pointer } // p is a *messageReflectWrapper
167*1c12ee1eSDan Willemsen
168*1c12ee1eSDan Willemsenfunc (m *atomicNilMessage) Init(mi *MessageInfo) *messageReflectWrapper {
169*1c12ee1eSDan Willemsen	if p := atomic.LoadPointer(&m.p); p != nil {
170*1c12ee1eSDan Willemsen		return (*messageReflectWrapper)(p)
171*1c12ee1eSDan Willemsen	}
172*1c12ee1eSDan Willemsen	w := &messageReflectWrapper{mi: mi}
173*1c12ee1eSDan Willemsen	atomic.CompareAndSwapPointer(&m.p, nil, (unsafe.Pointer)(w))
174*1c12ee1eSDan Willemsen	return (*messageReflectWrapper)(atomic.LoadPointer(&m.p))
175*1c12ee1eSDan Willemsen}
176