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>
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 {
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
{"chansend1", funcTag, 103},
{"closechan", funcTag, 104},
{"chanlen", funcTag, 105},
+ {"chancap", funcTag, 105},
{"writeBarrier", varTag, 107},
{"typedmemmove", funcTag, 108},
{"typedmemclr", funcTag, 109},
_, 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)
}
(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()
}
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)
//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