mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
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: David Crawshaw <crawshaw@golang.org>
This commit is contained in:
parent
c8941bb85c
commit
d98de0c3d0
1 changed files with 45 additions and 70 deletions
|
|
@ -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) {
|
||||||
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) {
|
||||||
|
|
||||||
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) {
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
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)
|
||||||
|
as = typecheck(as, Etop)
|
||||||
|
as = walkexpr(as, init)
|
||||||
|
as.Dodata = 2
|
||||||
|
init.Append(as)
|
||||||
|
|
||||||
a = Nod(OINDEX, vstat, a)
|
// build vstatv[b] = value
|
||||||
a = NodSym(ODOT, a, syma)
|
|
||||||
a = Nod(OAS, a, index)
|
|
||||||
a = typecheck(a, Etop)
|
|
||||||
a = walkexpr(a, init)
|
|
||||||
a.Dodata = 2
|
|
||||||
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)
|
||||||
|
rhs.Bounded = true
|
||||||
|
|
||||||
a = Nod(OINDEX, vstat, index)
|
kidx := Nod(OINDEX, vstatk, i)
|
||||||
a.Bounded = true
|
kidx.Bounded = true
|
||||||
a = NodSym(ODOT, a, symb)
|
lhs := Nod(OINDEX, m, kidx)
|
||||||
|
|
||||||
r := Nod(OINDEX, vstat, index)
|
zero := Nod(OAS, i, Nodintconst(0))
|
||||||
r.Bounded = true
|
cond := Nod(OLT, i, Nodintconst(tk.NumElem()))
|
||||||
r = NodSym(ODOT, r, syma)
|
incr := Nod(OAS, i, Nod(OADD, i, Nodintconst(1)))
|
||||||
r = Nod(OINDEX, var_, r)
|
body := Nod(OAS, lhs, rhs)
|
||||||
|
|
||||||
r = Nod(OAS, r, a)
|
loop := Nod(OFOR, cond, incr)
|
||||||
|
loop.Nbody.Set1(body)
|
||||||
|
loop.Ninit.Set1(zero)
|
||||||
|
|
||||||
a = Nod(OFOR, nil, nil)
|
loop = typecheck(loop, Etop)
|
||||||
a.Nbody.Set1(r)
|
loop = walkstmt(loop)
|
||||||
|
init.Append(loop)
|
||||||
a.Ninit.Set1(Nod(OAS, index, Nodintconst(0)))
|
|
||||||
a.Left = Nod(OLT, index, Nodintconst(tarr.NumElem()))
|
|
||||||
a.Right = Nod(OAS, index, Nod(OADD, index, Nodintconst(1)))
|
|
||||||
|
|
||||||
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) {
|
||||||
// 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) {
|
||||||
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)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue