]> Cypherpunks repositories - gostls13.git/commitdiff
reflect: restore Value.Pointer implementation
authorCuong Manh Le <cuong.manhle.vn@gmail.com>
Tue, 19 Oct 2021 17:09:09 +0000 (00:09 +0700)
committerCuong Manh Le <cuong.manhle.vn@gmail.com>
Tue, 19 Oct 2021 18:55:51 +0000 (18:55 +0000)
CL 350691 added Value.UnsafePointer and make Value.Pointer call it
internally. It has a downside that Value.Pointer can now eligible to be
inlined, thus making un-intentional side effect, like the test in
fixedbugs/issue15329.go becomes flaky.

This CL restore Value.Pointer original implementation, pre CL 350691,
with the deprecation TODO removed.

Fixes #49067

Change-Id: I735af182f8e729294333ca906ffc062f477cfc99
Reviewed-on: https://go-review.googlesource.com/c/go/+/356949
Trust: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
src/reflect/value.go

index 1d385f6bf9f943473f72680b5cfa4cbd164a3356..63faa0496443c8322ce552c9ac690f6c4bce1da6 100644 (file)
@@ -1936,7 +1936,42 @@ func (v Value) OverflowUint(x uint64) bool {
 //
 // Deprecated: use uintptr(Value.UnsafePointer()) to get the equivalent result.
 func (v Value) Pointer() uintptr {
-       return uintptr(v.UnsafePointer())
+       k := v.kind()
+       switch k {
+       case Ptr:
+               if v.typ.ptrdata == 0 {
+                       // Handle pointers to go:notinheap types directly,
+                       // so we never materialize such pointers as an
+                       // unsafe.Pointer. (Such pointers are always indirect.)
+                       // See issue 42076.
+                       return *(*uintptr)(v.ptr)
+               }
+               fallthrough
+       case Chan, Map, UnsafePointer:
+               return uintptr(v.pointer())
+       case Func:
+               if v.flag&flagMethod != 0 {
+                       // As the doc comment says, the returned pointer is an
+                       // underlying code pointer but not necessarily enough to
+                       // identify a single function uniquely. All method expressions
+                       // created via reflect have the same underlying code pointer,
+                       // so their Pointers are equal. The function used here must
+                       // match the one used in makeMethodValue.
+                       f := methodValueCall
+                       return **(**uintptr)(unsafe.Pointer(&f))
+               }
+               p := v.pointer()
+               // Non-nil func value points at data block.
+               // First word of data block is actual code.
+               if p != nil {
+                       p = *(*unsafe.Pointer)(p)
+               }
+               return uintptr(p)
+
+       case Slice:
+               return (*SliceHeader)(v.ptr).Data
+       }
+       panic(&ValueError{"reflect.Value.Pointer", v.kind()})
 }
 
 // Recv receives and returns a value from the channel v.