diff --git a/src/cmd/compile/internal/gc/const.go b/src/cmd/compile/internal/gc/const.go index c0ed8192d9..d881be485e 100644 --- a/src/cmd/compile/internal/gc/const.go +++ b/src/cmd/compile/internal/gc/const.go @@ -1134,7 +1134,6 @@ func strlit(n *Node) string { return n.Val().U.(string) } -// TODO(gri) smallintconst is only used in one place - can we used indexconst? func smallintconst(n *Node) bool { if n.Op == OLITERAL && Isconst(n, CTINT) && n.Type != nil { switch simtype[n.Type.Etype] { diff --git a/src/cmd/compile/internal/gc/esc.go b/src/cmd/compile/internal/gc/esc.go index 375331d1f5..d7aa72b450 100644 --- a/src/cmd/compile/internal/gc/esc.go +++ b/src/cmd/compile/internal/gc/esc.go @@ -169,36 +169,47 @@ func mayAffectMemory(n *Node) bool { } } -func mustHeapAlloc(n *Node) bool { +// heapAllocReason returns the reason the given Node must be heap +// allocated, or the empty string if it doesn't. +func heapAllocReason(n *Node) string { if n.Type == nil { - return false + return "" } // Parameters are always passed via the stack. if n.Op == ONAME && (n.Class() == PPARAM || n.Class() == PPARAMOUT) { - return false + return "" } if n.Type.Width > maxStackVarSize { - return true + return "too large for stack" } if (n.Op == ONEW || n.Op == OPTRLIT) && n.Type.Elem().Width >= maxImplicitStackVarSize { - return true + return "too large for stack" } if n.Op == OCLOSURE && closureType(n).Size() >= maxImplicitStackVarSize { - return true + return "too large for stack" } if n.Op == OCALLPART && partialCallType(n).Size() >= maxImplicitStackVarSize { - return true + return "too large for stack" } - if n.Op == OMAKESLICE && !isSmallMakeSlice(n) { - return true + if n.Op == OMAKESLICE { + r := n.Right + if r == nil { + r = n.Left + } + if !smallintconst(r) { + return "non-constant size" + } + if t := n.Type; t.Elem().Width != 0 && r.Int64() >= maxImplicitStackVarSize/t.Elem().Width { + return "too large for stack" + } } - return false + return "" } // addrescapes tags node n as having had its address taken diff --git a/src/cmd/compile/internal/gc/escape.go b/src/cmd/compile/internal/gc/escape.go index d79d32ec48..79df584ab1 100644 --- a/src/cmd/compile/internal/gc/escape.go +++ b/src/cmd/compile/internal/gc/escape.go @@ -1051,11 +1051,7 @@ func (e *Escape) newLoc(n *Node, transient bool) *EscLocation { } n.SetOpt(loc) - if mustHeapAlloc(n) { - why := "too large for stack" - if n.Op == OMAKESLICE && (!Isconst(n.Left, CTINT) || (n.Right != nil && !Isconst(n.Right, CTINT))) { - why = "non-constant size" - } + if why := heapAllocReason(n); why != "" { e.flow(e.heapHole().addr(n, why), loc) } } diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index 8e45059eab..3fe7c3e089 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -336,19 +336,6 @@ func walkstmt(n *Node) *Node { return n } -func isSmallMakeSlice(n *Node) bool { - if n.Op != OMAKESLICE { - return false - } - r := n.Right - if r == nil { - r = n.Left - } - t := n.Type - - return smallintconst(r) && (t.Elem().Width == 0 || r.Int64() < maxImplicitStackVarSize/t.Elem().Width) -} - // walk the whole tree of the body of an // expression or simple statement. // the types expressions are calculated. @@ -1339,8 +1326,8 @@ opswitch: yyerror("%v can't be allocated in Go; it is incomplete (or unallocatable)", t.Elem()) } if n.Esc == EscNone { - if !isSmallMakeSlice(n) { - Fatalf("non-small OMAKESLICE with EscNone: %v", n) + if why := heapAllocReason(n); why != "" { + Fatalf("%v has EscNone, but %v", n, why) } // var arr [r]T // n = arr[:l] diff --git a/test/fixedbugs/issue41635.go b/test/fixedbugs/issue41635.go index b33c1a07e7..35c0034cdd 100644 --- a/test/fixedbugs/issue41635.go +++ b/test/fixedbugs/issue41635.go @@ -7,12 +7,11 @@ package p func f() { // ERROR "" - b1 := make([]byte, 1<<17) // ERROR "too large for stack" "" - b2 := make([]byte, 100, 1<<17) // ERROR "too large for stack" "" - n, m := 100, 200 - b1 = make([]byte, n) // ERROR "non-constant size" "" - b2 = make([]byte, 100, m) // ERROR "non-constant size" "" + _ = make([]byte, 1<<17) // ERROR "too large for stack" "" + _ = make([]byte, 100, 1<<17) // ERROR "too large for stack" "" + _ = make([]byte, n, 1<<17) // ERROR "too large for stack" "" - _, _ = b1, b2 + _ = make([]byte, n) // ERROR "non-constant size" "" + _ = make([]byte, 100, m) // ERROR "non-constant size" "" }