mirror of
https://github.com/golang/go
synced 2024-11-19 13:54:56 -07:00
cmd/compile: insert ' ' and \n at beginning of walkprint
Rather than emitting spaces and newlines for println as we walk the expression, construct it all up front. This enables further optimizations. This requires using printstring instead of print in the implementation of printsp and printnl, on pain of infinite recursion. That's ok; it's more efficient anyway, and just as simple. While we're here, do it for other print routines as well. Change-Id: I61d7df143810e00710c4d4d948d904007a7fd190 Reviewed-on: https://go-review.googlesource.com/55097 Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
385ca9ae9a
commit
9de7990054
@ -448,6 +448,10 @@ func nodbool(b bool) *Node {
|
||||
return c
|
||||
}
|
||||
|
||||
func nodstr(s string) *Node {
|
||||
return nodlit(Val{s})
|
||||
}
|
||||
|
||||
// treecopy recursively copies n, with the exception of
|
||||
// ONAME, OLITERAL, OTYPE, and non-iota ONONAME leaves.
|
||||
// Copies of iota ONONAME nodes are assigned the current
|
||||
|
@ -2022,15 +2022,22 @@ func walkprint(nn *Node, init *Nodes) *Node {
|
||||
// Hoist all the argument evaluation up before the lock.
|
||||
walkexprlistcheap(nn.List.Slice(), init)
|
||||
|
||||
notfirst := false
|
||||
// For println, add " " between elements and "\n" at the end.
|
||||
if nn.Op == OPRINTN {
|
||||
s := nn.List.Slice()
|
||||
t := make([]*Node, 0, len(s)*2)
|
||||
for i, n := range s {
|
||||
x := " "
|
||||
if len(s)-1 == i {
|
||||
x = "\n"
|
||||
}
|
||||
t = append(t, n, nodstr(x))
|
||||
}
|
||||
nn.List.Set(t)
|
||||
}
|
||||
|
||||
calls := []*Node{mkcall("printlock", nil, init)}
|
||||
for i, n := range nn.List.Slice() {
|
||||
if notfirst {
|
||||
calls = append(calls, mkcall("printsp", nil, init))
|
||||
}
|
||||
|
||||
notfirst = nn.Op == OPRINTN
|
||||
|
||||
if n.Op == OLITERAL {
|
||||
switch n.Val().Ctype() {
|
||||
case CTRUNE:
|
||||
@ -2083,28 +2090,35 @@ func walkprint(nn *Node, init *Nodes) *Node {
|
||||
case TBOOL:
|
||||
on = syslook("printbool")
|
||||
case TSTRING:
|
||||
on = syslook("printstring")
|
||||
cs := ""
|
||||
if Isconst(n, CTSTR) {
|
||||
cs = n.Val().U.(string)
|
||||
}
|
||||
switch cs {
|
||||
case " ":
|
||||
on = syslook("printsp")
|
||||
case "\n":
|
||||
on = syslook("printnl")
|
||||
default:
|
||||
on = syslook("printstring")
|
||||
}
|
||||
default:
|
||||
badtype(OPRINT, n.Type, nil)
|
||||
continue
|
||||
}
|
||||
|
||||
t := on.Type.Params().Field(0).Type
|
||||
|
||||
if !eqtype(t, n.Type) {
|
||||
n = nod(OCONV, n, nil)
|
||||
n.Type = t
|
||||
}
|
||||
|
||||
r := nod(OCALL, on, nil)
|
||||
r.List.Append(n)
|
||||
if params := on.Type.Params().FieldSlice(); len(params) > 0 {
|
||||
t := params[0].Type
|
||||
if !eqtype(t, n.Type) {
|
||||
n = nod(OCONV, n, nil)
|
||||
n.Type = t
|
||||
}
|
||||
r.List.Append(n)
|
||||
}
|
||||
calls = append(calls, r)
|
||||
}
|
||||
|
||||
if nn.Op == OPRINTN {
|
||||
calls = append(calls, mkcall("printnl", nil, nil))
|
||||
}
|
||||
|
||||
calls = append(calls, mkcall("printunlock", nil, init))
|
||||
|
||||
typecheckslice(calls, Etop)
|
||||
|
@ -56,7 +56,7 @@ var debuglock mutex
|
||||
|
||||
// The compiler emits calls to printlock and printunlock around
|
||||
// the multiple calls that implement a single Go print or println
|
||||
// statement. Some of the print helpers (printsp, for example)
|
||||
// statement. Some of the print helpers (printslice, for example)
|
||||
// call print recursively. There is also the problem of a crash
|
||||
// happening during the print routines and needing to acquire
|
||||
// the print lock to print information about the crash.
|
||||
@ -98,31 +98,31 @@ func gwrite(b []byte) {
|
||||
}
|
||||
|
||||
func printsp() {
|
||||
print(" ")
|
||||
printstring(" ")
|
||||
}
|
||||
|
||||
func printnl() {
|
||||
print("\n")
|
||||
printstring("\n")
|
||||
}
|
||||
|
||||
func printbool(v bool) {
|
||||
if v {
|
||||
print("true")
|
||||
printstring("true")
|
||||
} else {
|
||||
print("false")
|
||||
printstring("false")
|
||||
}
|
||||
}
|
||||
|
||||
func printfloat(v float64) {
|
||||
switch {
|
||||
case v != v:
|
||||
print("NaN")
|
||||
printstring("NaN")
|
||||
return
|
||||
case v+v == v && v > 0:
|
||||
print("+Inf")
|
||||
printstring("+Inf")
|
||||
return
|
||||
case v+v == v && v < 0:
|
||||
print("-Inf")
|
||||
printstring("-Inf")
|
||||
return
|
||||
}
|
||||
|
||||
@ -204,7 +204,7 @@ func printuint(v uint64) {
|
||||
|
||||
func printint(v int64) {
|
||||
if v < 0 {
|
||||
print("-")
|
||||
printstring("-")
|
||||
v = -v
|
||||
}
|
||||
printuint(uint64(v))
|
||||
|
Loading…
Reference in New Issue
Block a user