aboutsummaryrefslogtreecommitdiff
path: root/src/reflect/value.go
AgeCommit message (Collapse)Author
2025-06-27reflect: fix TypeAssert on nil interface valuesJoe Tsai
In the Go language a type assertion of a nil interface value will always report false: var err error v, ok := err.(error) // always reports (nil, false) Consequently, assertion on a reflect.Value.Interface() will also report false: var err error rv := ValueOf(&err).Elem() v, ok := rv.Interface().(error) // reports (nil, false) However, prior to this change, a TypeAssert would report true: var err error rv := ValueOf(&err).Elem() v, ok := TypeAssert[error](rv) // reports (nil, true) when it should report false. This fixes TypeAssert to match the Go language by pushing the typ != v.typ check to the very end after we have validated that neither v nor T are interface kinds. Fixes #74404 Change-Id: Ie14d5cf18c8370c3e27ce4bdf4570c89519d8a16 Reviewed-on: https://go-review.googlesource.com/c/go/+/684675 Reviewed-by: Cherry Mui <cherryyz@google.com> Auto-Submit: Joseph Tsai <joetsai@digital-static.net> Reviewed-by: Mateusz Poliwczak <mpoliwczak34@gmail.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
2025-05-21reflect: leak packEface input to result rather than heapthepudds
This is part of a series of CLs that aim to help allocations in reflect and reduce how often interface arguments escape for the print functions in fmt. Before this change, the reflect.Value parameter for packEface leaks immediately to the heap due to the various ODOTPTR operations on the *emptyInterface. The -m=2 logs report: parameter v leaks to <heap> for packEface with derefs=0: flow: <heap> ← v: from v.ptr (dot) at .\value.go:145:13 from e.word = v.ptr (assign) at .\value.go:145:10 After this change, the input leaks to the result, which is what we want: parameter v leaks to ~r0 with derefs=0: flow: e = v: from v.ptr (dot) at .\value.go:143:13 from e.Data = v.ptr (assign) at .\value.go:143:10 flow: ~r0 = e: from &e (address-of) at .\value.go:147:32 from *(*any)(unsafe.Pointer(&e)) (indirection) at .\value.go:147:9 from return *(*any)(unsafe.Pointer(&e)) (return) at .\value.go:147:2 This change here is needed, but reflect.Value.Interface still leaks its input to the heap for other reasons having to do with method values, which we attempt to address in CL 530097, CL 530095, and CL 530096. Updates #8618 Updates #71349 Change-Id: Ie77bc850ff261212eeafe190bd6f9a879676a51d Reviewed-on: https://go-review.googlesource.com/c/go/+/528535 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Reviewed-by: qiu laidongfeng2 <2645477756@qq.com> Reviewed-by: Cherry Mui <cherryyz@google.com>
2025-05-21reflect: optimize IsZero with a pointer comparison to global zeroValthepudds
Our prior CL 649078 teaches the compiler to use a pointer to runtime.zeroVal as the data pointer for an interface in cases it where it can see that a zero value struct or array is being used in an interface conversion. This applies to some uses with reflect, such as: s := S{} v := reflect.ValueOf(s) This CL builds on that to do a cheap pointer check in reflect.IsZero to see if the Value points to runtime.zeroVal, which means it is a zero value. An alternative might be to do an initial pointer check in the typ.Equal function for types where it makes sense to do but doesn't already. This CL gives a performance boost of -51.71% geomean for BenchmarkZero/IsZero, with most of the impact there on arrays of structs. (The left column is CL 649078 and the right column is this CL). goos: linux goarch: amd64 pkg: reflect cpu: Intel(R) Xeon(R) CPU @ 2.80GHz │ find-zeroVal │ check-zeroVal │ │ sec/op │ sec/op vs base │ Zero/IsZero/ByteArray/size=16-4 4.171n ± 0% 3.123n ± 0% -25.13% (p=0.000 n=20) Zero/IsZero/ByteArray/size=64-4 3.864n ± 0% 3.129n ± 0% -19.02% (p=0.000 n=20) Zero/IsZero/ByteArray/size=1024-4 3.878n ± 0% 3.126n ± 0% -19.39% (p=0.000 n=20) Zero/IsZero/BigStruct/size=1024-4 5.061n ± 0% 3.273n ± 0% -35.34% (p=0.000 n=20) Zero/IsZero/SmallStruct/size=16-4 4.191n ± 0% 3.275n ± 0% -21.87% (p=0.000 n=20) Zero/IsZero/SmallStructArray/size=64-4 8.636n ± 0% 3.127n ± 0% -63.79% (p=0.000 n=20) Zero/IsZero/SmallStructArray/size=1024-4 80.055n ± 0% 3.126n ± 0% -96.10% (p=0.000 n=20) Zero/IsZero/Time/size=24-4 3.865n ± 0% 3.274n ± 0% -15.29% (p=0.000 n=20) geomean 6.587n 3.181n -51.71% Note these are of course micro benchmarks with easily predicted branches. The extra branch we introduce in the CL might hurt if there was for example a tight loop where 50% of the values used the global zeroVal and 50% didn't in a way that is not well predicted, although if the typ.Equal for many types already does an initial pointer check, it might not matter much. For the older BenchmarkIsZero in reflect, this change does not help. (The compiler does not use the global zeroVal as the data word for the interfaces in this benchmark because values are part of a larger value that is too big to be used in the global zeroVal, and also a piece of the larger value is mutated and is not zero). │ find-zeroVal │ check-zeroVal │ │ sec/op │ sec/op vs base │ IsZero/ArrayComparable-4 14.58n ± 0% 14.59n ± 0% ~ (p=0.177 n=20) IsZero/ArrayIncomparable-4 163.8n ± 0% 167.5n ± 0% +2.26% (p=0.000 n=20) IsZero/StructComparable-4 6.847n ± 0% 6.847n ± 0% ~ (p=0.703 n=20) IsZero/StructIncomparable-4 35.41n ± 0% 35.10n ± 0% -0.86% (p=0.000 n=20) IsZero/ArrayInt_4-4 8.631n ± 0% 8.363n ± 0% -3.10% (p=0.000 n=20) IsZero/ArrayInt_1024-4 265.5n ± 0% 265.4n ± 0% ~ (p=0.288 n=20) IsZero/ArrayInt_1024_NoZero-4 135.8n ± 0% 136.2n ± 0% +0.33% (p=0.000 n=20) IsZero/Struct4Int-4 8.451n ± 0% 8.386n ± 0% -0.77% (p=0.000 n=20) IsZero/ArrayStruct4Int_1024-4 265.2n ± 0% 266.0n ± 0% +0.30% (p=0.000 n=20) IsZero/ArrayChanInt_1024-4 265.5n ± 0% 265.4n ± 0% ~ (p=0.605 n=20) IsZero/StructInt_512-4 135.8n ± 0% 135.8n ± 0% ~ (p=0.396 n=20) geomean 55.22n 55.12n -0.18% Updates #71323 Change-Id: Ie083853a5bff03856277a293d94532a681f4a8d5 Reviewed-on: https://go-review.googlesource.com/c/go/+/654135 Reviewed-by: Keith Randall <khr@google.com> Reviewed-by: David Chase <drchase@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Keith Randall <khr@golang.org>
2025-05-20reflect: add TypeAssert[T]Mateusz Poliwczak
This implementation is zero-alloc when T is a concrete type, allocates when val contains a method or when T is a interface and Value was obtained for example through Elem(), in which case it has to be allocated to avoid sharing the same memory. goos: linux goarch: amd64 pkg: reflect cpu: AMD Ryzen 5 4600G with Radeon Graphics │ /tmp/bench2 │ │ sec/op │ TypeAssert/TypeAssert[int](int)-12 2.725n ± 1% TypeAssert/TypeAssert[uint8](int)-12 2.599n ± 1% TypeAssert/TypeAssert[fmt.Stringer](reflect_test.testTypeWithMethod)-12 8.470n ± 0% TypeAssert/TypeAssert[fmt.Stringer](*reflect_test.testTypeWithMethod)-12 8.460n ± 1% TypeAssert/TypeAssert[interface_{}](int)-12 4.181n ± 1% TypeAssert/TypeAssert[interface_{}](reflect_test.testTypeWithMethod)-12 4.178n ± 1% TypeAssert/TypeAssert[time.Time](time.Time)-12 2.839n ± 0% TypeAssert/TypeAssert[func()_string](func()_string)-12 151.1n ± 1% geomean 6.645n │ /tmp/bench2 │ │ B/op │ TypeAssert/TypeAssert[int](int)-12 0.000 ± 0% TypeAssert/TypeAssert[uint8](int)-12 0.000 ± 0% TypeAssert/TypeAssert[fmt.Stringer](reflect_test.testTypeWithMethod)-12 0.000 ± 0% TypeAssert/TypeAssert[fmt.Stringer](*reflect_test.testTypeWithMethod)-12 0.000 ± 0% TypeAssert/TypeAssert[interface_{}](int)-12 0.000 ± 0% TypeAssert/TypeAssert[interface_{}](reflect_test.testTypeWithMethod)-12 0.000 ± 0% TypeAssert/TypeAssert[time.Time](time.Time)-12 0.000 ± 0% TypeAssert/TypeAssert[func()_string](func()_string)-12 72.00 ± 0% geomean ¹ Fixes #62121 Change-Id: I0911c70c5966672c930d387438643f94a40441c4 GitHub-Last-Rev: ce89a53097b53fc59ff3ce3996917f8484ad3967 GitHub-Pull-Request: golang/go#71639 Reviewed-on: https://go-review.googlesource.com/c/go/+/648056 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Keith Randall <khr@google.com> Reviewed-by: Cherry Mui <cherryyz@google.com>
2025-03-17reflect: document Method(ByName) w.r.t dead code eliminationIlya Priven
The behavior is described in src/cmd/link/internal/ld/deadcode.go but is not otherwise documented. Since the usage of those functions could have significant caveats (longer builds, larger binaries), we are informing the user. Change-Id: I87571dd14aa16d7aac59fe45dfc52cb7c5b956c1 Reviewed-on: https://go-review.googlesource.com/c/go/+/658255 Auto-Submit: Ian Lance Taylor <iant@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: David Chase <drchase@google.com> Reviewed-by: Ian Lance Taylor <iant@google.com>
2025-02-21reflect: correctly handle method values in SeqMichael Anthony Knyszek
Currently method values aren't correctly handled in Seq because we call canRangeFunc on the reciever type, not the method value type, when we're handling a method value. reflect.Value.Type has the logic to obtain the method value type from the Value. This change slightly refactors reflect.Value.Type into a separate function so we can obtain the correct type as an abi.Type and pass it off to canRangeFunc (and canRangeFunc2). Fixes #71874. Change-Id: Ie62dfca2a84b8f2f816bb87ff1ed1a58a7bb8122 Reviewed-on: https://go-review.googlesource.com/c/go/+/651416 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Cherry Mui <cherryyz@google.com> Auto-Submit: Michael Knyszek <mknyszek@google.com>
2025-01-28runtime: rename mapiterinit and mapiternextMichael Pratt
mapiterinit allows external linkname. These users must allocate their own iter struct for initialization by mapiterinit. Since the type is unexported, they also must define the struct themselves. As a result, they of course define the struct matching the old hiter definition (in map_noswiss.go). The old definition is smaller on 32-bit platforms. On those platforms, mapiternext will clobber memory outside of the caller's allocation. On all platforms, the pointer layout between the old hiter and new maps.Iter does not match. Thus the GC may miss pointers and free reachable objects early, or it may see non-pointers that look like heap pointers and throw due to invalid references to free objects. To avoid these issues, we must keep mapiterinit and mapiternext with the old hiter definition. The most straightforward way to do this is to use mapiterinit and mapiternext as a compatibility layer between the old and new iter types. The first step to that is to move normal map use off of these functions, which is what this CL does. Introduce new mapIterStart and mapIterNext functions that replace the former functions everywhere in the toolchain. These have the same behavior as the old functions. This CL temporarily makes the old functions throw to ensure we don't have hidden dependencies on them. We cannot remove them entirely because GOEXPERIMENT=noswissmap still uses the old names, and internal/goobj requires all builtins to exist regardless of GOEXPERIMENT. The next CL will introduce the compatibility layer. I want to avoid using linkname between runtime and reflect, as that would also allow external linknames. So mapIterStart and mapIterNext are duplicated in reflect, which can be done trivially, as it imports internal/runtime/maps. For #71408. Change-Id: I6a6a636c6d4bd1392618c67ca648d3f061afe669 Reviewed-on: https://go-review.googlesource.com/c/go/+/643898 Auto-Submit: Michael Pratt <mpratt@google.com> Reviewed-by: Keith Randall <khr@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Keith Randall <khr@golang.org>
2024-12-11reflect: consistently document when value must be settableIan Lance Taylor
Fixes #70760 Change-Id: Ia00723698b7e502fa2c63f8f1dbe1143af22e0a5 Reviewed-on: https://go-review.googlesource.com/c/go/+/634799 Reviewed-by: Ian Lance Taylor <iant@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Keith Randall <khr@google.com> Commit-Queue: Ian Lance Taylor <iant@google.com> Reviewed-by: Keith Randall <khr@golang.org> Auto-Submit: Ian Lance Taylor <iant@golang.org> Auto-Submit: Ian Lance Taylor <iant@google.com>
2024-09-18reflect: remove calling mapiterkey, mapiterelemKyle Xiao
It makes use of the hiter structure which matches runtime.hiter's. This change mainly improves the performance of Next method of MapIter. goos: darwin goarch: arm64 pkg: reflect cpu: Apple M2 │ ./old.txt │ ./new.txt │ │ sec/op │ sec/op vs base │ MapIterNext-8 61.95n ± 0% 54.95n ± 0% -11.28% (p=0.000 n=10) for the change of `test/escape_reflect.go`: removing mapiterkey, mapiterelem would cause leaking MapIter content when calling SetIterKey and SetIterValue, and this may cause map bucket to be allocated on heap instead of stack. Reproduce: ``` { m := map[int]int{1: 2} // escapes to heap after this change it := reflect.ValueOf(m).MapRange() it.Next() var k, v int reflect.ValueOf(&k).Elem().SetIterKey(it) reflect.ValueOf(&v).Elem().SetIterValue(it) println(k, v) } ``` This CL would not introduce abi.NoEscape to fix this. It may need futher optimization and tests on hiter field usage and its escape analysis. Fixes #69416 Change-Id: Ibaa33bcf86228070b4a505b9512680791aa59f04 Reviewed-on: https://go-review.googlesource.com/c/go/+/612616 Reviewed-by: Keith Randall <khr@golang.org> Auto-Submit: Keith Randall <khr@golang.org> Reviewed-by: Michael Knyszek <mknyszek@google.com> Reviewed-by: Keith Randall <khr@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2024-08-02all: create swissmap experiment and fork filesMichael Pratt
The _swiss.go files are identical to the originals (except build tag). Later CLs will change them. For #54766. Cq-Include-Trybots: luci.golang.try:gotip-linux-amd64-longtest-swissmap Change-Id: I9943e2d6f1cfa227ffbf27c9ddc9ce853695d225 Reviewed-on: https://go-review.googlesource.com/c/go/+/580778 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Keith Randall <khr@golang.org> Auto-Submit: Michael Pratt <mpratt@google.com> Commit-Queue: Michael Pratt <mpratt@google.com> Reviewed-by: Keith Randall <khr@google.com>
2024-07-26cmd/compile, reflect: treat abi.NoEscape as cheap callCuong Manh Le
The abi.NoEscape function is introduced to replace all usages of noescape wrapper in the standard library. However, the last usage in reflect package is still present, because the inlining test failed if abi.NoEscape were used. The reason is that reflect.noescape is treated as a cheap call, while abi.NoEscape is not. By treating abi.NoEscape a cheap call, the last usage of noescape in reflect package can now be removed. Change-Id: I798079780129221a5a26cbcb18c95ee30855b784 Reviewed-on: https://go-review.googlesource.com/c/go/+/601275 Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Auto-Submit: Cuong Manh Le <cuong.manhle.vn@gmail.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Cherry Mui <cherryyz@google.com>
2024-05-22all: document legacy //go:linkname for modules with ≥50,000 dependentsRuss Cox
Note that this depends on the revert of CL 581395 to move zeroVal back. For #67401. Change-Id: I507c27c2404ad1348aabf1ffa3740e6b1957495b Reviewed-on: https://go-review.googlesource.com/c/go/+/587217 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Russ Cox <rsc@golang.org> Reviewed-by: Cherry Mui <cherryyz@google.com>
2024-05-22runtime: revert "move zeroVal to internal/abi"Russ Cox
This reverts CL 581395, commit 2f5b420fb5984842afab37a9c2e66e6599107483. It breaks a linkname from github.com/ugorji/go/codec. For #67401. A followup CL will document this dependence. Change-Id: I66d6c39c03e769ab829ca4c3f4f61277b93380d3 Reviewed-on: https://go-review.googlesource.com/c/go/+/587216 TryBot-Bypass: Russ Cox <rsc@golang.org> Auto-Submit: Russ Cox <rsc@golang.org> Reviewed-by: Cherry Mui <cherryyz@google.com>
2024-05-22all: document legacy //go:linkname for modules with ≥100,000 dependentsRuss Cox
For #67401. Change-Id: I51f5b561ee11eb242e3b1585d591281d0df4fc24 Reviewed-on: https://go-review.googlesource.com/c/go/+/587215 Auto-Submit: Russ Cox <rsc@golang.org> Reviewed-by: Cherry Mui <cherryyz@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2024-05-07reflect: remove redundent ifaceIndirapocelipes
Use abi.(*Type).IfaceIndir instead. Change-Id: I31197cbf0edaf53bbb0455fa76d2a4a2ab40b420 GitHub-Last-Rev: 2659b696ef3680e13e22bdf6a63e5d82b7b1ecdf GitHub-Pull-Request: golang/go#67227 Reviewed-on: https://go-review.googlesource.com/c/go/+/583755 Reviewed-by: Ian Lance Taylor <iant@google.com> Auto-Submit: Ian Lance Taylor <iant@google.com> Reviewed-by: Keith Randall <khr@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2024-05-03runtime,reflect: move zeroVal to internal/abiqiulaidongfeng
Change-Id: I0e19e4aa2ea47a714e27b8d66c23c449e27861f2 GitHub-Last-Rev: 2d59b9589efcf4ade6cfd7c8feffc46bf9ba912c GitHub-Pull-Request: golang/go#67014 Reviewed-on: https://go-review.googlesource.com/c/go/+/581395 Reviewed-by: Keith Randall <khr@golang.org> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Keith Randall <khr@google.com> Reviewed-by: Joedian Reid <joedian@google.com>
2024-04-17internal/abi: define EmptyInterface, TypeOf, and NoEscapeMichael Anthony Knyszek
This change defines two commonly-defined functions and a commonly-defined type in internal/abi to try and deduplicate some definitions. This is motivated by a follow-up CL which will want access to TypeOf in yet another package. There still exist duplicate definitions of all three of these things in the runtime, and this CL doesn't try to handle that yet. There are far too many uses in the runtime to handle manually in a way that feels comfortable; automated refactoring will help. For #62483. Change-Id: I02fc64a28f11af618f6071f94d27f45c135fa8ac Reviewed-on: https://go-review.googlesource.com/c/go/+/573955 Auto-Submit: Michael Knyszek <mknyszek@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: David Chase <drchase@google.com>
2024-04-03reflect: add missing String case in Value.UnsafePointer docCuong Manh Le
CL 516596 changes Value.UnsafePointer to handle String case. However, the method's doc comment is not updated to reflect this change. Updates #61308 Change-Id: I84e02fd969ae0244184e1a2f05cac4651cdf7bff Reviewed-on: https://go-review.googlesource.com/c/go/+/575956 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Auto-Submit: Cuong Manh Le <cuong.manhle.vn@gmail.com> Reviewed-by: Ian Lance Taylor <iant@google.com>
2024-04-02all: add reflect.SliceAt functionCuong Manh Le
Fixes #61308 Change-Id: Ic17d737fda055a60779985d5da497745c80d5cfa Reviewed-on: https://go-review.googlesource.com/c/go/+/516597 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Cuong Manh Le <cuong.manhle.vn@gmail.com> Reviewed-by: Ian Lance Taylor <iant@google.com> Reviewed-by: Than McIntosh <thanm@google.com>
2024-04-02reflect: handle String kind in Value.{Pointer,UnsafePointer}Cuong Manh Le
Updates #61308 Change-Id: I92d459383c520d137787ce5c8f135d205af74e5d Reviewed-on: https://go-review.googlesource.com/c/go/+/516596 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Auto-Submit: Cuong Manh Le <cuong.manhle.vn@gmail.com> Reviewed-by: Ian Lance Taylor <iant@google.com>
2024-04-02reflect: add available godoc linkcui fliter
Change-Id: Ib199ce1a781e8e3a66d3dc8bda617e6bc30b290e Reviewed-on: https://go-review.googlesource.com/c/go/+/539578 Auto-Submit: Ian Lance Taylor <iant@google.com> Run-TryBot: shuang cui <imcusg@gmail.com> Reviewed-by: Ian Lance Taylor <iant@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Reviewed-by: qiulaidongfeng <2645477756@qq.com>
2024-03-04runtime: use .Pointers() instead of manual checkingPouriya
Change-Id: Ib78c1513616089f4942297cd17212b1b11871fd5 GitHub-Last-Rev: f97fe5b5bffffe25dc31de7964588640cb70ec41 GitHub-Pull-Request: golang/go#65819 Reviewed-on: https://go-review.googlesource.com/c/go/+/565515 Reviewed-by: Jorropo <jorropo.pgm@gmail.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Keith Randall <khr@golang.org> Reviewed-by: Michael Knyszek <mknyszek@google.com> Reviewed-by: Keith Randall <khr@google.com> Reviewed-by: Keith Randall <khr@golang.org>
2024-02-27reflect: fix typo in commentguoguangwu
Change-Id: Ia8e666b128622391d72e42449c01c4e10f3c9e1e GitHub-Last-Rev: c74cf13b70772a965a14630108544a89690d1383 GitHub-Pull-Request: golang/go#65938 Reviewed-on: https://go-review.googlesource.com/c/go/+/566855 Reviewed-by: Carlos Amedee <carlos@golang.org> Reviewed-by: qiulaidongfeng <2645477756@qq.com> Auto-Submit: Ian Lance Taylor <iant@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Ian Lance Taylor <iant@google.com>
2024-02-17reflect: make Value.Comparable return true for nil interface valueJes Cok
Fixes #65718 Change-Id: I0b3edf9085f2d71f915bdf8ff9d312509b438c5f GitHub-Last-Rev: 9fb1ca1a631c648d1f38f75b1fcb2f878048706b GitHub-Pull-Request: golang/go#65750 Reviewed-on: https://go-review.googlesource.com/c/go/+/564795 Auto-Submit: Ian Lance Taylor <iant@google.com> Reviewed-by: Ian Lance Taylor <iant@google.com> Reviewed-by: Cherry Mui <cherryyz@google.com> Commit-Queue: Ian Lance Taylor <iant@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2024-02-16reflect: use internal/abi itab typeKeith Randall
Change-Id: I4a40d9cda41d3601169ef0daf0f25fb1509bdcb7 Reviewed-on: https://go-review.googlesource.com/c/go/+/549458 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Keith Randall <khr@google.com> Reviewed-by: David Chase <drchase@google.com>
2024-01-26reflect: use MapMaxKeyBytes,MapMaxElemBytes,MapBucketCount of internal/abiqiulaidongfeng
For #59670 Change-Id: I63a6e2cfaf9eec03866ea61064164a059fc42bb2 GitHub-Last-Rev: a3aa46a36444b08382ddac79c10a064b314bd971 GitHub-Pull-Request: golang/go#64773 Reviewed-on: https://go-review.googlesource.com/c/go/+/550595 TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Austin Clements <austin@google.com> Reviewed-by: Cherry Mui <cherryyz@google.com>
2024-01-23reflect: delete TODO pass safe to packEface don't need to copy if safe==trueqiulaidongfeng
valueInterface not copy result in the follow incorrect behavior w1. x := ValueOf(&v).Elem() r1. iface := Value.Interface() w2. x.Set() or x.SetT() The write operation of W2 will be observed by the read operation of r1, but the existing behavior is not. The valueInterface in deepValueEqual can, in theory, pass safe==true to not copy the object, but there is no benchmark to indicate that the memory allocation has changed, maybe we don't actually need safe==true here. Change-Id: I55c423fd50adac8822a7fdbfe67af89ee223eace GitHub-Last-Rev: 4a6386709817f3ea6055711dd39d2694d58b3043 GitHub-Pull-Request: golang/go#64618 Reviewed-on: https://go-review.googlesource.com/c/go/+/548436 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Cherry Mui <cherryyz@google.com> Reviewed-by: Keith Randall <khr@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org> Auto-Submit: Keith Randall <khr@golang.org>
2023-11-22internal/abi, runtime, reflect, cmd: merge maxZero const into internal/abiqiulaidongfeng
For #59670 Change-Id: If38a74ad067a3ea3ff551c0c25c8ef41abec114b GitHub-Last-Rev: fb1f2f3c9f320017627bc3342b061e1e7f6f7fad GitHub-Pull-Request: golang/go#64268 Reviewed-on: https://go-review.googlesource.com/c/go/+/543655 Run-TryBot: qiulaidongfeng <2645477756@qq.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com> Reviewed-by: Keith Randall <khr@google.com> Reviewed-by: Keith Randall <khr@golang.org>
2023-11-21reflect: tweak logic for 'case Array' in IsZeroJes Cok
For 'case Array' in IsZero, check 'v.flag&flagIndir == 0' in the first place, rename 'array' to 'typ' for consistency, and remove stale comment. Add line breaks for long sentence in isZero. Change-Id: Id06d01fd61eefd205bf4626e6b920ae82b459455 GitHub-Last-Rev: 7225ca3f7b55cbef58387365ed8f3ff104236a06 GitHub-Pull-Request: golang/go#64270 Reviewed-on: https://go-review.googlesource.com/c/go/+/543656 TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Keith Randall <khr@google.com> Run-TryBot: Jes Cok <xigua67damn@gmail.com> Reviewed-by: Keith Randall <khr@golang.org> Auto-Submit: Keith Randall <khr@golang.org> Reviewed-by: Cherry Mui <cherryyz@google.com>
2023-11-19reflect: optimize Value.IsZero for struct typesqiulaidongfeng
For some types where the zero value is a value where all bits of this type are 0 optimize it. goos: windows goarch: amd64 pkg: reflect cpu: AMD Ryzen 7 7840HS w/ Radeon 780M Graphics │ old.txt │ new.txt │ │ sec/op │ sec/op vs base │ IsZero/StructInt_512-16 109.75n ± 0% 72.61n ± 1% -33.84% (p=0.000 n=12) Change-Id: I56de8b95f4d4482068960d6f38938763fa1caa90 GitHub-Last-Rev: c143f0cd7616cb3be52c59879f748e49a3c5cbf1 GitHub-Pull-Request: golang/go#64220 Reviewed-on: https://go-review.googlesource.com/c/go/+/543355 Reviewed-by: David Chase <drchase@google.com> Reviewed-by: Cherry Mui <cherryyz@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Auto-Submit: Keith Randall <khr@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
2023-11-16reflect: remove go121noForceValueEscapeCherry Mui
Before Go 1.21, ValueOf always escapes and a Value's content is always heap allocated. In Go 1.21, we made it no longer always escape, guarded by go121noForceValueEscape. This behavior has been released for some time and there is no issue so far. We can remove the guard now. Change-Id: I81f5366412390f6c63b642f4c7c016da534da76a Reviewed-on: https://go-review.googlesource.com/c/go/+/542795 Reviewed-by: David Chase <drchase@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2023-11-16runtime: optimize bulkBarrierPreWrite with allocheadersMichael Anthony Knyszek
Currently bulkBarrierPreWrite follows a fairly slow path wherein it calls typePointersOf, which ends up calling into fastForward. This does some fairly heavy computation to move the iterator forward without any assumptions about where it lands at all. It needs to be completely general to support splitting at arbitrary boundaries, for example for scanning oblets. This means that copying objects during the GC mark phase is fairly expensive, and is a regression from before allocheaders. However, in almost all cases bulkBarrierPreWrite and bulkBarrierPreWriteSrcOnly have perfect type information. We can do a lot better in these cases because we're starting on a type-size boundary, which is exactly what the iterator is built around. This change adds the typePointersOfType method which produces a typePointers iterator from a pointer and a type. This change significantly improves the performance of these bulk write barriers, eliminating some performance regressions that were noticed on the perf dashboard. There are still just a couple cases where we have to use the more general typePointersOf calls, but they're fairly rare; most bulk barriers have perfect type information. This change is tested by the GCInfo tests in the runtime and the GCBits tests in the reflect package via an additional check in getgcmask. Results for tile38 before and after allocheaders. There was previous a regression in the p90, now it's gone. Also, the overall win has been boosted slightly. tile38 $ benchstat noallocheaders.results allocheaders.results name old time/op new time/op delta Tile38QueryLoad 481µs ± 1% 468µs ± 1% -2.71% (p=0.000 n=10+10) name old average-RSS-bytes new average-RSS-bytes delta Tile38QueryLoad 6.32GB ± 1% 6.23GB ± 0% -1.38% (p=0.000 n=9+8) name old peak-RSS-bytes new peak-RSS-bytes delta Tile38QueryLoad 6.49GB ± 1% 6.40GB ± 1% -1.38% (p=0.002 n=10+10) name old peak-VM-bytes new peak-VM-bytes delta Tile38QueryLoad 7.72GB ± 1% 7.64GB ± 1% -1.07% (p=0.007 n=10+10) name old p50-latency-ns new p50-latency-ns delta Tile38QueryLoad 212k ± 1% 205k ± 0% -3.02% (p=0.000 n=10+9) name old p90-latency-ns new p90-latency-ns delta Tile38QueryLoad 622k ± 1% 616k ± 1% -1.03% (p=0.005 n=10+10) name old p99-latency-ns new p99-latency-ns delta Tile38QueryLoad 4.55M ± 2% 4.39M ± 2% -3.51% (p=0.000 n=10+10) name old ops/s new ops/s delta Tile38QueryLoad 12.5k ± 1% 12.8k ± 1% +2.78% (p=0.000 n=10+10) Change-Id: I0a48f848eae8777d0fd6769c3a1fe449f8d9d0a6 Reviewed-on: https://go-review.googlesource.com/c/go/+/542219 Reviewed-by: Cherry Mui <cherryyz@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2023-11-15reflect: optimize Value.IsZero for array typesqiulaidongfeng
For some types where the zero value is a value where all bits of this type are 0 optimize it goos: windows goarch: amd64 pkg: reflect cpu: AMD Ryzen 7 7840HS w/ Radeon 780M Graphics │ std.txt │ new.txt │ │ sec/op │ sec/op vs base │ IsZero/ArrayComparable-16 8.483n ± 0% 8.470n ± 2% ~ (p=0.542 n=10) IsZero/ArrayIncomparable-16 88.13n ± 1% 87.34n ± 2% ~ (p=0.110 n=10) IsZero/StructComparable-16 4.050n ± 2% 4.011n ± 1% ~ (p=0.093 n=10) IsZero/StructIncomparable-16 19.93n ± 1% 19.81n ± 1% ~ (p=0.493 n=10) IsZero/ArrayInt_4-16 4.445n ± 2% 4.478n ± 2% ~ (p=0.306 n=10) IsZero/ArrayInt_1024-16 3381.5n ± 3% 140.8n ± 1% -95.84% (p=0.000 n=10) IsZero/ArrayInt_1024_NoZero-16 1760.50n ± 3% 72.17n ± 1% -95.90% (p=0.000 n=10) IsZero/Struct4Int-16 4.495n ± 3% 4.478n ± 1% ~ (p=0.579 n=10) IsZero/ArrayStruct4Int_1024-16 1404.0n ± 3% 140.5n ± 0% -90.00% (p=0.000 n=10) IsZero/ArrayChanInt_1024-16 3437.0n ± 6% 140.5n ± 1% -95.91% (p=0.000 n=10) geomean 89.94n 27.38n -69.56% Change-Id: I835231a79b9cd89686d44c5b8c2fbe629ccd98ba GitHub-Last-Rev: 3abe118a108faf0070b56ba9098871746daa1ac1 GitHub-Pull-Request: golang/go#63661 Reviewed-on: https://go-review.googlesource.com/c/go/+/536855 Reviewed-by: Cherry Mui <cherryyz@google.com> Reviewed-by: Keith Randall <khr@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Keith Randall <khr@google.com>
2023-09-01reflect: make Value.IsZero identical to v == zeroJoe Tsai
The upcoming built-in zero value provides an idiomatic way to test for zero by comparing to the zero literal: v == zero. The reflect package is meant to provide a programmatic way to perform operations that the Go language itself provides. Thus, it seems prudent that reflect.ValueOf(&v).Elem().IsZero() is identical to v == zero. This change alters the behavior of Value.IsZero in two concrete ways: * negative zero is identical to zero * blank fields in a struct are ignored Prior to this change, we were already in an inconsistent state due to a regression introduced by CL 411478. The new behavior was already the case for comparable composite types. This change makes it consistent for all other types (in particular incomparable composite types and standalone numbers). Updates #61372 Fixes #61827 Change-Id: Id23fb97eb3b8921417cc75a1d3ead963e22dc3d9 Reviewed-on: https://go-review.googlesource.com/c/go/+/517777 Reviewed-by: Russ Cox <rsc@golang.org> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Ian Lance Taylor <iant@google.com>
2023-08-01reflect: make linkable cross-references in documentationKeith Randall
This makes it easier to click around in documentation on pkg.go.dev. Change-Id: Idc67c312bc72c612e660607e5400b43ecc110bc1 Reviewed-on: https://go-review.googlesource.com/c/go/+/514895 Run-TryBot: Keith Randall <khr@golang.org> Auto-Submit: Keith Randall <khr@google.com> Reviewed-by: Keith Randall <khr@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@google.com>
2023-07-21reflect: panic on recv channel closeMauri de Souza Meneguzzo
It is possible to call reflect.ValueOf(ch).Close() on a recv-only channel, while close(ch) is a compile-time error. Following the same reflect semantics as send and recv this should result in a panic. Fixes #61445 Change-Id: I2a9ee8f45963593a37bd6df4643dd64fb322f9f9 GitHub-Last-Rev: fe2d5e09f5bb5536ac25d1606cf3744fb7a0a4a9 GitHub-Pull-Request: golang/go#61453 Reviewed-on: https://go-review.googlesource.com/c/go/+/511295 Auto-Submit: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Ian Lance Taylor <iant@google.com> Reviewed-by: Bryan Mills <bcmills@google.com> Reviewed-by: Ian Lance Taylor <iant@google.com>
2023-05-12reflect: make Value.IsZero not escapeCherry Mui
With CL 408826 reflect.Value not always escape. IsZero still escapes the Value because in some cases it passes the Value pointer to the equal function, which is function pointer. Equal functions are compiler generated and never escapes, but the escape analysis doesn't know. Add noescape to help. Change-Id: Ica397c2be77cac9e8a46d03d70bac385b0aa9e82 Reviewed-on: https://go-review.googlesource.com/c/go/+/441937 Reviewed-by: David Chase <drchase@google.com> Run-TryBot: Cherry Mui <cherryyz@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
2023-05-12reflect: do not escape Value.TypeCherry Mui
Types are either static (for compiler-created types) or heap allocated and always reachable (for reflection-created types, held in the central map). So there is no need to escape types. With CL 408826 reflect.Value does not always escape. Some functions that escapes Value.typ would make the Value escape without this CL. Had to add a special case for the inliner to keep (*Value).Type still inlineable. Change-Id: I7c14d35fd26328347b509a06eb5bd1534d40775f Reviewed-on: https://go-review.googlesource.com/c/go/+/413474 Reviewed-by: Austin Clements <austin@google.com> Reviewed-by: David Chase <drchase@google.com> Run-TryBot: Cherry Mui <cherryyz@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
2023-05-12reflect: allow Value be stack allocatedCherry Mui
Currently, reflect.ValueOf forces the referenced object to be heap allocated. This CL makes it possible to be stack allocated. We need to be careful to make sure the compiler's escape analysis can do the right thing, e.g. channel send, map assignment, unsafe pointer conversions. Tests will be added in a later CL. CL 408827 might help ensure the correctness. Change-Id: I8663651370c7c8108584902235062dd2b3f65954 Reviewed-on: https://go-review.googlesource.com/c/go/+/408826 Run-TryBot: Cherry Mui <cherryyz@google.com> Reviewed-by: David Chase <drchase@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Austin Clements <austin@google.com>
2023-05-12Revert "reflect: change rtype so that it (not *rtype) implements Type"Austin Clements
This reverts CL 487558, which is causing test failures in Google. See b/282133554. Change-Id: Icafa4ffc6aaa24a363abb90b8ae0b0183aca2b89 Reviewed-on: https://go-review.googlesource.com/c/go/+/494410 TryBot-Result: Gopher Robot <gobot@golang.org> Auto-Submit: Austin Clements <austin@google.com> Reviewed-by: David Chase <drchase@google.com> Run-TryBot: Austin Clements <austin@google.com>
2023-05-11reflect: change rtype so that it (not *rtype) implements TypeDavid Chase
The abi.Type field was changed to *abi.Type, thus the bitwise representation is the same, many casts are now avoided and replace by either rtype{afoo} or rfoo.Type. Change-Id: Ie7643edc714a0e56027c2875498a4dfe989cf7dd Reviewed-on: https://go-review.googlesource.com/c/go/+/487558 Run-TryBot: David Chase <drchase@google.com> Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Keith Randall <khr@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
2023-05-11reflect: replacing almost all use of *rtype with *abi.TypeDavid Chase
Change-Id: I3601525b10237d828c449c62a3447f66cb6f025e Reviewed-on: https://go-review.googlesource.com/c/go/+/487557 Run-TryBot: David Chase <drchase@google.com> Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Keith Randall <khr@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
2023-05-10reflect: move funcType to abi/type.goDavid Chase
Change-Id: I381229ba67a39487cdcc60da1c73d33b0a7d494a Reviewed-on: https://go-review.googlesource.com/c/go/+/487556 Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Keith Randall <khr@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: David Chase <drchase@google.com>
2023-05-10reflect: prepare fieldnames for moving to abi/type.goDavid Chase
Change-Id: Ia8e88029d29a1210dc7a321578e61336e235f35a Reviewed-on: https://go-review.googlesource.com/c/go/+/487555 Reviewed-by: Keith Randall <khr@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: David Chase <drchase@google.com> Reviewed-by: Keith Randall <khr@golang.org>
2023-05-10internal/abi,reflectlite,reflect,runtime: common up chan typeDavid Chase
Change-Id: I085b61c544b85d70fabb1c0d9fe91207826dd21a Reviewed-on: https://go-review.googlesource.com/c/go/+/484858 TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org> Run-TryBot: David Chase <drchase@google.com> Reviewed-by: Keith Randall <khr@google.com>
2023-05-10reflect: move more types, constants, functions into internal/abiDavid Chase
Change-Id: Ib9cd15576896225e7c5e6fda11f1a77f6993a91a Reviewed-on: https://go-review.googlesource.com/c/go/+/484857 Run-TryBot: David Chase <drchase@google.com> Reviewed-by: Keith Randall <khr@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Keith Randall <khr@google.com>
2023-05-10internal/abi: common up ArrayTypeDavid Chase
This refactoring is more problematic because the client package wrap abi.Type, thus the self-referential fields within ArrayType need to be downcast to the client wrappers in several places. It's not clear to me this is worthwhile; this CL is for additional comment, before I attempt similar changes for other self-referential types. Change-Id: I41e517e6d851b32560c41676b91b76d7eb17c951 Reviewed-on: https://go-review.googlesource.com/c/go/+/466236 Run-TryBot: David Chase <drchase@google.com> Reviewed-by: Keith Randall <khr@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Keith Randall <khr@google.com>
2023-05-10internal/abi: common up Method, Imethod, UncommonType typesDavid Chase
was two commits, the first contained a lot of intermediate work, better this way. Change-Id: I7c5b79ef78b21a85828c8aaf9baeae86bb144db7 Reviewed-on: https://go-review.googlesource.com/c/go/+/463118 Reviewed-by: Keith Randall <khr@golang.org> Run-TryBot: David Chase <drchase@google.com> Reviewed-by: Keith Randall <khr@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
2023-05-05internal/abi: refactor (basic) type struct into one definitionDavid Chase
This touches a lot of files, which is bad, but it is also good, since there's N copies of this information commoned into 1. The new files in internal/abi are copied from the end of the stack; ultimately this will all end up being used. Change-Id: Ia252c0055aaa72ca569411ef9f9e96e3d610889e Reviewed-on: https://go-review.googlesource.com/c/go/+/462995 TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Carlos Amedee <carlos@golang.org> Run-TryBot: David Chase <drchase@google.com> Reviewed-by: Keith Randall <khr@golang.org>
2023-04-10reflect: remove typedmemmovepartial as it is unusedDaniel Martí
It appears to have been unused since https://go.dev/cl/298670 in April 2021, as that change removed its only use. It is always in the git history if it is needed again. Change-Id: Ie55d059c102dfaa75bd253e09d48a4b30f45e941 Reviewed-on: https://go-review.googlesource.com/c/go/+/483136 Reviewed-by: Michael Pratt <mpratt@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Daniel Martí <mvdan@mvdan.cc> Reviewed-by: Michael Knyszek <mknyszek@google.com> Auto-Submit: Michael Pratt <mpratt@google.com>