]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: compile cap(ch) as call to runtime.chancap
authorRuss Cox <rsc@golang.org>
Thu, 29 Feb 2024 19:28:09 +0000 (14:28 -0500)
committerGopher Robot <gobot@golang.org>
Fri, 8 Mar 2024 22:35:22 +0000 (22:35 +0000)
An upcoming CL will give this call more to do.
For now, separate out the compiler change that
stops inlining the computation.

For #37196.

Change-Id: I965426d446964b9b4958e4613246002a7660e7eb
Reviewed-on: https://go-review.googlesource.com/c/go/+/568375
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Auto-Submit: Russ Cox <rsc@golang.org>

src/cmd/compile/internal/ssagen/ssa.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 6335aff8321f1990780de8bd39ab162f404a1078..2e3ad3232bf3e868776b7c3c7da3ceca5e9e9589 100644 (file)
@@ -6350,6 +6350,9 @@ func (s *state) referenceTypeBuiltin(n *ir.UnaryExpr, x *ssa.Value) *ssa.Value {
        if n.X.Type().IsChan() && n.Op() == ir.OLEN {
                s.Fatalf("cannot inline len(chan)") // must use runtime.chanlen now
        }
+       if n.X.Type().IsChan() && n.Op() == ir.OCAP {
+               s.Fatalf("cannot inline cap(chan)") // must use runtime.chancap now
+       }
        // if n == nil {
        //   return 0
        // } else {
index 1ae9fe21d9f63599ed604b0b6a4fe80daa87ef1e..3fee023afb8fe4a87b571dfad99da9f097dd5d8b 100644 (file)
@@ -161,6 +161,7 @@ func chanrecv2(hchan <-chan any, elem *any) bool
 func chansend1(hchan chan<- any, elem *any)
 func closechan(hchan chan<- any)
 func chanlen(hchan any) int
+func chancap(hchan any) int
 
 var writeBarrier struct {
        enabled bool
index 975eff3f50405858be5b569b2966dcf9066e1af0..e3ef360a032af2e30f68989232348910dac7c957 100644 (file)
@@ -138,6 +138,7 @@ var runtimeDecls = [...]struct {
        {"chansend1", funcTag, 103},
        {"closechan", funcTag, 104},
        {"chanlen", funcTag, 105},
+       {"chancap", funcTag, 105},
        {"writeBarrier", varTag, 107},
        {"typedmemmove", funcTag, 108},
        {"typedmemclr", funcTag, 109},
index 9a2c1353bb15aa45f1ee950410289defc38ea4b9..512420e6d5800b6049671fdc1f3d25077af75bd5 100644 (file)
@@ -261,10 +261,14 @@ func walkLenCap(n *ir.UnaryExpr, init *ir.Nodes) ir.Node {
                _, len := backingArrayPtrLen(cheapExpr(conv.X, init))
                return len
        }
-       if isChanLen(n) {
+       if isChanLenCap(n) {
+               name := "chanlen"
+               if n.Op() == ir.OCAP {
+                       name = "chancap"
+               }
                // 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())
+               fn := typecheck.LookupRuntime(name, n.X.Type())
                return mkcall1(fn, n.Type(), init, n.X)
        }
 
@@ -892,9 +896,9 @@ func isByteCount(n ir.Node) bool {
                (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.
+// isChanLenCap reports whether n is of the form len(c) or cap(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()
+func isChanLenCap(n ir.Node) bool {
+       return (n.Op() == ir.OLEN || n.Op() == ir.OCAP) && n.(*ir.UnaryExpr).X.Type().IsChan()
 }
index c793d6cef3cfd180a2df0368d116c89a6e517996..b14ebc31d25e7f9d7be9e57f72aff3be51a33896 100644 (file)
@@ -731,6 +731,13 @@ func chanlen(c *hchan) int {
        return int(c.qcount)
 }
 
+func chancap(c *hchan) int {
+       if c == nil {
+               return 0
+       }
+       return int(c.dataqsiz)
+}
+
 //go:linkname reflect_chanlen reflect.chanlen
 func reflect_chanlen(c *hchan) int {
        return chanlen(c)
@@ -743,10 +750,7 @@ func reflectlite_chanlen(c *hchan) int {
 
 //go:linkname reflect_chancap reflect.chancap
 func reflect_chancap(c *hchan) int {
-       if c == nil {
-               return 0
-       }
-       return int(c.dataqsiz)
+       return chancap(c)
 }
 
 //go:linkname reflect_chanclose reflect.chanclose