Commit d98de0c3 authored by Josh Bleecher Snyder's avatar Josh Bleecher Snyder Committed by Brad Fitzpatrick

cmd/compile: use two tables for table-driven map inserts

This enables better packing when key and value
types have different alignments.

Cuts 57k off cmd/go.

Change-Id: Ifdd125264caccd7852d622382c94e4689e757978
Reviewed-on: https://go-review.googlesource.com/26669
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarDavid Crawshaw <crawshaw@golang.org>
parent c8941bb8
...@@ -473,7 +473,6 @@ func staticassign(l *Node, r *Node, out *[]*Node) bool { ...@@ -473,7 +473,6 @@ func staticassign(l *Node, r *Node, out *[]*Node) bool {
return true return true
case OMAPLIT: case OMAPLIT:
// TODO: Table-driven map insert.
break break
case OCLOSURE: case OCLOSURE:
...@@ -859,7 +858,7 @@ func slicelit(ctxt int, n *Node, var_ *Node, init *Nodes) { ...@@ -859,7 +858,7 @@ func slicelit(ctxt int, n *Node, var_ *Node, init *Nodes) {
init.Append(a) init.Append(a)
} }
func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) { func maplit(ctxt int, n *Node, m *Node, init *Nodes) {
ctxt = 0 ctxt = 0
// make the map var // make the map var
...@@ -867,7 +866,7 @@ func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) { ...@@ -867,7 +866,7 @@ func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) {
a := Nod(OMAKE, nil, nil) a := Nod(OMAKE, nil, nil)
a.List.Set2(typenod(n.Type), Nodintconst(int64(len(n.List.Slice())))) a.List.Set2(typenod(n.Type), Nodintconst(int64(len(n.List.Slice()))))
litas(var_, a, init) litas(m, a, init)
// count the initializers // count the initializers
b := 0 b := 0
...@@ -884,32 +883,17 @@ func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) { ...@@ -884,32 +883,17 @@ func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) {
} }
if b != 0 { if b != 0 {
// build type [count]struct { a Tindex, b Tvalue } // build types [count]Tindex and [count]Tvalue
t := n.Type tk := typArray(n.Type.Key(), int64(b))
tk := t.Key() tv := typArray(n.Type.Val(), int64(b))
tv := t.Val()
syma := Lookup("a")
symb := Lookup("b")
var fields [2]*Field
fields[0] = newField()
fields[0].Type = tk
fields[0].Sym = syma
fields[1] = newField()
fields[1].Type = tv
fields[1].Sym = symb
tstruct := typ(TSTRUCT)
tstruct.SetFields(fields[:])
tarr := typArray(tstruct, int64(b))
// TODO(josharian): suppress alg generation for these types? // TODO(josharian): suppress alg generation for these types?
dowidth(tarr) dowidth(tk)
dowidth(tv)
// make and initialize static array // make and initialize static arrays
vstat := staticname(tarr, ctxt) vstatk := staticname(tk, ctxt)
vstatv := staticname(tv, ctxt)
b := int64(0) b := int64(0)
for _, r := range n.List.Slice() { for _, r := range n.List.Slice() {
...@@ -920,61 +904,52 @@ func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) { ...@@ -920,61 +904,52 @@ func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) {
value := r.Right value := r.Right
if isliteral(index) && isliteral(value) { if isliteral(index) && isliteral(value) {
// build vstat[b].a = key; // build vstatk[b] = index
setlineno(index) setlineno(index)
a = Nodintconst(b) lhs := Nod(OINDEX, vstatk, Nodintconst(b))
as := Nod(OAS, lhs, index)
a = Nod(OINDEX, vstat, a) as = typecheck(as, Etop)
a = NodSym(ODOT, a, syma) as = walkexpr(as, init)
a = Nod(OAS, a, index) as.Dodata = 2
a = typecheck(a, Etop) init.Append(as)
a = walkexpr(a, init)
a.Dodata = 2 // build vstatv[b] = value
init.Append(a)
// build vstat[b].b = value;
setlineno(value) setlineno(value)
a = Nodintconst(b) lhs = Nod(OINDEX, vstatv, Nodintconst(b))
as = Nod(OAS, lhs, value)
a = Nod(OINDEX, vstat, a) as = typecheck(as, Etop)
a = NodSym(ODOT, a, symb) as = walkexpr(as, init)
a = Nod(OAS, a, value) as.Dodata = 2
a = typecheck(a, Etop) init.Append(as)
a = walkexpr(a, init)
a.Dodata = 2
init.Append(a)
b++ b++
} }
} }
// loop adding structure elements to map // loop adding structure elements to map
// for i = 0; i < len(vstat); i++ { // for i = 0; i < len(vstatk); i++ {
// map[vstat[i].a] = vstat[i].b // map[vstatk[i]] = vstatv[i]
// } // }
index := temp(Types[TINT]) i := temp(Types[TINT])
rhs := Nod(OINDEX, vstatv, i)
a = Nod(OINDEX, vstat, index) rhs.Bounded = true
a.Bounded = true
a = NodSym(ODOT, a, symb)
r := Nod(OINDEX, vstat, index) kidx := Nod(OINDEX, vstatk, i)
r.Bounded = true kidx.Bounded = true
r = NodSym(ODOT, r, syma) lhs := Nod(OINDEX, m, kidx)
r = Nod(OINDEX, var_, r)
r = Nod(OAS, r, a) zero := Nod(OAS, i, Nodintconst(0))
cond := Nod(OLT, i, Nodintconst(tk.NumElem()))
incr := Nod(OAS, i, Nod(OADD, i, Nodintconst(1)))
body := Nod(OAS, lhs, rhs)
a = Nod(OFOR, nil, nil) loop := Nod(OFOR, cond, incr)
a.Nbody.Set1(r) loop.Nbody.Set1(body)
loop.Ninit.Set1(zero)
a.Ninit.Set1(Nod(OAS, index, Nodintconst(0))) loop = typecheck(loop, Etop)
a.Left = Nod(OLT, index, Nodintconst(tarr.NumElem())) loop = walkstmt(loop)
a.Right = Nod(OAS, index, Nod(OADD, index, Nodintconst(1))) init.Append(loop)
a = typecheck(a, Etop)
a = walkstmt(a)
init.Append(a)
} }
// put in dynamic entries one-at-a-time // put in dynamic entries one-at-a-time
...@@ -993,8 +968,8 @@ func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) { ...@@ -993,8 +968,8 @@ func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) {
// build list of var[c] = expr. // build list of var[c] = expr.
// use temporary so that mapassign1 can have addressable key, val. // use temporary so that mapassign1 can have addressable key, val.
if key == nil { if key == nil {
key = temp(var_.Type.Key()) key = temp(m.Type.Key())
val = temp(var_.Type.Val()) val = temp(m.Type.Val())
} }
setlineno(r.Left) setlineno(r.Left)
...@@ -1009,7 +984,7 @@ func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) { ...@@ -1009,7 +984,7 @@ func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) {
init.Append(a) init.Append(a)
setlineno(val) setlineno(val)
a = Nod(OAS, Nod(OINDEX, var_, key), val) a = Nod(OAS, Nod(OINDEX, m, key), val)
a = typecheck(a, Etop) a = typecheck(a, Etop)
a = walkstmt(a) a = walkstmt(a)
init.Append(a) init.Append(a)
......
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