Skip to content

Commit 160b97c

Browse files
committed
cmd/compile: pass an hmap to makemap when initializing static maps
DO NOT SUBMIT [I am not sure the best way to identify whether a particular OMAPLIT is safe for a static hmap; see the TODO in the CL] Prior to this CL, we did code generation for a map literal like this: m := make(maptype, number of elements) m[k] = v // for all elements, sometimes using a loop The assignment to m generates a write barrier. Each write barrier generates a new SSA block. In giant composite literals, this can lead to lots of blocks. This led to a panic when compiling the code in golang#19751. This CL changes code generation when compiling a static composite literal to do: var stat hmap // static symbol hp := &stat m := (map)(hp) initmap(hp, number of elements) m[k] = v This involves no assignments, and thus no write barriers. As a result, the code in golang#19751 compiles. Slowly still, but the compilation completes. Change-Id: Ic0c05f5892e50fadc5e6d6adb5a3f5275ec38224
1 parent 5e157db commit 160b97c

File tree

3 files changed

+41
-5
lines changed

3 files changed

+41
-5
lines changed

src/cmd/compile/internal/gc/sinit.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -929,12 +929,9 @@ func slicelit(ctxt initContext, n *Node, var_ *Node, init *Nodes) {
929929
init.Append(a)
930930
}
931931

932+
// maplit populates the map m with the values in n.
933+
// m must already have been created.
932934
func maplit(n *Node, m *Node, init *Nodes) {
933-
// make the map var
934-
a := nod(OMAKE, nil, nil)
935-
a.List.Set2(typenod(n.Type), nodintconst(int64(n.List.Len())))
936-
litas(m, a, init)
937-
938935
// Split the initializers into static and dynamic.
939936
var stat, dyn []*Node
940937
for _, r := range n.List.Slice() {
@@ -1150,6 +1147,11 @@ func anylit(n *Node, var_ *Node, init *Nodes) {
11501147
if !t.IsMap() {
11511148
Fatalf("anylit: not map")
11521149
}
1150+
// make the map var
1151+
a := nod(OMAKE, nil, nil)
1152+
a.List.Set2(typenod(n.Type), nodintconst(int64(n.List.Len())))
1153+
litas(var_, a, init)
1154+
// populate it
11531155
maplit(n, var_, init)
11541156
}
11551157
}

src/cmd/compile/internal/gc/ssa.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1509,6 +1509,11 @@ func (s *state) expr(n *Node) *ssa.Value {
15091509
return v
15101510
}
15111511

1512+
// Conversion of *hmap to map.
1513+
if to.Etype == TMAP && from.IsPtr() && from.Elem().StructType().Map != nil {
1514+
return v
1515+
}
1516+
15121517
// named <--> unnamed type or typed <--> untyped const
15131518
if from.Etype == to.Etype {
15141519
return v

src/cmd/compile/internal/gc/walk.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1634,6 +1634,35 @@ opswitch:
16341634
n = typecheck(n, Erv)
16351635
break
16361636
}
1637+
// TODO: checking Curfn.funcname() == "init" is not the right way,
1638+
// if for no other reason than we're trying to eliminate Curfn.
1639+
// But what to replace it with?
1640+
if n.Op == OMAPLIT && Curfn.funcname() == "init" {
1641+
// Construct a static hmap.
1642+
t := n.Type
1643+
ht := hmap(t)
1644+
h := staticname(ht)
1645+
// Take its address, to pass as *hmap to makemap.
1646+
mp := nod(OCONVNOP, nod(OADDR, h, nil), nil)
1647+
mp.Type = types.NewPtr(ht)
1648+
// Pass a nil bucket pointer to makemap.
1649+
b := nodnil()
1650+
// Call makemap.
1651+
fn := syslook("makemap") // TODO(josharian): refactor out constructing a makemap call?
1652+
fn = substArgTypes(fn, hmap(t), mapbucket(t), t.Key(), t.Val())
1653+
call := mkcall1(fn, n.Type, init, typename(n.Type), nodintconst(int64(n.List.Len())), mp, b)
1654+
call = typecheck(call, Etop)
1655+
call = walkexpr(call, init)
1656+
init.Append(call)
1657+
1658+
// Convert the *hmap to a map for use in maplit.
1659+
m := nod(OCONVNOP, mp, nil)
1660+
m.Type = t
1661+
// Populate the map and return it.
1662+
maplit(n, m, init)
1663+
n = m
1664+
break
1665+
}
16371666
var_ := temp(n.Type)
16381667
anylit(n, var_, init)
16391668
n = var_

0 commit comments

Comments
 (0)