Commit 9de79900 authored by Josh Bleecher Snyder's avatar Josh Bleecher Snyder

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: default avatarMatthew Dempsky <mdempsky@google.com>
parent 385ca9ae
...@@ -448,6 +448,10 @@ func nodbool(b bool) *Node { ...@@ -448,6 +448,10 @@ func nodbool(b bool) *Node {
return c return c
} }
func nodstr(s string) *Node {
return nodlit(Val{s})
}
// treecopy recursively copies n, with the exception of // treecopy recursively copies n, with the exception of
// ONAME, OLITERAL, OTYPE, and non-iota ONONAME leaves. // ONAME, OLITERAL, OTYPE, and non-iota ONONAME leaves.
// Copies of iota ONONAME nodes are assigned the current // Copies of iota ONONAME nodes are assigned the current
......
...@@ -2022,15 +2022,22 @@ func walkprint(nn *Node, init *Nodes) *Node { ...@@ -2022,15 +2022,22 @@ func walkprint(nn *Node, init *Nodes) *Node {
// Hoist all the argument evaluation up before the lock. // Hoist all the argument evaluation up before the lock.
walkexprlistcheap(nn.List.Slice(), init) walkexprlistcheap(nn.List.Slice(), init)
notfirst := false // For println, add " " between elements and "\n" at the end.
calls := []*Node{mkcall("printlock", nil, init)} if nn.Op == OPRINTN {
for i, n := range nn.List.Slice() { s := nn.List.Slice()
if notfirst { t := make([]*Node, 0, len(s)*2)
calls = append(calls, mkcall("printsp", nil, init)) for i, n := range s {
x := " "
if len(s)-1 == i {
x = "\n"
}
t = append(t, n, nodstr(x))
} }
nn.List.Set(t)
}
notfirst = nn.Op == OPRINTN calls := []*Node{mkcall("printlock", nil, init)}
for i, n := range nn.List.Slice() {
if n.Op == OLITERAL { if n.Op == OLITERAL {
switch n.Val().Ctype() { switch n.Val().Ctype() {
case CTRUNE: case CTRUNE:
...@@ -2083,28 +2090,35 @@ func walkprint(nn *Node, init *Nodes) *Node { ...@@ -2083,28 +2090,35 @@ func walkprint(nn *Node, init *Nodes) *Node {
case TBOOL: case TBOOL:
on = syslook("printbool") on = syslook("printbool")
case TSTRING: 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: default:
badtype(OPRINT, n.Type, nil) badtype(OPRINT, n.Type, nil)
continue 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 := 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) calls = append(calls, r)
} }
if nn.Op == OPRINTN {
calls = append(calls, mkcall("printnl", nil, nil))
}
calls = append(calls, mkcall("printunlock", nil, init)) calls = append(calls, mkcall("printunlock", nil, init))
typecheckslice(calls, Etop) typecheckslice(calls, Etop)
......
...@@ -56,7 +56,7 @@ var debuglock mutex ...@@ -56,7 +56,7 @@ var debuglock mutex
// The compiler emits calls to printlock and printunlock around // The compiler emits calls to printlock and printunlock around
// the multiple calls that implement a single Go print or println // 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 // call print recursively. There is also the problem of a crash
// happening during the print routines and needing to acquire // happening during the print routines and needing to acquire
// the print lock to print information about the crash. // the print lock to print information about the crash.
...@@ -98,31 +98,31 @@ func gwrite(b []byte) { ...@@ -98,31 +98,31 @@ func gwrite(b []byte) {
} }
func printsp() { func printsp() {
print(" ") printstring(" ")
} }
func printnl() { func printnl() {
print("\n") printstring("\n")
} }
func printbool(v bool) { func printbool(v bool) {
if v { if v {
print("true") printstring("true")
} else { } else {
print("false") printstring("false")
} }
} }
func printfloat(v float64) { func printfloat(v float64) {
switch { switch {
case v != v: case v != v:
print("NaN") printstring("NaN")
return return
case v+v == v && v > 0: case v+v == v && v > 0:
print("+Inf") printstring("+Inf")
return return
case v+v == v && v < 0: case v+v == v && v < 0:
print("-Inf") printstring("-Inf")
return return
} }
...@@ -204,7 +204,7 @@ func printuint(v uint64) { ...@@ -204,7 +204,7 @@ func printuint(v uint64) {
func printint(v int64) { func printint(v int64) {
if v < 0 { if v < 0 {
print("-") printstring("-")
v = -v v = -v
} }
printuint(uint64(v)) printuint(uint64(v))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment