mirror of
https://github.com/golang/go
synced 2024-11-26 01:07:57 -07:00
cmd/compile: compile len(ch) as call to runtime.chanlen
An upcoming CL will give this call more to do. For now, separate out the compiler change that stops inlining the computation. Change-Id: I4c5cbd84a0694b306191bff38cc6ea2d69458d7d Reviewed-on: https://go-review.googlesource.com/c/go/+/564556 Auto-Submit: Russ Cox <rsc@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
parent
370c8e983b
commit
b6753baaed
@ -6349,6 +6349,9 @@ func (s *state) referenceTypeBuiltin(n *ir.UnaryExpr, x *ssa.Value) *ssa.Value {
|
||||
if !n.X.Type().IsMap() && !n.X.Type().IsChan() {
|
||||
s.Fatalf("node must be a map or a channel")
|
||||
}
|
||||
if n.X.Type().IsChan() && n.Op() == ir.OLEN {
|
||||
s.Fatalf("cannot inline len(chan)") // must use runtime.chanlen now
|
||||
}
|
||||
// if n == nil {
|
||||
// return 0
|
||||
// } else {
|
||||
|
@ -3,6 +3,7 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// NOTE: If you change this file you must run "go generate"
|
||||
// in cmd/compile/internal/typecheck
|
||||
// to update builtin.go. This is not done automatically
|
||||
// to avoid depending on having a working compiler binary.
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// NOTE: If you change this file you must run "go generate"
|
||||
// in cmd/compile/internal/typecheck
|
||||
// to update builtin.go. This is not done automatically
|
||||
// to avoid depending on having a working compiler binary.
|
||||
|
||||
@ -158,7 +159,8 @@ func makechan(chanType *byte, size int) (hchan chan any)
|
||||
func chanrecv1(hchan <-chan any, elem *any)
|
||||
func chanrecv2(hchan <-chan any, elem *any) bool
|
||||
func chansend1(hchan chan<- any, elem *any)
|
||||
func closechan(hchan any)
|
||||
func closechan(hchan chan<- any)
|
||||
func chanlen(hchan any) int
|
||||
|
||||
var writeBarrier struct {
|
||||
enabled bool
|
||||
|
@ -136,106 +136,107 @@ var runtimeDecls = [...]struct {
|
||||
{"chanrecv1", funcTag, 100},
|
||||
{"chanrecv2", funcTag, 101},
|
||||
{"chansend1", funcTag, 103},
|
||||
{"closechan", funcTag, 30},
|
||||
{"writeBarrier", varTag, 105},
|
||||
{"typedmemmove", funcTag, 106},
|
||||
{"typedmemclr", funcTag, 107},
|
||||
{"typedslicecopy", funcTag, 108},
|
||||
{"selectnbsend", funcTag, 109},
|
||||
{"selectnbrecv", funcTag, 110},
|
||||
{"selectsetpc", funcTag, 111},
|
||||
{"selectgo", funcTag, 112},
|
||||
{"closechan", funcTag, 104},
|
||||
{"chanlen", funcTag, 105},
|
||||
{"writeBarrier", varTag, 107},
|
||||
{"typedmemmove", funcTag, 108},
|
||||
{"typedmemclr", funcTag, 109},
|
||||
{"typedslicecopy", funcTag, 110},
|
||||
{"selectnbsend", funcTag, 111},
|
||||
{"selectnbrecv", funcTag, 112},
|
||||
{"selectsetpc", funcTag, 113},
|
||||
{"selectgo", funcTag, 114},
|
||||
{"block", funcTag, 9},
|
||||
{"makeslice", funcTag, 113},
|
||||
{"makeslice64", funcTag, 114},
|
||||
{"makeslicecopy", funcTag, 115},
|
||||
{"growslice", funcTag, 117},
|
||||
{"unsafeslicecheckptr", funcTag, 118},
|
||||
{"makeslice", funcTag, 115},
|
||||
{"makeslice64", funcTag, 116},
|
||||
{"makeslicecopy", funcTag, 117},
|
||||
{"growslice", funcTag, 119},
|
||||
{"unsafeslicecheckptr", funcTag, 120},
|
||||
{"panicunsafeslicelen", funcTag, 9},
|
||||
{"panicunsafeslicenilptr", funcTag, 9},
|
||||
{"unsafestringcheckptr", funcTag, 119},
|
||||
{"unsafestringcheckptr", funcTag, 121},
|
||||
{"panicunsafestringlen", funcTag, 9},
|
||||
{"panicunsafestringnilptr", funcTag, 9},
|
||||
{"memmove", funcTag, 120},
|
||||
{"memclrNoHeapPointers", funcTag, 121},
|
||||
{"memclrHasPointers", funcTag, 121},
|
||||
{"memequal", funcTag, 122},
|
||||
{"memequal0", funcTag, 123},
|
||||
{"memequal8", funcTag, 123},
|
||||
{"memequal16", funcTag, 123},
|
||||
{"memequal32", funcTag, 123},
|
||||
{"memequal64", funcTag, 123},
|
||||
{"memequal128", funcTag, 123},
|
||||
{"f32equal", funcTag, 124},
|
||||
{"f64equal", funcTag, 124},
|
||||
{"c64equal", funcTag, 124},
|
||||
{"c128equal", funcTag, 124},
|
||||
{"strequal", funcTag, 124},
|
||||
{"interequal", funcTag, 124},
|
||||
{"nilinterequal", funcTag, 124},
|
||||
{"memhash", funcTag, 125},
|
||||
{"memhash0", funcTag, 126},
|
||||
{"memhash8", funcTag, 126},
|
||||
{"memhash16", funcTag, 126},
|
||||
{"memhash32", funcTag, 126},
|
||||
{"memhash64", funcTag, 126},
|
||||
{"memhash128", funcTag, 126},
|
||||
{"f32hash", funcTag, 127},
|
||||
{"f64hash", funcTag, 127},
|
||||
{"c64hash", funcTag, 127},
|
||||
{"c128hash", funcTag, 127},
|
||||
{"strhash", funcTag, 127},
|
||||
{"interhash", funcTag, 127},
|
||||
{"nilinterhash", funcTag, 127},
|
||||
{"int64div", funcTag, 128},
|
||||
{"uint64div", funcTag, 129},
|
||||
{"int64mod", funcTag, 128},
|
||||
{"uint64mod", funcTag, 129},
|
||||
{"float64toint64", funcTag, 130},
|
||||
{"float64touint64", funcTag, 131},
|
||||
{"float64touint32", funcTag, 132},
|
||||
{"int64tofloat64", funcTag, 133},
|
||||
{"int64tofloat32", funcTag, 135},
|
||||
{"uint64tofloat64", funcTag, 136},
|
||||
{"uint64tofloat32", funcTag, 137},
|
||||
{"uint32tofloat64", funcTag, 138},
|
||||
{"complex128div", funcTag, 139},
|
||||
{"getcallerpc", funcTag, 140},
|
||||
{"getcallersp", funcTag, 140},
|
||||
{"memmove", funcTag, 122},
|
||||
{"memclrNoHeapPointers", funcTag, 123},
|
||||
{"memclrHasPointers", funcTag, 123},
|
||||
{"memequal", funcTag, 124},
|
||||
{"memequal0", funcTag, 125},
|
||||
{"memequal8", funcTag, 125},
|
||||
{"memequal16", funcTag, 125},
|
||||
{"memequal32", funcTag, 125},
|
||||
{"memequal64", funcTag, 125},
|
||||
{"memequal128", funcTag, 125},
|
||||
{"f32equal", funcTag, 126},
|
||||
{"f64equal", funcTag, 126},
|
||||
{"c64equal", funcTag, 126},
|
||||
{"c128equal", funcTag, 126},
|
||||
{"strequal", funcTag, 126},
|
||||
{"interequal", funcTag, 126},
|
||||
{"nilinterequal", funcTag, 126},
|
||||
{"memhash", funcTag, 127},
|
||||
{"memhash0", funcTag, 128},
|
||||
{"memhash8", funcTag, 128},
|
||||
{"memhash16", funcTag, 128},
|
||||
{"memhash32", funcTag, 128},
|
||||
{"memhash64", funcTag, 128},
|
||||
{"memhash128", funcTag, 128},
|
||||
{"f32hash", funcTag, 129},
|
||||
{"f64hash", funcTag, 129},
|
||||
{"c64hash", funcTag, 129},
|
||||
{"c128hash", funcTag, 129},
|
||||
{"strhash", funcTag, 129},
|
||||
{"interhash", funcTag, 129},
|
||||
{"nilinterhash", funcTag, 129},
|
||||
{"int64div", funcTag, 130},
|
||||
{"uint64div", funcTag, 131},
|
||||
{"int64mod", funcTag, 130},
|
||||
{"uint64mod", funcTag, 131},
|
||||
{"float64toint64", funcTag, 132},
|
||||
{"float64touint64", funcTag, 133},
|
||||
{"float64touint32", funcTag, 134},
|
||||
{"int64tofloat64", funcTag, 135},
|
||||
{"int64tofloat32", funcTag, 137},
|
||||
{"uint64tofloat64", funcTag, 138},
|
||||
{"uint64tofloat32", funcTag, 139},
|
||||
{"uint32tofloat64", funcTag, 140},
|
||||
{"complex128div", funcTag, 141},
|
||||
{"getcallerpc", funcTag, 142},
|
||||
{"getcallersp", funcTag, 142},
|
||||
{"racefuncenter", funcTag, 31},
|
||||
{"racefuncexit", funcTag, 9},
|
||||
{"raceread", funcTag, 31},
|
||||
{"racewrite", funcTag, 31},
|
||||
{"racereadrange", funcTag, 141},
|
||||
{"racewriterange", funcTag, 141},
|
||||
{"msanread", funcTag, 141},
|
||||
{"msanwrite", funcTag, 141},
|
||||
{"msanmove", funcTag, 142},
|
||||
{"asanread", funcTag, 141},
|
||||
{"asanwrite", funcTag, 141},
|
||||
{"checkptrAlignment", funcTag, 143},
|
||||
{"checkptrArithmetic", funcTag, 145},
|
||||
{"libfuzzerTraceCmp1", funcTag, 146},
|
||||
{"libfuzzerTraceCmp2", funcTag, 147},
|
||||
{"libfuzzerTraceCmp4", funcTag, 148},
|
||||
{"libfuzzerTraceCmp8", funcTag, 149},
|
||||
{"libfuzzerTraceConstCmp1", funcTag, 146},
|
||||
{"libfuzzerTraceConstCmp2", funcTag, 147},
|
||||
{"libfuzzerTraceConstCmp4", funcTag, 148},
|
||||
{"libfuzzerTraceConstCmp8", funcTag, 149},
|
||||
{"libfuzzerHookStrCmp", funcTag, 150},
|
||||
{"libfuzzerHookEqualFold", funcTag, 150},
|
||||
{"addCovMeta", funcTag, 152},
|
||||
{"racereadrange", funcTag, 143},
|
||||
{"racewriterange", funcTag, 143},
|
||||
{"msanread", funcTag, 143},
|
||||
{"msanwrite", funcTag, 143},
|
||||
{"msanmove", funcTag, 144},
|
||||
{"asanread", funcTag, 143},
|
||||
{"asanwrite", funcTag, 143},
|
||||
{"checkptrAlignment", funcTag, 145},
|
||||
{"checkptrArithmetic", funcTag, 147},
|
||||
{"libfuzzerTraceCmp1", funcTag, 148},
|
||||
{"libfuzzerTraceCmp2", funcTag, 149},
|
||||
{"libfuzzerTraceCmp4", funcTag, 150},
|
||||
{"libfuzzerTraceCmp8", funcTag, 151},
|
||||
{"libfuzzerTraceConstCmp1", funcTag, 148},
|
||||
{"libfuzzerTraceConstCmp2", funcTag, 149},
|
||||
{"libfuzzerTraceConstCmp4", funcTag, 150},
|
||||
{"libfuzzerTraceConstCmp8", funcTag, 151},
|
||||
{"libfuzzerHookStrCmp", funcTag, 152},
|
||||
{"libfuzzerHookEqualFold", funcTag, 152},
|
||||
{"addCovMeta", funcTag, 154},
|
||||
{"x86HasPOPCNT", varTag, 6},
|
||||
{"x86HasSSE41", varTag, 6},
|
||||
{"x86HasFMA", varTag, 6},
|
||||
{"armHasVFPv4", varTag, 6},
|
||||
{"arm64HasATOMICS", varTag, 6},
|
||||
{"asanregisterglobals", funcTag, 121},
|
||||
{"asanregisterglobals", funcTag, 123},
|
||||
}
|
||||
|
||||
func runtimeTypes() []*types.Type {
|
||||
var typs [153]*types.Type
|
||||
var typs [155]*types.Type
|
||||
typs[0] = types.ByteType
|
||||
typs[1] = types.NewPtr(typs[0])
|
||||
typs[2] = types.Types[types.TANY]
|
||||
@ -340,55 +341,57 @@ func runtimeTypes() []*types.Type {
|
||||
typs[101] = newSig(params(typs[99], typs[3]), params(typs[6]))
|
||||
typs[102] = types.NewChan(typs[2], types.Csend)
|
||||
typs[103] = newSig(params(typs[102], typs[3]), nil)
|
||||
typs[104] = types.NewArray(typs[0], 3)
|
||||
typs[105] = types.NewStruct([]*types.Field{types.NewField(src.NoXPos, Lookup("enabled"), typs[6]), types.NewField(src.NoXPos, Lookup("pad"), typs[104]), types.NewField(src.NoXPos, Lookup("cgo"), typs[6]), types.NewField(src.NoXPos, Lookup("alignme"), typs[24])})
|
||||
typs[106] = newSig(params(typs[1], typs[3], typs[3]), nil)
|
||||
typs[107] = newSig(params(typs[1], typs[3]), nil)
|
||||
typs[108] = newSig(params(typs[1], typs[3], typs[15], typs[3], typs[15]), params(typs[15]))
|
||||
typs[109] = newSig(params(typs[102], typs[3]), params(typs[6]))
|
||||
typs[110] = newSig(params(typs[3], typs[99]), params(typs[6], typs[6]))
|
||||
typs[111] = newSig(params(typs[71]), nil)
|
||||
typs[112] = newSig(params(typs[1], typs[1], typs[71], typs[15], typs[15], typs[6]), params(typs[15], typs[6]))
|
||||
typs[113] = newSig(params(typs[1], typs[15], typs[15]), params(typs[7]))
|
||||
typs[114] = newSig(params(typs[1], typs[22], typs[22]), params(typs[7]))
|
||||
typs[115] = newSig(params(typs[1], typs[15], typs[15], typs[7]), params(typs[7]))
|
||||
typs[116] = types.NewSlice(typs[2])
|
||||
typs[117] = newSig(params(typs[3], typs[15], typs[15], typs[15], typs[1]), params(typs[116]))
|
||||
typs[118] = newSig(params(typs[1], typs[7], typs[22]), nil)
|
||||
typs[119] = newSig(params(typs[7], typs[22]), nil)
|
||||
typs[120] = newSig(params(typs[3], typs[3], typs[5]), nil)
|
||||
typs[121] = newSig(params(typs[7], typs[5]), nil)
|
||||
typs[122] = newSig(params(typs[3], typs[3], typs[5]), params(typs[6]))
|
||||
typs[123] = newSig(params(typs[3], typs[3]), params(typs[6]))
|
||||
typs[124] = newSig(params(typs[7], typs[7]), params(typs[6]))
|
||||
typs[125] = newSig(params(typs[3], typs[5], typs[5]), params(typs[5]))
|
||||
typs[126] = newSig(params(typs[7], typs[5]), params(typs[5]))
|
||||
typs[127] = newSig(params(typs[3], typs[5]), params(typs[5]))
|
||||
typs[128] = newSig(params(typs[22], typs[22]), params(typs[22]))
|
||||
typs[129] = newSig(params(typs[24], typs[24]), params(typs[24]))
|
||||
typs[130] = newSig(params(typs[20]), params(typs[22]))
|
||||
typs[131] = newSig(params(typs[20]), params(typs[24]))
|
||||
typs[132] = newSig(params(typs[20]), params(typs[60]))
|
||||
typs[133] = newSig(params(typs[22]), params(typs[20]))
|
||||
typs[134] = types.Types[types.TFLOAT32]
|
||||
typs[135] = newSig(params(typs[22]), params(typs[134]))
|
||||
typs[136] = newSig(params(typs[24]), params(typs[20]))
|
||||
typs[137] = newSig(params(typs[24]), params(typs[134]))
|
||||
typs[138] = newSig(params(typs[60]), params(typs[20]))
|
||||
typs[139] = newSig(params(typs[26], typs[26]), params(typs[26]))
|
||||
typs[140] = newSig(nil, params(typs[5]))
|
||||
typs[141] = newSig(params(typs[5], typs[5]), nil)
|
||||
typs[142] = newSig(params(typs[5], typs[5], typs[5]), nil)
|
||||
typs[143] = newSig(params(typs[7], typs[1], typs[5]), nil)
|
||||
typs[144] = types.NewSlice(typs[7])
|
||||
typs[145] = newSig(params(typs[7], typs[144]), nil)
|
||||
typs[146] = newSig(params(typs[64], typs[64], typs[17]), nil)
|
||||
typs[147] = newSig(params(typs[58], typs[58], typs[17]), nil)
|
||||
typs[148] = newSig(params(typs[60], typs[60], typs[17]), nil)
|
||||
typs[149] = newSig(params(typs[24], typs[24], typs[17]), nil)
|
||||
typs[150] = newSig(params(typs[28], typs[28], typs[17]), nil)
|
||||
typs[151] = types.NewArray(typs[0], 16)
|
||||
typs[152] = newSig(params(typs[7], typs[60], typs[151], typs[28], typs[15], typs[64], typs[64]), params(typs[60]))
|
||||
typs[104] = newSig(params(typs[102]), nil)
|
||||
typs[105] = newSig(params(typs[2]), params(typs[15]))
|
||||
typs[106] = types.NewArray(typs[0], 3)
|
||||
typs[107] = types.NewStruct([]*types.Field{types.NewField(src.NoXPos, Lookup("enabled"), typs[6]), types.NewField(src.NoXPos, Lookup("pad"), typs[106]), types.NewField(src.NoXPos, Lookup("cgo"), typs[6]), types.NewField(src.NoXPos, Lookup("alignme"), typs[24])})
|
||||
typs[108] = newSig(params(typs[1], typs[3], typs[3]), nil)
|
||||
typs[109] = newSig(params(typs[1], typs[3]), nil)
|
||||
typs[110] = newSig(params(typs[1], typs[3], typs[15], typs[3], typs[15]), params(typs[15]))
|
||||
typs[111] = newSig(params(typs[102], typs[3]), params(typs[6]))
|
||||
typs[112] = newSig(params(typs[3], typs[99]), params(typs[6], typs[6]))
|
||||
typs[113] = newSig(params(typs[71]), nil)
|
||||
typs[114] = newSig(params(typs[1], typs[1], typs[71], typs[15], typs[15], typs[6]), params(typs[15], typs[6]))
|
||||
typs[115] = newSig(params(typs[1], typs[15], typs[15]), params(typs[7]))
|
||||
typs[116] = newSig(params(typs[1], typs[22], typs[22]), params(typs[7]))
|
||||
typs[117] = newSig(params(typs[1], typs[15], typs[15], typs[7]), params(typs[7]))
|
||||
typs[118] = types.NewSlice(typs[2])
|
||||
typs[119] = newSig(params(typs[3], typs[15], typs[15], typs[15], typs[1]), params(typs[118]))
|
||||
typs[120] = newSig(params(typs[1], typs[7], typs[22]), nil)
|
||||
typs[121] = newSig(params(typs[7], typs[22]), nil)
|
||||
typs[122] = newSig(params(typs[3], typs[3], typs[5]), nil)
|
||||
typs[123] = newSig(params(typs[7], typs[5]), nil)
|
||||
typs[124] = newSig(params(typs[3], typs[3], typs[5]), params(typs[6]))
|
||||
typs[125] = newSig(params(typs[3], typs[3]), params(typs[6]))
|
||||
typs[126] = newSig(params(typs[7], typs[7]), params(typs[6]))
|
||||
typs[127] = newSig(params(typs[3], typs[5], typs[5]), params(typs[5]))
|
||||
typs[128] = newSig(params(typs[7], typs[5]), params(typs[5]))
|
||||
typs[129] = newSig(params(typs[3], typs[5]), params(typs[5]))
|
||||
typs[130] = newSig(params(typs[22], typs[22]), params(typs[22]))
|
||||
typs[131] = newSig(params(typs[24], typs[24]), params(typs[24]))
|
||||
typs[132] = newSig(params(typs[20]), params(typs[22]))
|
||||
typs[133] = newSig(params(typs[20]), params(typs[24]))
|
||||
typs[134] = newSig(params(typs[20]), params(typs[60]))
|
||||
typs[135] = newSig(params(typs[22]), params(typs[20]))
|
||||
typs[136] = types.Types[types.TFLOAT32]
|
||||
typs[137] = newSig(params(typs[22]), params(typs[136]))
|
||||
typs[138] = newSig(params(typs[24]), params(typs[20]))
|
||||
typs[139] = newSig(params(typs[24]), params(typs[136]))
|
||||
typs[140] = newSig(params(typs[60]), params(typs[20]))
|
||||
typs[141] = newSig(params(typs[26], typs[26]), params(typs[26]))
|
||||
typs[142] = newSig(nil, params(typs[5]))
|
||||
typs[143] = newSig(params(typs[5], typs[5]), nil)
|
||||
typs[144] = newSig(params(typs[5], typs[5], typs[5]), nil)
|
||||
typs[145] = newSig(params(typs[7], typs[1], typs[5]), nil)
|
||||
typs[146] = types.NewSlice(typs[7])
|
||||
typs[147] = newSig(params(typs[7], typs[146]), nil)
|
||||
typs[148] = newSig(params(typs[64], typs[64], typs[17]), nil)
|
||||
typs[149] = newSig(params(typs[58], typs[58], typs[17]), nil)
|
||||
typs[150] = newSig(params(typs[60], typs[60], typs[17]), nil)
|
||||
typs[151] = newSig(params(typs[24], typs[24], typs[17]), nil)
|
||||
typs[152] = newSig(params(typs[28], typs[28], typs[17]), nil)
|
||||
typs[153] = types.NewArray(typs[0], 16)
|
||||
typs[154] = newSig(params(typs[7], typs[60], typs[153], typs[28], typs[15], typs[64], typs[64]), params(typs[60]))
|
||||
return typs[:]
|
||||
}
|
||||
|
||||
|
@ -153,9 +153,7 @@ func walkClear(n *ir.UnaryExpr) ir.Node {
|
||||
|
||||
// walkClose walks an OCLOSE node.
|
||||
func walkClose(n *ir.UnaryExpr, init *ir.Nodes) ir.Node {
|
||||
// cannot use chanfn - closechan takes any, not chan any
|
||||
fn := typecheck.LookupRuntime("closechan", n.X.Type())
|
||||
return mkcall1(fn, nil, init, n.X)
|
||||
return mkcall1(chanfn("closechan", 1, n.X.Type()), nil, init, n.X)
|
||||
}
|
||||
|
||||
// Lower copy(a, b) to a memmove call or a runtime call.
|
||||
@ -263,6 +261,12 @@ func walkLenCap(n *ir.UnaryExpr, init *ir.Nodes) ir.Node {
|
||||
_, len := backingArrayPtrLen(cheapExpr(conv.X, init))
|
||||
return len
|
||||
}
|
||||
if isChanLen(n) {
|
||||
// cannot use chanfn - closechan takes any, not chan any,
|
||||
// because it accepts both send-only and recv-only channels.
|
||||
fn := typecheck.LookupRuntime("chanlen", n.X.Type())
|
||||
return mkcall1(fn, n.Type(), init, n.X)
|
||||
}
|
||||
|
||||
n.X = walkExpr(n.X, init)
|
||||
|
||||
@ -887,3 +891,10 @@ func isByteCount(n ir.Node) bool {
|
||||
return base.Flag.N == 0 && !base.Flag.Cfg.Instrumenting && n.Op() == ir.OLEN &&
|
||||
(n.(*ir.UnaryExpr).X.Op() == ir.OBYTES2STR || n.(*ir.UnaryExpr).X.Op() == ir.OBYTES2STRTMP)
|
||||
}
|
||||
|
||||
// isChanLen reports whether n is of the form len(c) for a channel c.
|
||||
// Note that this does not check for -n or instrumenting because this
|
||||
// is a correctness rewrite, not an optimization.
|
||||
func isChanLen(n ir.Node) bool {
|
||||
return n.Op() == ir.OLEN && n.(*ir.UnaryExpr).X.Type().IsChan()
|
||||
}
|
||||
|
@ -724,20 +724,21 @@ func reflect_chanrecv(c *hchan, nb bool, elem unsafe.Pointer) (selected bool, re
|
||||
return chanrecv(c, elem, !nb)
|
||||
}
|
||||
|
||||
//go:linkname reflect_chanlen reflect.chanlen
|
||||
func reflect_chanlen(c *hchan) int {
|
||||
func chanlen(c *hchan) int {
|
||||
if c == nil {
|
||||
return 0
|
||||
}
|
||||
return int(c.qcount)
|
||||
}
|
||||
|
||||
//go:linkname reflect_chanlen reflect.chanlen
|
||||
func reflect_chanlen(c *hchan) int {
|
||||
return chanlen(c)
|
||||
}
|
||||
|
||||
//go:linkname reflectlite_chanlen internal/reflectlite.chanlen
|
||||
func reflectlite_chanlen(c *hchan) int {
|
||||
if c == nil {
|
||||
return 0
|
||||
}
|
||||
return int(c.qcount)
|
||||
return chanlen(c)
|
||||
}
|
||||
|
||||
//go:linkname reflect_chancap reflect.chancap
|
||||
|
Loading…
Reference in New Issue
Block a user