]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: compile len(ch) as call to runtime.chanlen
authorRuss Cox <rsc@golang.org>
Thu, 15 Feb 2024 20:30:16 +0000 (15:30 -0500)
committerGopher Robot <gobot@golang.org>
Wed, 28 Feb 2024 16:59:48 +0000 (16:59 +0000)
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>

src/cmd/compile/internal/ssagen/ssa.go
src/cmd/compile/internal/typecheck/_builtin/coverage.go
src/cmd/compile/internal/typecheck/_builtin/runtime.go
src/cmd/compile/internal/typecheck/builtin.go
src/cmd/compile/internal/walk/builtin.go
src/runtime/chan.go

index 68b1547048f8927f3fcf5cca82d6830f82c5dab5..05919b99245c55c303ca40fbb7aaecc67d16fcf6 100644 (file)
@@ -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 {
index 02226356bc9873df39ecb1b7dc4107e1a73bccc4..f5c9e24991e9b9025ea861bf430876ccd6e19d11 100644 (file)
@@ -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.
 
index 421152967cd61db724c6a36df937271f5b592807..1ae9fe21d9f63599ed604b0b6a4fe80daa87ef1e 100644 (file)
@@ -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
index 09f60c68c0fb9dd17642ac9e5bcb01c4dc401d1f..975eff3f50405858be5b569b2966dcf9066e1af0 100644 (file)
@@ -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[:]
 }
 
index 41fc0bf5dcb3312d67f937dd108dabc133ec3ff5..9a2c1353bb15aa45f1ee950410289defc38ea4b9 100644 (file)
@@ -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()
+}
index ff9e2a9155af22cfccfdbbebb0bdd56df91d551c..c48b85f5763b278fc36af51fef18288ca4c3e9ed 100644 (file)
@@ -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