From 890e31c1784d23b90c19e1d4f83621f3a6b13647 Mon Sep 17 00:00:00 2001 From: qiulaidongfeng <2645477756@qq.com> Date: Wed, 31 Jan 2024 14:41:53 +0800 Subject: [PATCH] runtime,reflect: clean duplicate definitions runtimeSelect For #65355 Change-Id: I32f37b2971996d50451505e412157dd49b29f581 --- src/cmd/internal/objabi/pkgspecial.go | 2 ++ src/go/build/deps_test.go | 5 ++-- src/internal/runtime/rchan/select.go | 27 +++++++++++++++++ src/reflect/value.go | 42 +++++++++++---------------- src/runtime/select.go | 32 +++++--------------- 5 files changed, 56 insertions(+), 52 deletions(-) create mode 100644 src/internal/runtime/rchan/select.go diff --git a/src/cmd/internal/objabi/pkgspecial.go b/src/cmd/internal/objabi/pkgspecial.go index 6df95f33f93692..d669e45dd04b90 100644 --- a/src/cmd/internal/objabi/pkgspecial.go +++ b/src/cmd/internal/objabi/pkgspecial.go @@ -57,6 +57,8 @@ var runtimePkgs = []string{ "internal/godebugs", "internal/goexperiment", "internal/goos", + + "internal/runtime/rchan", } // extraNoInstrumentPkgs is the set of packages in addition to runtimePkgs that diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index 47a0f3a0b409d4..84fa39589756fc 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -54,7 +54,7 @@ var depsRules = ` internal/goarch, unsafe < internal/abi, internal/chacha8rand; - unsafe < maps; + unsafe < maps, internal/runtime/rchan; # RUNTIME is the core runtime group of packages, all of them very light-weight. internal/abi, @@ -63,6 +63,7 @@ var depsRules = ` internal/cpu, internal/goarch, internal/godebugs, + internal/runtime/rchan, internal/goexperiment, internal/goos < internal/bytealg @@ -189,7 +190,7 @@ var depsRules = ` # FMT is OS (which includes string routines) plus reflect and fmt. # It does not include package log, which should be avoided in core packages. - arena, strconv, unicode + arena, strconv, unicode, internal/runtime/rchan < reflect; os, reflect diff --git a/src/internal/runtime/rchan/select.go b/src/internal/runtime/rchan/select.go new file mode 100644 index 00000000000000..74061173c164aa --- /dev/null +++ b/src/internal/runtime/rchan/select.go @@ -0,0 +1,27 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rchan + +import ( + "unsafe" +) + +// A Select is a single case passed to rselect. +type Select struct { + Dir SelectDir + Typ unsafe.Pointer // channel type (not used here) + Ch unsafe.Pointer // channel + Val unsafe.Pointer // ptr to data (SendDir) or ptr to receive buffer (RecvDir) +} + +// These values must match ../reflect/value.go:/SelectDir. +type SelectDir int + +const ( + _ SelectDir = iota + SelectSend // case Chan <- Send + SelectRecv // case <-Chan: + SelectDefault // default +) diff --git a/src/reflect/value.go b/src/reflect/value.go index 60ba79a6e68bab..2719b26cf1689c 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -9,6 +9,7 @@ import ( "internal/abi" "internal/goarch" "internal/itoa" + "internal/runtime/rchan" "internal/unsafeheader" "math" "runtime" @@ -3015,15 +3016,6 @@ func Copy(dst, src Value) int { return typedslicecopy(de.Common(), ds, ss) } -// A runtimeSelect is a single case passed to rselect. -// This must match ../runtime/select.go:/runtimeSelect -type runtimeSelect struct { - dir SelectDir // SelectSend, SelectRecv or SelectDefault - typ *rtype // channel type - ch unsafe.Pointer // channel - val unsafe.Pointer // ptr to data (SendDir) or ptr to receive buffer (RecvDir) -} - // rselect runs a select. It returns the index of the chosen case. // If the case was a receive, val is filled in with the received value. // The conventional OK bool indicates whether the receive corresponds @@ -3035,7 +3027,7 @@ type runtimeSelect struct { // that with a forced escape in function Select. // //go:noescape -func rselect([]runtimeSelect) (chosen int, recvOK bool) +func rselect([]rchan.Select) (chosen int, recvOK bool) // A SelectDir describes the communication direction of a select case. type SelectDir int @@ -3086,19 +3078,19 @@ func Select(cases []SelectCase) (chosen int, recv Value, recvOK bool) { // NOTE: Do not trust that caller is not modifying cases data underfoot. // The range is safe because the caller cannot modify our copy of the len // and each iteration makes its own copy of the value c. - var runcases []runtimeSelect + var runcases []rchan.Select if len(cases) > 4 { // Slice is heap allocated due to runtime dependent capacity. - runcases = make([]runtimeSelect, len(cases)) + runcases = make([]rchan.Select, len(cases)) } else { // Slice can be stack allocated due to constant capacity. - runcases = make([]runtimeSelect, len(cases), 4) + runcases = make([]rchan.Select, len(cases), 4) } haveDefault := false for i, c := range cases { rc := &runcases[i] - rc.dir = c.Dir + rc.Dir = rchan.SelectDir(c.Dir) switch c.Dir { default: panic("reflect.Select: invalid Dir") @@ -3126,8 +3118,8 @@ func Select(cases []SelectCase) (chosen int, recv Value, recvOK bool) { if ChanDir(tt.Dir)&SendDir == 0 { panic("reflect.Select: SendDir case using recv-only channel") } - rc.ch = ch.pointer() - rc.typ = toRType(&tt.Type) + rc.Ch = ch.pointer() + rc.Typ = (unsafe.Pointer)(&tt.Type) v := c.Send if !v.IsValid() { panic("reflect.Select: SendDir case missing Send value") @@ -3135,13 +3127,13 @@ func Select(cases []SelectCase) (chosen int, recv Value, recvOK bool) { v.mustBeExported() v = v.assignTo("reflect.Select", tt.Elem, nil) if v.flag&flagIndir != 0 { - rc.val = v.ptr + rc.Val = v.ptr } else { - rc.val = unsafe.Pointer(&v.ptr) + rc.Val = unsafe.Pointer(&v.ptr) } // The value to send needs to escape. See the comment at rselect for // why we need forced escape. - escapes(rc.val) + escapes(rc.Val) case SelectRecv: if c.Send.IsValid() { @@ -3157,17 +3149,17 @@ func Select(cases []SelectCase) (chosen int, recv Value, recvOK bool) { if ChanDir(tt.Dir)&RecvDir == 0 { panic("reflect.Select: RecvDir case using send-only channel") } - rc.ch = ch.pointer() - rc.typ = toRType(&tt.Type) - rc.val = unsafe_New(tt.Elem) + rc.Ch = ch.pointer() + rc.Typ = (unsafe.Pointer)(&tt.Type) + rc.Val = unsafe_New(tt.Elem) } } chosen, recvOK = rselect(runcases) - if runcases[chosen].dir == SelectRecv { - tt := (*chanType)(unsafe.Pointer(runcases[chosen].typ)) + if runcases[chosen].Dir == rchan.SelectDir(SelectRecv) { + tt := (*chanType)(unsafe.Pointer(runcases[chosen].Typ)) t := tt.Elem - p := runcases[chosen].val + p := runcases[chosen].Val fl := flag(t.Kind()) if t.IfaceIndir() { recv = Value{t, p, fl | flagIndir} diff --git a/src/runtime/select.go b/src/runtime/select.go index b3a3085cb03bf9..fb5240a9b5d8b2 100644 --- a/src/runtime/select.go +++ b/src/runtime/select.go @@ -8,6 +8,7 @@ package runtime import ( "internal/abi" + "internal/runtime/rchan" "unsafe" ) @@ -519,27 +520,8 @@ func (c *hchan) sortkey() uintptr { return uintptr(unsafe.Pointer(c)) } -// A runtimeSelect is a single case passed to rselect. -// This must match ../reflect/value.go:/runtimeSelect -type runtimeSelect struct { - dir selectDir - typ unsafe.Pointer // channel type (not used here) - ch *hchan // channel - val unsafe.Pointer // ptr to data (SendDir) or ptr to receive buffer (RecvDir) -} - -// These values must match ../reflect/value.go:/SelectDir. -type selectDir int - -const ( - _ selectDir = iota - selectSend // case Chan <- Send - selectRecv // case <-Chan: - selectDefault // default -) - //go:linkname reflect_rselect reflect.rselect -func reflect_rselect(cases []runtimeSelect) (int, bool) { +func reflect_rselect(cases []rchan.Select) (int, bool) { if len(cases) == 0 { block() } @@ -549,19 +531,19 @@ func reflect_rselect(cases []runtimeSelect) (int, bool) { dflt := -1 for i, rc := range cases { var j int - switch rc.dir { - case selectDefault: + switch rc.Dir { + case rchan.SelectDefault: dflt = i continue - case selectSend: + case rchan.SelectSend: j = nsends nsends++ - case selectRecv: + case rchan.SelectRecv: nrecvs++ j = len(cases) - nrecvs } - sel[j] = scase{c: rc.ch, elem: rc.val} + sel[j] = scase{c: (*hchan)(rc.Ch), elem: rc.Val} orig[j] = i }