aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/reflect/value.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/reflect/value.go')
-rw-r--r--libgo/go/reflect/value.go455
1 files changed, 364 insertions, 91 deletions
diff --git a/libgo/go/reflect/value.go b/libgo/go/reflect/value.go
index 300ef1a..54ebd6f 100644
--- a/libgo/go/reflect/value.go
+++ b/libgo/go/reflect/value.go
@@ -5,6 +5,8 @@
package reflect
import (
+ "errors"
+ "internal/goarch"
"internal/itoa"
"internal/unsafeheader"
"math"
@@ -12,8 +14,6 @@ import (
"unsafe"
)
-const ptrSize = 4 << (^uintptr(0) >> 63) // unsafe.Sizeof(uintptr(0)) but an ideal const
-
// Value is the reflection interface to a Go value.
//
// Not all methods apply to all kinds of values. Restrictions,
@@ -91,10 +91,10 @@ func (f flag) ro() flag {
}
// pointer returns the underlying pointer represented by v.
-// v.Kind() must be Ptr, Map, Chan, Func, or UnsafePointer
-// if v.Kind() == Ptr, the base type must not be go:notinheap.
+// v.Kind() must be Pointer, Map, Chan, Func, or UnsafePointer
+// if v.Kind() == Pointer, the base type must not be go:notinheap.
func (v Value) pointer() unsafe.Pointer {
- if v.typ.size != ptrSize || !v.typ.pointers() {
+ if v.typ.size != goarch.PtrSize || !v.typ.pointers() {
panic("can't call pointer on a non-pointer Value")
}
if v.flag&flagIndir != 0 {
@@ -104,9 +104,9 @@ func (v Value) pointer() unsafe.Pointer {
}
// packEface converts v to the empty interface.
-func packEface(v Value) interface{} {
+func packEface(v Value) any {
t := v.typ
- var i interface{}
+ var i any
e := (*emptyInterface)(unsafe.Pointer(&i))
// First, fill in the data portion of the interface.
switch {
@@ -141,7 +141,7 @@ func packEface(v Value) interface{} {
}
// unpackEface converts the empty interface i to a Value.
-func unpackEface(i interface{}) Value {
+func unpackEface(i any) Value {
e := (*emptyInterface)(unsafe.Pointer(&i))
// NOTE: don't read e.word until we know whether it is really a pointer or not.
t := e.typ
@@ -272,7 +272,7 @@ func (v Value) Addr() Value {
// Preserve flagRO instead of using v.flag.ro() so that
// v.Addr().Elem() is equivalent to v (#32772)
fl := v.flag & flagRO
- return Value{v.typ.ptrTo(), v.ptr, fl | flag(Ptr)}
+ return Value{v.typ.ptrTo(), v.ptr, fl | flag(Pointer)}
}
// Bool returns v's underlying value.
@@ -349,7 +349,7 @@ func (v Value) CallSlice(in []Value) []Value {
return v.call("CallSlice", in)
}
-var callGC bool // for testing; see TestCallMethodJump
+var callGC bool // for testing; see TestCallMethodJump and TestCallArgLive
const debugReflectCall = false
@@ -596,6 +596,16 @@ func (v Value) Close() {
chanclose(v.pointer())
}
+// CanComplex reports whether Complex can be used without panicking.
+func (v Value) CanComplex() bool {
+ switch v.kind() {
+ case Complex64, Complex128:
+ return true
+ default:
+ return false
+ }
+}
+
// Complex returns v's underlying value, as a complex128.
// It panics if v's Kind is not Complex64 or Complex128
func (v Value) Complex() complex128 {
@@ -611,17 +621,17 @@ func (v Value) Complex() complex128 {
// Elem returns the value that the interface v contains
// or that the pointer v points to.
-// It panics if v's Kind is not Interface or Ptr.
+// It panics if v's Kind is not Interface or Pointer.
// It returns the zero Value if v is nil.
func (v Value) Elem() Value {
k := v.kind()
switch k {
case Interface:
- var eface interface{}
+ var eface any
if v.typ.NumMethod() == 0 {
- eface = *(*interface{})(v.ptr)
+ eface = *(*any)(v.ptr)
} else {
- eface = (interface{})(*(*interface {
+ eface = (any)(*(*interface {
M()
})(v.ptr))
}
@@ -630,9 +640,24 @@ func (v Value) Elem() Value {
x.flag |= v.flag.ro()
}
return x
- case Ptr:
+ case Pointer:
ptr := v.ptr
if v.flag&flagIndir != 0 {
+ if ifaceIndir(v.typ) {
+ // This is a pointer to a not-in-heap object. ptr points to a uintptr
+ // in the heap. That uintptr is the address of a not-in-heap object.
+ // In general, pointers to not-in-heap objects can be total junk.
+ // But Elem() is asking to dereference it, so the user has asserted
+ // that at least it is a valid pointer (not just an integer stored in
+ // a pointer slot). So let's check, to make sure that it isn't a pointer
+ // that the runtime will crash on if it sees it during GC or write barriers.
+ // Since it is a not-in-heap pointer, all pointers to the heap are
+ // forbidden! That makes the test pretty easy.
+ // See issue 48399.
+ if !verifyNotInHeapPtr(*(*uintptr)(ptr)) {
+ panic("reflect: reflect.Value.Elem on an invalid notinheap pointer")
+ }
+ }
ptr = *(*unsafe.Pointer)(ptr)
}
// The returned value's address is v's value.
@@ -681,7 +706,8 @@ func (v Value) Field(i int) Value {
}
// FieldByIndex returns the nested field corresponding to index.
-// It panics if v's Kind is not struct.
+// It panics if evaluation requires stepping through a nil
+// pointer or a field that is not a struct.
func (v Value) FieldByIndex(index []int) Value {
if len(index) == 1 {
return v.Field(index[0])
@@ -689,7 +715,7 @@ func (v Value) FieldByIndex(index []int) Value {
v.mustBe(Struct)
for i, x := range index {
if i > 0 {
- if v.Kind() == Ptr && v.typ.Elem().Kind() == Struct {
+ if v.Kind() == Pointer && v.typ.Elem().Kind() == Struct {
if v.IsNil() {
panic("reflect: indirection through nil pointer to embedded struct")
}
@@ -701,6 +727,29 @@ func (v Value) FieldByIndex(index []int) Value {
return v
}
+// FieldByIndexErr returns the nested field corresponding to index.
+// It returns an error if evaluation requires stepping through a nil
+// pointer, but panics if it must step through a field that
+// is not a struct.
+func (v Value) FieldByIndexErr(index []int) (Value, error) {
+ if len(index) == 1 {
+ return v.Field(index[0]), nil
+ }
+ v.mustBe(Struct)
+ for i, x := range index {
+ if i > 0 {
+ if v.Kind() == Ptr && v.typ.Elem().Kind() == Struct {
+ if v.IsNil() {
+ return Value{}, errors.New("reflect: indirection through nil pointer to embedded struct field " + v.typ.Elem().Name())
+ }
+ v = v.Elem()
+ }
+ }
+ v = v.Field(x)
+ }
+ return v, nil
+}
+
// FieldByName returns the struct field with the given name.
// It returns the zero Value if no field was found.
// It panics if v's Kind is not struct.
@@ -723,6 +772,16 @@ func (v Value) FieldByNameFunc(match func(string) bool) Value {
return Value{}
}
+// CanFloat reports whether Float can be used without panicking.
+func (v Value) CanFloat() bool {
+ switch v.kind() {
+ case Float32, Float64:
+ return true
+ default:
+ return false
+ }
+}
+
// Float returns v's underlying value, as a float64.
// It panics if v's Kind is not Float32 or Float64
func (v Value) Float() float64 {
@@ -760,7 +819,7 @@ func (v Value) Index(i int) Value {
return Value{typ, val, fl}
case Slice:
- // Element flag same as Elem of Ptr.
+ // Element flag same as Elem of Pointer.
// Addressable, indirect, possibly read-only.
s := (*unsafeheader.Slice)(v.ptr)
if uint(i) >= uint(s.Len) {
@@ -784,6 +843,16 @@ func (v Value) Index(i int) Value {
panic(&ValueError{"reflect.Value.Index", v.kind()})
}
+// CanInt reports whether Int can be used without panicking.
+func (v Value) CanInt() bool {
+ switch v.kind() {
+ case Int, Int8, Int16, Int32, Int64:
+ return true
+ default:
+ return false
+ }
+}
+
// Int returns v's underlying value, as an int64.
// It panics if v's Kind is not Int, Int8, Int16, Int32, or Int64.
func (v Value) Int() int64 {
@@ -817,11 +886,11 @@ func (v Value) CanInterface() bool {
// var i interface{} = (v's underlying value)
// It panics if the Value was obtained by accessing
// unexported struct fields.
-func (v Value) Interface() (i interface{}) {
+func (v Value) Interface() (i any) {
return valueInterface(v, true)
}
-func valueInterface(v Value, safe bool) interface{} {
+func valueInterface(v Value, safe bool) any {
if v.flag == 0 {
panic(&ValueError{"reflect.Value.Interface", Invalid})
}
@@ -850,7 +919,7 @@ func valueInterface(v Value, safe bool) interface{} {
// Empty interface has one layout, all interfaces with
// methods have a second layout.
if v.NumMethod() == 0 {
- return *(*interface{})(v.ptr)
+ return *(*any)(v.ptr)
}
return *(*interface {
M()
@@ -890,7 +959,7 @@ func (v Value) InterfaceData() [2]uintptr {
func (v Value) IsNil() bool {
k := v.kind()
switch k {
- case Chan, Func, Map, Ptr, UnsafePointer:
+ case Chan, Func, Map, Pointer, UnsafePointer:
if v.flag&flagMethod != 0 {
return false
}
@@ -938,7 +1007,7 @@ func (v Value) IsZero() bool {
}
}
return true
- case Chan, Func, Interface, Map, Ptr, Slice, UnsafePointer:
+ case Chan, Func, Interface, Map, Pointer, Slice, UnsafePointer:
return v.IsNil()
case String:
return v.Len() == 0
@@ -999,15 +1068,21 @@ func (v Value) MapIndex(key Value) Value {
// considered unexported. This is consistent with the
// behavior for structs, which allow read but not write
// of unexported fields.
- key = key.assignTo("reflect.Value.MapIndex", tt.key, nil)
- var k unsafe.Pointer
- if key.flag&flagIndir != 0 {
- k = key.ptr
+ var e unsafe.Pointer
+ if key.kind() == String && tt.key.Kind() == String && tt.elem.size <= maxValSize {
+ k := *(*string)(key.ptr)
+ e = mapaccess_faststr(v.typ, v.pointer(), k)
} else {
- k = unsafe.Pointer(&key.ptr)
+ key = key.assignTo("reflect.Value.MapIndex", tt.key, nil)
+ var k unsafe.Pointer
+ if key.flag&flagIndir != 0 {
+ k = key.ptr
+ } else {
+ k = unsafe.Pointer(&key.ptr)
+ }
+ e = mapaccess(v.typ, v.pointer(), k)
}
- e := mapaccess(v.typ, v.pointer(), k)
if e == nil {
return Value{}
}
@@ -1033,11 +1108,12 @@ func (v Value) MapKeys() []Value {
if m != nil {
mlen = maplen(m)
}
- it := mapiterinit(v.typ, m)
+ var it hiter
+ mapiterinit(v.typ, m, &it)
a := make([]Value, mlen)
var i int
for i = 0; i < len(a); i++ {
- key := mapiterkey(it)
+ key := mapiterkey(&it)
if key == nil {
// Someone deleted an entry from the map since we
// called maplen above. It's a data race, but nothing
@@ -1045,59 +1121,154 @@ func (v Value) MapKeys() []Value {
break
}
a[i] = copyVal(keyType, fl, key)
- mapiternext(it)
+ mapiternext(&it)
}
return a[:i]
}
+// hiter's structure matches runtime.hiter's structure.
+// Having a clone here allows us to embed a map iterator
+// inside type MapIter so that MapIters can be re-used
+// without doing any allocations.
+type hiter struct {
+ key unsafe.Pointer
+ elem unsafe.Pointer
+ t unsafe.Pointer
+ h unsafe.Pointer
+ buckets unsafe.Pointer
+ bptr unsafe.Pointer
+ overflow *[]unsafe.Pointer
+ oldoverflow *[]unsafe.Pointer
+ startBucket uintptr
+ offset uint8
+ wrapped bool
+ B uint8
+ i uint8
+ bucket uintptr
+ checkBucket uintptr
+}
+
+func (h *hiter) initialized() bool {
+ return h.t != nil
+}
+
// A MapIter is an iterator for ranging over a map.
// See Value.MapRange.
type MapIter struct {
- m Value
- it unsafe.Pointer
+ m Value
+ hiter hiter
}
-// Key returns the key of the iterator's current map entry.
-func (it *MapIter) Key() Value {
- if it.it == nil {
+// Key returns the key of iter's current map entry.
+func (iter *MapIter) Key() Value {
+ if !iter.hiter.initialized() {
panic("MapIter.Key called before Next")
}
- if mapiterkey(it.it) == nil {
+ iterkey := mapiterkey(&iter.hiter)
+ if iterkey == nil {
panic("MapIter.Key called on exhausted iterator")
}
- t := (*mapType)(unsafe.Pointer(it.m.typ))
+ t := (*mapType)(unsafe.Pointer(iter.m.typ))
ktype := t.key
- return copyVal(ktype, it.m.flag.ro()|flag(ktype.Kind()), mapiterkey(it.it))
+ return copyVal(ktype, iter.m.flag.ro()|flag(ktype.Kind()), iterkey)
}
-// Value returns the value of the iterator's current map entry.
-func (it *MapIter) Value() Value {
- if it.it == nil {
+// SetIterKey assigns to v the key of iter's current map entry.
+// It is equivalent to v.Set(iter.Key()), but it avoids allocating a new Value.
+// As in Go, the key must be assignable to v's type.
+func (v Value) SetIterKey(iter *MapIter) {
+ if !iter.hiter.initialized() {
+ panic("reflect: Value.SetIterKey called before Next")
+ }
+ iterkey := mapiterkey(&iter.hiter)
+ if iterkey == nil {
+ panic("reflect: Value.SetIterKey called on exhausted iterator")
+ }
+
+ v.mustBeAssignable()
+ var target unsafe.Pointer
+ if v.kind() == Interface {
+ target = v.ptr
+ }
+
+ t := (*mapType)(unsafe.Pointer(iter.m.typ))
+ ktype := t.key
+
+ key := Value{ktype, iterkey, iter.m.flag | flag(ktype.Kind()) | flagIndir}
+ key = key.assignTo("reflect.MapIter.SetKey", v.typ, target)
+ typedmemmove(v.typ, v.ptr, key.ptr)
+}
+
+// Value returns the value of iter's current map entry.
+func (iter *MapIter) Value() Value {
+ if !iter.hiter.initialized() {
panic("MapIter.Value called before Next")
}
- if mapiterkey(it.it) == nil {
+ iterelem := mapiterelem(&iter.hiter)
+ if iterelem == nil {
panic("MapIter.Value called on exhausted iterator")
}
- t := (*mapType)(unsafe.Pointer(it.m.typ))
+ t := (*mapType)(unsafe.Pointer(iter.m.typ))
vtype := t.elem
- return copyVal(vtype, it.m.flag.ro()|flag(vtype.Kind()), mapiterelem(it.it))
+ return copyVal(vtype, iter.m.flag.ro()|flag(vtype.Kind()), iterelem)
+}
+
+// SetIterValue assigns to v the value of iter's current map entry.
+// It is equivalent to v.Set(iter.Value()), but it avoids allocating a new Value.
+// As in Go, the value must be assignable to v's type.
+func (v Value) SetIterValue(iter *MapIter) {
+ if !iter.hiter.initialized() {
+ panic("reflect: Value.SetIterValue called before Next")
+ }
+ iterelem := mapiterelem(&iter.hiter)
+ if iterelem == nil {
+ panic("reflect: Value.SetIterValue called on exhausted iterator")
+ }
+
+ v.mustBeAssignable()
+ var target unsafe.Pointer
+ if v.kind() == Interface {
+ target = v.ptr
+ }
+
+ t := (*mapType)(unsafe.Pointer(iter.m.typ))
+ vtype := t.elem
+
+ elem := Value{vtype, iterelem, iter.m.flag | flag(vtype.Kind()) | flagIndir}
+ elem = elem.assignTo("reflect.MapIter.SetValue", v.typ, target)
+ typedmemmove(v.typ, v.ptr, elem.ptr)
}
// Next advances the map iterator and reports whether there is another
-// entry. It returns false when the iterator is exhausted; subsequent
+// entry. It returns false when iter is exhausted; subsequent
// calls to Key, Value, or Next will panic.
-func (it *MapIter) Next() bool {
- if it.it == nil {
- it.it = mapiterinit(it.m.typ, it.m.pointer())
+func (iter *MapIter) Next() bool {
+ if !iter.m.IsValid() {
+ panic("MapIter.Next called on an iterator that does not have an associated map Value")
+ }
+ if !iter.hiter.initialized() {
+ mapiterinit(iter.m.typ, iter.m.pointer(), &iter.hiter)
} else {
- if mapiterkey(it.it) == nil {
+ if mapiterkey(&iter.hiter) == nil {
panic("MapIter.Next called on exhausted iterator")
}
- mapiternext(it.it)
+ mapiternext(&iter.hiter)
}
- return mapiterkey(it.it) != nil
+ return mapiterkey(&iter.hiter) != nil
+}
+
+// Reset modifies iter to iterate over v.
+// It panics if v's Kind is not Map and v is not the zero Value.
+// Reset(Value{}) causes iter to not to refer to any map,
+// which may allow the previously iterated-over map to be garbage collected.
+func (iter *MapIter) Reset(v Value) {
+ if v.IsValid() {
+ v.mustBe(Map)
+ }
+ iter.m = v
+ iter.hiter = hiter{}
}
// MapRange returns a range iterator for a map.
@@ -1260,7 +1431,7 @@ func (v Value) OverflowUint(x uint64) bool {
// It returns uintptr instead of unsafe.Pointer so that
// code using reflect cannot obtain unsafe.Pointers
// without importing the unsafe package explicitly.
-// It panics if v's Kind is not Chan, Func, Map, Ptr, Slice, or UnsafePointer.
+// It panics if v's Kind is not Chan, Func, Map, Pointer, Slice, or UnsafePointer.
//
// If v's Kind is Func, the returned pointer is an underlying
// code pointer, but not necessarily enough to identify a
@@ -1270,22 +1441,34 @@ func (v Value) OverflowUint(x uint64) bool {
// If v's Kind is Slice, the returned pointer is to the first
// element of the slice. If the slice is nil the returned value
// is 0. If the slice is empty but non-nil the return value is non-zero.
+//
+// It's preferred to use uintptr(Value.UnsafePointer()) to get the equivalent result.
func (v Value) Pointer() uintptr {
- // TODO: deprecate
k := v.kind()
switch k {
- case Ptr:
+ case Pointer:
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)
+ val := *(*uintptr)(v.ptr)
+ // Since it is a not-in-heap pointer, all pointers to the heap are
+ // forbidden! See comment in Value.Elem and issue #48399.
+ if !verifyNotInHeapPtr(val) {
+ panic("reflect: reflect.Value.Pointer on an invalid notinheap pointer")
+ }
+ return val
}
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.
+ return methodValueCallCodePtr()
+ }
p := v.pointer()
// Non-nil func value points at data block.
// First word of data block is actual code.
@@ -1499,6 +1682,25 @@ func (v Value) SetMapIndex(key, elem Value) {
v.mustBeExported()
key.mustBeExported()
tt := (*mapType)(unsafe.Pointer(v.typ))
+
+ if key.kind() == String && tt.key.Kind() == String && tt.elem.size <= maxValSize {
+ k := *(*string)(key.ptr)
+ if elem.typ == nil {
+ mapdelete_faststr(v.typ, v.pointer(), k)
+ return
+ }
+ elem.mustBeExported()
+ elem = elem.assignTo("reflect.Value.SetMapIndex", tt.elem, nil)
+ var e unsafe.Pointer
+ if elem.flag&flagIndir != 0 {
+ e = elem.ptr
+ } else {
+ e = unsafe.Pointer(&elem.ptr)
+ }
+ mapassign_faststr(v.typ, v.pointer(), k, e)
+ return
+ }
+
key = key.assignTo("reflect.Value.SetMapIndex", tt.key, nil)
var k unsafe.Pointer
if key.flag&flagIndir != 0 {
@@ -1744,6 +1946,16 @@ func (v Value) Type() Type {
return toType(m.mtyp)
}
+// CanUint reports whether Uint can be used without panicking.
+func (v Value) CanUint() bool {
+ switch v.kind() {
+ case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
+ return true
+ default:
+ return false
+ }
+}
+
// Uint returns v's underlying value, as a uint64.
// It panics if v's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64.
func (v Value) Uint() uint64 {
@@ -1771,11 +1983,12 @@ func (v Value) Uint() uint64 {
// which ensures cmd/compile can recognize unsafe.Pointer(v.UnsafeAddr())
// and make an exception.
-// UnsafeAddr returns a pointer to v's data.
+// UnsafeAddr returns a pointer to v's data, as a uintptr.
// It is for advanced clients that also import the "unsafe" package.
// It panics if v is not addressable.
+//
+// It's preferred to use uintptr(Value.Addr().UnsafePointer()) to get the equivalent result.
func (v Value) UnsafeAddr() uintptr {
- // TODO: deprecate
if v.typ == nil {
panic(&ValueError{"reflect.Value.UnsafeAddr", Invalid})
}
@@ -1785,6 +1998,57 @@ func (v Value) UnsafeAddr() uintptr {
return uintptr(v.ptr)
}
+// UnsafePointer returns v's value as a unsafe.Pointer.
+// It panics if v's Kind is not Chan, Func, Map, Pointer, Slice, or UnsafePointer.
+//
+// If v's Kind is Func, the returned pointer is an underlying
+// code pointer, but not necessarily enough to identify a
+// single function uniquely. The only guarantee is that the
+// result is zero if and only if v is a nil func Value.
+//
+// If v's Kind is Slice, the returned pointer is to the first
+// element of the slice. If the slice is nil the returned value
+// is nil. If the slice is empty but non-nil the return value is non-nil.
+func (v Value) UnsafePointer() unsafe.Pointer {
+ k := v.kind()
+ switch k {
+ case Pointer:
+ if v.typ.ptrdata == 0 {
+ // Since it is a not-in-heap pointer, all pointers to the heap are
+ // forbidden! See comment in Value.Elem and issue #48399.
+ if !verifyNotInHeapPtr(*(*uintptr)(v.ptr)) {
+ panic("reflect: reflect.Value.UnsafePointer on an invalid notinheap pointer")
+ }
+ return *(*unsafe.Pointer)(v.ptr)
+ }
+ fallthrough
+ case Chan, Map, UnsafePointer:
+ return 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.
+ code := methodValueCallCodePtr()
+ return *(*unsafe.Pointer)(unsafe.Pointer(&code))
+ }
+ 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 p
+
+ case Slice:
+ return (*unsafeheader.Slice)(v.ptr).Data
+ }
+ panic(&ValueError{"reflect.Value.UnsafePointer", v.kind()})
+}
+
// StringHeader is the runtime representation of a string.
// It cannot be used safely or portably and its representation may
// change in a later release.
@@ -1840,11 +2104,12 @@ func grow(s Value, extra int) (Value, int, int) {
if m == 0 {
m = extra
} else {
+ const threshold = 256
for m < i1 {
- if i0 < 1024 {
+ if i0 < threshold {
m += m
} else {
- m += m / 4
+ m += (m + 3*threshold) / 4
}
}
}
@@ -2151,7 +2416,7 @@ func MakeMapWithSize(typ Type, n int) Value {
// If v is a nil pointer, Indirect returns a zero Value.
// If v is not a pointer, Indirect returns v.
func Indirect(v Value) Value {
- if v.Kind() != Ptr {
+ if v.Kind() != Pointer {
return v
}
return v.Elem()
@@ -2159,7 +2424,7 @@ func Indirect(v Value) Value {
// ValueOf returns a new Value initialized to the concrete value
// stored in the interface i. ValueOf(nil) returns the zero Value.
-func ValueOf(i interface{}) Value {
+func ValueOf(i any) Value {
if i == nil {
return Value{}
}
@@ -2204,7 +2469,7 @@ const maxZero = 1024
var zeroVal [maxZero]byte
// New returns a Value representing a pointer to a new zero value
-// for the specified type. That is, the returned Value's Type is PtrTo(typ).
+// for the specified type. That is, the returned Value's Type is PointerTo(typ).
func New(typ Type) Value {
if typ == nil {
panic("reflect: New(nil)")
@@ -2216,14 +2481,14 @@ func New(typ Type) Value {
panic("reflect: New of type that may not be allocated in heap (possibly undefined cgo C type)")
}
ptr := unsafe_New(t)
- fl := flag(Ptr)
+ fl := flag(Pointer)
return Value{pt, ptr, fl}
}
// NewAt returns a Value representing a pointer to a value of the
// specified type, using p as that pointer.
func NewAt(typ Type, p unsafe.Pointer) Value {
- fl := flag(Ptr)
+ fl := flag(Pointer)
t := typ.(*rtype)
return Value{t.ptrTo(), p, fl}
}
@@ -2257,7 +2522,7 @@ func (v Value) assignTo(context string, dst *rtype, target unsafe.Pointer) Value
}
x := valueInterface(v, false)
if dst.NumMethod() == 0 {
- *(*interface{})(target) = x
+ *(*any)(target) = x
} else {
ifaceE2I(dst, x, target)
}
@@ -2292,10 +2557,9 @@ func (v Value) CanConvert(t Type) bool {
// Currently the only conversion that is OK in terms of type
// but that can panic depending on the value is converting
// from slice to pointer-to-array.
- if vt.Kind() == Slice && t.Kind() == Ptr && t.Elem().Kind() == Array {
+ if vt.Kind() == Slice && t.Kind() == Pointer && t.Elem().Kind() == Array {
n := t.Elem().Len()
- h := (*unsafeheader.Slice)(v.ptr)
- if n > h.Len {
+ if n > v.Len() {
return false
}
}
@@ -2363,7 +2627,7 @@ func convertOp(dst, src *rtype) func(Value, Type) Value {
}
// "x is a slice, T is a pointer-to-array type,
// and the slice and array types have identical element types."
- if dst.Kind() == Ptr && dst.Elem().Kind() == Array && src.Elem() == dst.Elem().Elem() {
+ if dst.Kind() == Pointer && dst.Elem().Kind() == Array && src.Elem() == dst.Elem().Elem() {
return cvtSliceArrayPtr
}
@@ -2379,8 +2643,8 @@ func convertOp(dst, src *rtype) func(Value, Type) Value {
}
// dst and src are non-defined pointer types with same underlying base type.
- if dst.Kind() == Ptr && dst.Name() == "" &&
- src.Kind() == Ptr && src.Name() == "" &&
+ if dst.Kind() == Pointer && dst.Name() == "" &&
+ src.Kind() == Pointer && src.Name() == "" &&
haveIdenticalUnderlyingType(dst.Elem().common(), src.Elem().common(), false) {
return cvtDirect
}
@@ -2562,11 +2826,11 @@ func cvtStringRunes(v Value, t Type) Value {
// convertOp: []T -> *[N]T
func cvtSliceArrayPtr(v Value, t Type) Value {
n := t.Elem().Len()
- h := (*unsafeheader.Slice)(v.ptr)
- if n > h.Len {
- panic("reflect: cannot convert slice with length " + itoa.Itoa(h.Len) + " to pointer to array with length " + itoa.Itoa(n))
+ if n > v.Len() {
+ panic("reflect: cannot convert slice with length " + itoa.Itoa(v.Len()) + " to pointer to array with length " + itoa.Itoa(n))
}
- return Value{t.common(), h.Data, v.flag&^(flagIndir|flagAddr|flagKindMask) | flag(Ptr)}
+ h := (*unsafeheader.Slice)(v.ptr)
+ return Value{t.common(), h.Data, v.flag&^(flagIndir|flagAddr|flagKindMask) | flag(Pointer)}
}
// convertOp: direct copy
@@ -2589,7 +2853,7 @@ func cvtT2I(v Value, typ Type) Value {
target := unsafe_New(typ.common())
x := valueInterface(v, false)
if typ.NumMethod() == 0 {
- *(*interface{})(target) = x
+ *(*any)(target) = x
} else {
ifaceE2I(typ.(*rtype), x, target)
}
@@ -2632,24 +2896,31 @@ func makemap(t *rtype, cap int) (m unsafe.Pointer)
func mapaccess(t *rtype, m unsafe.Pointer, key unsafe.Pointer) (val unsafe.Pointer)
//go:noescape
+func mapaccess_faststr(t *rtype, m unsafe.Pointer, key string) (val unsafe.Pointer)
+
+//go:noescape
func mapassign(t *rtype, m unsafe.Pointer, key, val unsafe.Pointer)
//go:noescape
+func mapassign_faststr(t *rtype, m unsafe.Pointer, key string, val unsafe.Pointer)
+
+//go:noescape
func mapdelete(t *rtype, m unsafe.Pointer, key unsafe.Pointer)
-// m escapes into the return value, but the caller of mapiterinit
-// doesn't let the return value escape.
//go:noescape
-func mapiterinit(t *rtype, m unsafe.Pointer) unsafe.Pointer
+func mapdelete_faststr(t *rtype, m unsafe.Pointer, key string)
+
+//go:noescape
+func mapiterinit(t *rtype, m unsafe.Pointer, it *hiter)
//go:noescape
-func mapiterkey(it unsafe.Pointer) (key unsafe.Pointer)
+func mapiterkey(it *hiter) (key unsafe.Pointer)
//go:noescape
-func mapiterelem(it unsafe.Pointer) (elem unsafe.Pointer)
+func mapiterelem(it *hiter) (elem unsafe.Pointer)
//go:noescape
-func mapiternext(it unsafe.Pointer)
+func mapiternext(it *hiter)
//go:noescape
func maplen(m unsafe.Pointer) int
@@ -2657,7 +2928,7 @@ func maplen(m unsafe.Pointer) int
//go:linkname call runtime.reflectcall
func call(typ *funcType, fnaddr unsafe.Pointer, isInterface bool, isMethod bool, params *unsafe.Pointer, results *unsafe.Pointer)
-func ifaceE2I(t *rtype, src interface{}, dst unsafe.Pointer)
+func ifaceE2I(t *rtype, src any, dst unsafe.Pointer)
// memmove copies size bytes to dst from src. No write barriers are used.
//go:noescape
@@ -2679,10 +2950,12 @@ func typedslicecopy(elemType *rtype, dst, src unsafeheader.Slice) int
//go:noescape
func typehash(t *rtype, p unsafe.Pointer, h uintptr) uintptr
+func verifyNotInHeapPtr(p uintptr) bool
+
// Dummy annotation marking that the value x escapes,
// for use in cases where the reflect code is so clever that
// the compiler cannot follow.
-func escapes(x interface{}) {
+func escapes(x any) {
if dummy.b {
dummy.x = x
}
@@ -2690,5 +2963,5 @@ func escapes(x interface{}) {
var dummy struct {
b bool
- x interface{}
+ x any
}