Skip to content

Commit 095a62c

Browse files
committed
cmd/compile: refactor maplit
Instead of walking the list of nodes twice, once to find static entries to add to an array and once to find dynamic entries to generate code for, do the split once up front, into two slices. Then process each slice individually. This makes the code easier to read and more importantly, easier to modify. While we're here, add a TODO to avoid using temporaries for mapassign_fast calls. It's not an important TODO; the generated code would be basically identical. It would just avoid a minor amount of pointless SSA optimization work. Passes toolstash-check. No measureable compiler performance impact. Updates #19751 Change-Id: I84a8f2c22f9025c718ef34639059d7bd02a3c406 Reviewed-on: https://go-review.googlesource.com/39351 Run-TryBot: Josh Bleecher Snyder <[email protected]> Reviewed-by: Brad Fitzpatrick <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
1 parent 1d6a499 commit 095a62c

File tree

1 file changed

+48
-60
lines changed

1 file changed

+48
-60
lines changed

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

+48-60
Original file line numberDiff line numberDiff line change
@@ -924,30 +924,28 @@ func slicelit(ctxt initContext, n *Node, var_ *Node, init *Nodes) {
924924

925925
func maplit(n *Node, m *Node, init *Nodes) {
926926
// make the map var
927-
nerr := nerrors
928-
929927
a := nod(OMAKE, nil, nil)
930928
a.List.Set2(typenod(n.Type), nodintconst(int64(n.List.Len())))
931929
litas(m, a, init)
932930

933-
// count the initializers
934-
b := 0
931+
// Split the initializers into static and dynamic.
932+
var stat, dyn []*Node
935933
for _, r := range n.List.Slice() {
936934
if r.Op != OKEY {
937935
Fatalf("maplit: rhs not OKEY: %v", r)
938936
}
939-
index := r.Left
940-
value := r.Right
941-
942-
if isliteral(index) && isliteral(value) {
943-
b++
937+
if isliteral(r.Left) && isliteral(r.Right) {
938+
stat = append(stat, r)
939+
} else {
940+
dyn = append(dyn, r)
944941
}
945942
}
946943

947-
if b != 0 {
944+
// Add static entries.
945+
if len(stat) > 0 {
948946
// build types [count]Tindex and [count]Tvalue
949-
tk := typArray(n.Type.Key(), int64(b))
950-
tv := typArray(n.Type.Val(), int64(b))
947+
tk := typArray(n.Type.Key(), int64(len(stat)))
948+
tv := typArray(n.Type.Val(), int64(len(stat)))
951949

952950
// TODO(josharian): suppress alg generation for these types?
953951
dowidth(tk)
@@ -959,31 +957,23 @@ func maplit(n *Node, m *Node, init *Nodes) {
959957
vstatv := staticname(tv)
960958
vstatv.Name.SetReadonly(true)
961959

962-
b := int64(0)
963-
for _, r := range n.List.Slice() {
964-
if r.Op != OKEY {
965-
Fatalf("maplit: rhs not OKEY: %v", r)
966-
}
960+
for i, r := range stat {
967961
index := r.Left
968962
value := r.Right
969963

970-
if isliteral(index) && isliteral(value) {
971-
// build vstatk[b] = index
972-
setlineno(index)
973-
lhs := nod(OINDEX, vstatk, nodintconst(b))
974-
as := nod(OAS, lhs, index)
975-
as = typecheck(as, Etop)
976-
genAsStatic(as)
977-
978-
// build vstatv[b] = value
979-
setlineno(value)
980-
lhs = nod(OINDEX, vstatv, nodintconst(b))
981-
as = nod(OAS, lhs, value)
982-
as = typecheck(as, Etop)
983-
genAsStatic(as)
984-
985-
b++
986-
}
964+
// build vstatk[b] = index
965+
setlineno(index)
966+
lhs := nod(OINDEX, vstatk, nodintconst(int64(i)))
967+
as := nod(OAS, lhs, index)
968+
as = typecheck(as, Etop)
969+
genAsStatic(as)
970+
971+
// build vstatv[b] = value
972+
setlineno(value)
973+
lhs = nod(OINDEX, vstatv, nodintconst(int64(i)))
974+
as = nod(OAS, lhs, value)
975+
as = typecheck(as, Etop)
976+
genAsStatic(as)
987977
}
988978

989979
// loop adding structure elements to map
@@ -1012,28 +1002,28 @@ func maplit(n *Node, m *Node, init *Nodes) {
10121002
init.Append(loop)
10131003
}
10141004

1015-
// put in dynamic entries one-at-a-time
1016-
var key, val *Node
1017-
for _, r := range n.List.Slice() {
1018-
if r.Op != OKEY {
1019-
Fatalf("maplit: rhs not OKEY: %v", r)
1020-
}
1021-
index := r.Left
1022-
value := r.Right
1005+
// Add dynamic entries.
1006+
addMapEntries(m, dyn, init)
1007+
}
10231008

1024-
if isliteral(index) && isliteral(value) {
1025-
continue
1026-
}
1009+
func addMapEntries(m *Node, dyn []*Node, init *Nodes) {
1010+
if len(dyn) == 0 {
1011+
return
1012+
}
10271013

1028-
// build list of var[c] = expr.
1029-
// use temporary so that mapassign1 can have addressable key, val.
1030-
if key == nil {
1031-
key = temp(m.Type.Key())
1032-
val = temp(m.Type.Val())
1033-
}
1014+
nerr := nerrors
1015+
1016+
// Build list of var[c] = expr.
1017+
// Use temporaries so that mapassign1 can have addressable key, val.
1018+
// TODO(josharian): avoid map key temporaries for mapfast_* assignments with literal keys.
1019+
key := temp(m.Type.Key())
1020+
val := temp(m.Type.Val())
1021+
1022+
for _, r := range dyn {
1023+
index, value := r.Left, r.Right
10341024

10351025
setlineno(index)
1036-
a = nod(OAS, key, index)
1026+
a := nod(OAS, key, index)
10371027
a = typecheck(a, Etop)
10381028
a = walkstmt(a)
10391029
init.Append(a)
@@ -1055,14 +1045,12 @@ func maplit(n *Node, m *Node, init *Nodes) {
10551045
}
10561046
}
10571047

1058-
if key != nil {
1059-
a = nod(OVARKILL, key, nil)
1060-
a = typecheck(a, Etop)
1061-
init.Append(a)
1062-
a = nod(OVARKILL, val, nil)
1063-
a = typecheck(a, Etop)
1064-
init.Append(a)
1065-
}
1048+
a := nod(OVARKILL, key, nil)
1049+
a = typecheck(a, Etop)
1050+
init.Append(a)
1051+
a = nod(OVARKILL, val, nil)
1052+
a = typecheck(a, Etop)
1053+
init.Append(a)
10661054
}
10671055

10681056
func anylit(n *Node, var_ *Node, init *Nodes) {

0 commit comments

Comments
 (0)