aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cmd/compile/internal/gc/builtin.go92
-rw-r--r--src/cmd/compile/internal/gc/builtin/runtime.go2
-rw-r--r--src/cmd/compile/internal/gc/order.go32
-rw-r--r--src/cmd/compile/internal/gc/racewalk.go4
-rw-r--r--src/cmd/compile/internal/gc/syntax.go2
-rw-r--r--src/cmd/compile/internal/gc/walk.go84
-rw-r--r--src/runtime/hashmap.go38
7 files changed, 120 insertions, 134 deletions
diff --git a/src/cmd/compile/internal/gc/builtin.go b/src/cmd/compile/internal/gc/builtin.go
index e78b1ace74..a5d433140d 100644
--- a/src/cmd/compile/internal/gc/builtin.go
+++ b/src/cmd/compile/internal/gc/builtin.go
@@ -57,52 +57,52 @@ const runtimeimport = "" +
"ast64\x00\x06\x17\"\xc2\x01\x00\x00\x1d::\xc4\x01\x00\x00:\xc6\x01\x00\x00\x04\x17:\xb4\x01\x00\x00\x00\xc8\x01\x00\x00\t#m" +
"apaccess2_faststr\x00\x06\x17\"\xc2\x01\x00\x00\x1d::\xc4\x01\x00\x00:\xc6\x01\x00\x00\x04\x17:" +
"\xb4\x01\x00\x00\x00\xc8\x01\x00\x00\t\x1bmapaccess2_fat\x00\b\x17\"\xc2\x01\x00\x00\x1d::\xc4\x01\x00\x00" +
- "\x17:\xc6\x01\x00\x00\x17\"\rzero·6\x00\x00\x04\x17:\xb4\x01\x00\x00\x00\xc8\x01\x00\x00\t\x13mapassig" +
- "n1\x00\b\x17\"\x13mapType·1\x00\x00\x1d::\rhmap·2\x00\x00\x17:\vkey·" +
- "3\x00\x00\x17:\vval·4\x00\x00\x00\t\x15mapiterinit\x00\x06\x17\"\xd6\x01\x00\x00\x1d::\xd8" +
- "\x01\x00\x00\x17:\x0fhiter·3\x00\x00\x00\t\x11mapdelete\x00\x06\x17\"\xd6\x01\x00\x00\x1d::\xd8" +
- "\x01\x00\x00\x17:\xda\x01\x00\x00\x00\t\x15mapiternext\x00\x02\x17:\x0fhiter·1\x00\x00\x00\t" +
- "\x0fmakechan\x00\x04\x17\"\x15chanType·2\x00\x00\n\xa6\x01\x00\x00\x02\x1f\x06:\x0fhch" +
- "an·1\x00\x00\t\x11chanrecv1\x00\x06\x17\"\x15chanType·1\x00\x00\x1f\x02:\x0f" +
- "hchan·2\x00\x00\x17:j\x00\x00\x00\t\x11chanrecv2\x00\x06\x17\"\xea\x01\x00\x00\x1f\x02:\x0fh" +
- "chan·3\x00\x00\x17:\relem·4\x00\x00\x01\x00\x00\t\x11chansend1\x00\x06\x17\"\xf0" +
- "\x01\x00\x00\x1f\x04:\xf2\x01\x00\x00\x17:j\x00\x00\x00\t\x11closechan\x00\x02:\xec\x01\x00\x00\x00\a\x17wri" +
- "teBarrier\x00\x15\x06\renabled\x00\x00\x00\vneeded\x00\x00\x00\x05cgo\x00\x00\x00" +
- "\t\x1dwritebarrierptr\x00\x04\x17:\vdst·1\x00\x00:\vsrc·2\x00\x00" +
- "\x00\t\x17typedmemmove\x00\x06\x17\"t\x00\x00\x17:\vdst·2\x00\x00\x17:\vsrc\xc2" +
- "\xb73\x00\x00\x00\t\x1btypedslicecopy\x00\x06\x17\"\x06\x00\x00:\vdst·3\x00\x00:\v" +
- "src·4\x00\x00\x01\x02\x00\t\x17selectnbsend\x00\x06\x17\"\xea\x01\x00\x00\x1f\x04:\xf6\x01\x00\x00" +
- "\x17:\xf8\x01\x00\x00\x01\x00\x00\t\x17selectnbrecv\x00\x06\x17\"\xea\x01\x00\x00\x17:j\x00\x00\x1f\x02:\x0f" +
- "hchan·4\x00\x00\x01\x00\x00\t\x19selectnbrecv2\x00\b\x17\"\xea\x01\x00\x00\x17:j\x00" +
- "\x00\x17\x00\x15received·4\x00\x00\x1f\x02:\x0fhchan·5\x00\x00\x01\x00\x00\t\x11news" +
- "elect\x00\x06\x17\"\vsel·1\x00\x00\n\x13selsize·2\x00\x00\b\rsize·" +
- "3\x00\x00\x00\t\x13selectsend\x00\x06\x17\"\vsel·2\x00\x00\x1f\x04:\xf6\x01\x00\x00\x17:\xf8\x01" +
- "\x00\x00\x02\x00\x15selected·1\x00\x00\t\x13selectrecv\x00\x06\x17\"\xae\x02\x00\x00\x1f\x02" +
- ":\xf6\x01\x00\x00\x17:\xf8\x01\x00\x00\x02\x00\xb0\x02\x00\x00\t\x15selectrecv2\x00\b\x17\"\xae\x02\x00\x00\x1f\x02" +
- ":\xf6\x01\x00\x00\x17:\xf8\x01\x00\x00\x17\x00\x15received·5\x00\x00\x02\x00\xb0\x02\x00\x00\t\x19selec" +
- "tdefault\x00\x02\x17\"\xae\x02\x00\x00\x02\x00\xb0\x02\x00\x00\t\x0fselectgo\x00\x02\x17\"\xa6\x02\x00\x00" +
- "\x00\t\tblock\x00\x00\x00\t\x11makeslice\x00\x06\x17\"\x06\x00\x00\x02\vlen·3\x00\x00\x02" +
- "\vcap·4\x00\x00\x02\x11:\vary·1\x00\x00\t\x15makeslice64\x00\x06\x17\"\x06\x00" +
- "\x00\n\xc0\x02\x00\x00\n\xc2\x02\x00\x00\x02\x11:\xc4\x02\x00\x00\t\x11growslice\x00\x06\x17\"\x06\x00\x00\x11:\vo" +
- "ld·3\x00\x00\x02\xc2\x02\x00\x00\x02\x11:\xc4\x02\x00\x00\t\rmemmove\x00\x06\x17:\tto·1\x00\x00" +
- "\x17:\vfrm·2\x00\x00\x16\x11length·3\x00^\x00\t\vmemclr\x00\x04\x17\"\vpt" +
- "r·1\x00\x00\x16\x11length·2\x00^\x00\t\x0fmemequal\x00\x06\x17:\ax·2\x00" +
- "\x00\x17:\ay·3\x00\x00\x16\rsize·4\x00^\x01\x00\x00\t\x11memequal8\x00\x04\x17:\xdc" +
- "\x02\x00\x00\x17:\xde\x02\x00\x00\x01\x00\x00\t\x13memequal16\x00\x04\x17:\xdc\x02\x00\x00\x17:\xde\x02\x00\x00\x01\x00" +
- "\x00\t\x13memequal32\x00\x04\x17:\xdc\x02\x00\x00\x17:\xde\x02\x00\x00\x01\x00\x00\t\x13memequal" +
- "64\x00\x04\x17:\xdc\x02\x00\x00\x17:\xde\x02\x00\x00\x01\x00\x00\t\x15memequal128\x00\x04\x17:\xdc\x02\x00\x00" +
- "\x17:\xde\x02\x00\x00\x01\x00\x00\t\x0fint64div\x00\x03\n\x00\n\x00\x01\n\x00\t\x11uint64div\x00" +
- "\x03\x14\x00\x14\x00\x01\x14\x00\t\x0fint64mod\x00\x03\n\x00\n\x00\x01\n\x00\t\x11uint64mod\x00\x03" +
- "\x14\x00\x14\x00\x01\x14\x00\t\x1bfloat64toint64\x00\x01\x1a\x00\x01\n\x00\t\x1dfloat64t" +
- "ouint64\x00\x01\x1a\x00\x01\x14\x00\t\x1dfloat64touint32\x00\x01\x1a\x00\x01\x12\x00\t\x1b" +
- "int64tofloat64\x00\x01\n\x00\x01\x1a\x00\t\x1duint64tofloat64\x00\x01" +
- "\x14\x00\x01\x1a\x00\t\x1duint32tofloat64\x00\x01\x12\x00\x01\x1a\x00\t\x19complex12" +
- "8div\x00\x04\x1e\vnum·2\x00\x00\x1e\vden·3\x00\x00\x02\x1e\vquo·1\x00\x00\t\x19r" +
- "acefuncenter\x00\x01\x16^\x00\t\x17racefuncexit\x00\x00\x00\t\x0frace" +
- "read\x00\x01\x16^\x00\t\x11racewrite\x00\x01\x16^\x00\t\x19racereadrange" +
- "\x00\x04\x16\raddr·1\x00^\x16\rsize·2\x00^\x00\t\x1bracewriterang" +
- "e\x00\x04\x16\x92\x03\x00^\x16\x94\x03\x00^\x00\t\x0fmsanread\x00\x04\x16\x92\x03\x00^\x16\x94\x03\x00^\x00\t\x11m" +
- "sanwrite\x00\x04\x16\x92\x03\x00^\x16\x94\x03\x00^\x00\v\xf6\x01\v\x00\x01\x00\n$$\n"
+ "\x17:\xc6\x01\x00\x00\x17\"\rzero·6\x00\x00\x04\x17:\xb4\x01\x00\x00\x00\xc8\x01\x00\x00\t\x11mapassig" +
+ "n\x00\x06\x17\"\xa4\x01\x00\x00\x1d::\xb0\x01\x00\x00\x17:\xb2\x01\x00\x00\x02\x17:\xb4\x01\x00\x00\t\x15mapiterin" +
+ "it\x00\x06\x17\"\x13mapType·1\x00\x00\x1d::\rhmap·2\x00\x00\x17:\x0fhiter" +
+ "·3\x00\x00\x00\t\x11mapdelete\x00\x06\x17\"\xd8\x01\x00\x00\x1d::\xda\x01\x00\x00\x17:\vkey·" +
+ "3\x00\x00\x00\t\x15mapiternext\x00\x02\x17:\x0fhiter·1\x00\x00\x00\t\x0fmakec" +
+ "han\x00\x04\x17\"\x15chanType·2\x00\x00\n\xa6\x01\x00\x00\x02\x1f\x06:\x0fhchan·1\x00" +
+ "\x00\t\x11chanrecv1\x00\x06\x17\"\x15chanType·1\x00\x00\x1f\x02:\x0fhchan\xc2" +
+ "\xb72\x00\x00\x17:j\x00\x00\x00\t\x11chanrecv2\x00\x06\x17\"\xe8\x01\x00\x00\x1f\x02:\x0fhchan·" +
+ "3\x00\x00\x17:\relem·4\x00\x00\x01\x00\x00\t\x11chansend1\x00\x06\x17\"\xee\x01\x00\x00\x1f\x04:" +
+ "\xf0\x01\x00\x00\x17:j\x00\x00\x00\t\x11closechan\x00\x02:\xea\x01\x00\x00\x00\a\x17writeBarr" +
+ "ier\x00\x15\x06\renabled\x00\x00\x00\vneeded\x00\x00\x00\x05cgo\x00\x00\x00\t\x1dwrit" +
+ "ebarrierptr\x00\x04\x17:\vdst·1\x00\x00:\vsrc·2\x00\x00\x00\t\x17typ" +
+ "edmemmove\x00\x06\x17\"t\x00\x00\x17:\vdst·2\x00\x00\x17:\vsrc·3\x00\x00\x00\t" +
+ "\x1btypedslicecopy\x00\x06\x17\"\x06\x00\x00:\vdst·3\x00\x00:\vsrc·4" +
+ "\x00\x00\x01\x02\x00\t\x17selectnbsend\x00\x06\x17\"\xe8\x01\x00\x00\x1f\x04:\xf4\x01\x00\x00\x17:\xf6\x01\x00\x00" +
+ "\x01\x00\x00\t\x17selectnbrecv\x00\x06\x17\"\xe8\x01\x00\x00\x17:j\x00\x00\x1f\x02:\x0fhchan\xc2" +
+ "\xb74\x00\x00\x01\x00\x00\t\x19selectnbrecv2\x00\b\x17\"\xe8\x01\x00\x00\x17:j\x00\x00\x17\x00\x15re" +
+ "ceived·4\x00\x00\x1f\x02:\x0fhchan·5\x00\x00\x01\x00\x00\t\x11newselect\x00" +
+ "\x06\x17\"\vsel·1\x00\x00\n\x13selsize·2\x00\x00\b\rsize·3\x00\x00\x00\t\x13" +
+ "selectsend\x00\x06\x17\"\vsel·2\x00\x00\x1f\x04:\xf4\x01\x00\x00\x17:\xf6\x01\x00\x00\x02\x00\x15s" +
+ "elected·1\x00\x00\t\x13selectrecv\x00\x06\x17\"\xac\x02\x00\x00\x1f\x02:\xf4\x01\x00\x00\x17" +
+ ":\xf6\x01\x00\x00\x02\x00\xae\x02\x00\x00\t\x15selectrecv2\x00\b\x17\"\xac\x02\x00\x00\x1f\x02:\xf4\x01\x00\x00\x17" +
+ ":\xf6\x01\x00\x00\x17\x00\x15received·5\x00\x00\x02\x00\xae\x02\x00\x00\t\x19selectdefau" +
+ "lt\x00\x02\x17\"\xac\x02\x00\x00\x02\x00\xae\x02\x00\x00\t\x0fselectgo\x00\x02\x17\"\xa4\x02\x00\x00\x00\t\tblo" +
+ "ck\x00\x00\x00\t\x11makeslice\x00\x06\x17\"\x06\x00\x00\x02\vlen·3\x00\x00\x02\vcap·" +
+ "4\x00\x00\x02\x11:\vary·1\x00\x00\t\x15makeslice64\x00\x06\x17\"\x06\x00\x00\n\xbe\x02\x00\x00" +
+ "\n\xc0\x02\x00\x00\x02\x11:\xc2\x02\x00\x00\t\x11growslice\x00\x06\x17\"\x06\x00\x00\x11:\vold·3\x00" +
+ "\x00\x02\xc0\x02\x00\x00\x02\x11:\xc2\x02\x00\x00\t\rmemmove\x00\x06\x17:\tto·1\x00\x00\x17:\vfrm" +
+ "·2\x00\x00\x16\x11length·3\x00^\x00\t\vmemclr\x00\x04\x17\"\vptr·1\x00\x00" +
+ "\x16\x11length·2\x00^\x00\t\x0fmemequal\x00\x06\x17:\ax·2\x00\x00\x17:\ay\xc2" +
+ "\xb73\x00\x00\x16\rsize·4\x00^\x01\x00\x00\t\x11memequal8\x00\x04\x17:\xda\x02\x00\x00\x17:\xdc" +
+ "\x02\x00\x00\x01\x00\x00\t\x13memequal16\x00\x04\x17:\xda\x02\x00\x00\x17:\xdc\x02\x00\x00\x01\x00\x00\t\x13mem" +
+ "equal32\x00\x04\x17:\xda\x02\x00\x00\x17:\xdc\x02\x00\x00\x01\x00\x00\t\x13memequal64\x00\x04\x17:" +
+ "\xda\x02\x00\x00\x17:\xdc\x02\x00\x00\x01\x00\x00\t\x15memequal128\x00\x04\x17:\xda\x02\x00\x00\x17:\xdc\x02\x00\x00" +
+ "\x01\x00\x00\t\x0fint64div\x00\x03\n\x00\n\x00\x01\n\x00\t\x11uint64div\x00\x03\x14\x00\x14\x00\x01" +
+ "\x14\x00\t\x0fint64mod\x00\x03\n\x00\n\x00\x01\n\x00\t\x11uint64mod\x00\x03\x14\x00\x14\x00\x01\x14" +
+ "\x00\t\x1bfloat64toint64\x00\x01\x1a\x00\x01\n\x00\t\x1dfloat64touint6" +
+ "4\x00\x01\x1a\x00\x01\x14\x00\t\x1dfloat64touint32\x00\x01\x1a\x00\x01\x12\x00\t\x1bint64t" +
+ "ofloat64\x00\x01\n\x00\x01\x1a\x00\t\x1duint64tofloat64\x00\x01\x14\x00\x01\x1a\x00\t" +
+ "\x1duint32tofloat64\x00\x01\x12\x00\x01\x1a\x00\t\x19complex128div\x00\x04" +
+ "\x1e\vnum·2\x00\x00\x1e\vden·3\x00\x00\x02\x1e\vquo·1\x00\x00\t\x19racefun" +
+ "center\x00\x01\x16^\x00\t\x17racefuncexit\x00\x00\x00\t\x0fraceread\x00\x01" +
+ "\x16^\x00\t\x11racewrite\x00\x01\x16^\x00\t\x19racereadrange\x00\x04\x16\rad" +
+ "dr·1\x00^\x16\rsize·2\x00^\x00\t\x1bracewriterange\x00\x04\x16\x90\x03" +
+ "\x00^\x16\x92\x03\x00^\x00\t\x0fmsanread\x00\x04\x16\x90\x03\x00^\x16\x92\x03\x00^\x00\t\x11msanwri" +
+ "te\x00\x04\x16\x90\x03\x00^\x16\x92\x03\x00^\x00\v\xf6\x01\v\x00\x01\x00\n$$\n"
const unsafeimport = "" +
"version 2\n\n\x00\x00\x01\vunsafe\x00\t\x0fOffsetof\x00\x01:\x00\x01\x16\x00\t" +
diff --git a/src/cmd/compile/internal/gc/builtin/runtime.go b/src/cmd/compile/internal/gc/builtin/runtime.go
index 4d71e4eec3..c6afce9e70 100644
--- a/src/cmd/compile/internal/gc/builtin/runtime.go
+++ b/src/cmd/compile/internal/gc/builtin/runtime.go
@@ -93,7 +93,7 @@ func mapaccess2_fast32(mapType *byte, hmap map[any]any, key any) (val *any, pres
func mapaccess2_fast64(mapType *byte, hmap map[any]any, key any) (val *any, pres bool)
func mapaccess2_faststr(mapType *byte, hmap map[any]any, key any) (val *any, pres bool)
func mapaccess2_fat(mapType *byte, hmap map[any]any, key *any, zero *byte) (val *any, pres bool)
-func mapassign1(mapType *byte, hmap map[any]any, key *any, val *any)
+func mapassign(mapType *byte, hmap map[any]any, key *any) (val *any)
func mapiterinit(mapType *byte, hmap map[any]any, hiter *any)
func mapdelete(mapType *byte, hmap map[any]any, key *any)
func mapiternext(hiter *any)
diff --git a/src/cmd/compile/internal/gc/order.go b/src/cmd/compile/internal/gc/order.go
index 4f34049d6a..6d23566782 100644
--- a/src/cmd/compile/internal/gc/order.go
+++ b/src/cmd/compile/internal/gc/order.go
@@ -188,9 +188,9 @@ func isaddrokay(n *Node) bool {
return islvalue(n) && (n.Op != ONAME || n.Class == PEXTERN || istemp(n))
}
-// Orderaddrtemp ensures that *np is okay to pass by address to runtime routines.
-// If the original argument *np is not okay, orderaddrtemp creates a tmp, emits
-// tmp = *np, and then sets *np to the tmp variable.
+// Orderaddrtemp ensures that n is okay to pass by address to runtime routines.
+// If the original argument n is not okay, orderaddrtemp creates a tmp, emits
+// tmp = n, and then returns tmp.
func orderaddrtemp(n *Node, order *Order) *Node {
if isaddrokay(n) {
return n
@@ -395,13 +395,8 @@ func ordercall(n *Node, order *Order) {
}
// Ordermapassign appends n to order->out, introducing temporaries
-// to make sure that all map assignments have the form m[k] = x,
-// where x is addressable.
-// (Orderexpr has already been called on n, so we know k is addressable.)
-//
-// If n is m[k] = x where x is not addressable, the rewrite is:
-// tmp = x
-// m[k] = tmp
+// to make sure that all map assignments have the form m[k] = x.
+// (Note: orderexpr has already been called on n, so we know k is addressable.)
//
// If n is the multiple assignment form ..., m[k], ... = ..., the rewrite is
// t1 = m
@@ -428,7 +423,7 @@ func ordermapassign(n *Node, order *Order) {
// We call writebarrierfat only for values > 4 pointers long. See walk.go.
// TODO(mdempsky): writebarrierfat doesn't exist anymore, but removing that
// logic causes net/http's tests to become flaky; see CL 21242.
- if (n.Left.Op == OINDEXMAP || (needwritebarrier(n.Left, n.Right) && n.Left.Type.Width > int64(4*Widthptr))) && !isaddrokay(n.Right) {
+ if needwritebarrier(n.Left, n.Right) && n.Left.Type.Width > int64(4*Widthptr) && !isaddrokay(n.Right) {
m := n.Left
n.Left = ordertemp(m.Type, order, false)
a := nod(OAS, m, n.Left)
@@ -1061,8 +1056,14 @@ func orderexpr(n *Node, order *Order, lhs *Node) *Node {
// key must be addressable
case OINDEXMAP:
n.Left = orderexpr(n.Left, order, nil)
-
n.Right = orderexpr(n.Right, order, nil)
+ needCopy := false
+
+ if n.Etype == 0 && instrumenting {
+ // Race detector needs the copy so it can
+ // call treecopy on the result.
+ needCopy = true
+ }
// For x = m[string(k)] where k is []byte, the allocation of
// backing bytes for the string can be avoided by reusing
@@ -1076,12 +1077,13 @@ func orderexpr(n *Node, order *Order, lhs *Node) *Node {
// conversion (by the ordercopyexpr a few lines below).
if n.Etype == 0 && n.Right.Op == OARRAYBYTESTR {
n.Right.Op = OARRAYBYTESTRTMP
+ needCopy = true
}
+ // Map calls need to take the address of the key.
n.Right = orderaddrtemp(n.Right, order)
- if n.Etype == 0 {
- // use of value (not being assigned);
- // make copy in temporary.
+
+ if needCopy {
n = ordercopyexpr(n, n.Type, order, 0)
}
diff --git a/src/cmd/compile/internal/gc/racewalk.go b/src/cmd/compile/internal/gc/racewalk.go
index effdcf9ea4..74fa53da73 100644
--- a/src/cmd/compile/internal/gc/racewalk.go
+++ b/src/cmd/compile/internal/gc/racewalk.go
@@ -474,8 +474,8 @@ func isartificial(n *Node) bool {
func callinstr(np **Node, init *Nodes, wr int, skip int) bool {
n := *np
- //print("callinstr for %+N [ %O ] etype=%E class=%d\n",
- // n, n->op, n->type ? n->type->etype : -1, n->class);
+ //fmt.Printf("callinstr for %v [ %v ] etype=%v class=%v\n",
+ // n, n.Op, n.Type.Etype, n.Class)
if skip != 0 || n.Type == nil || n.Type.Etype >= TIDEAL {
return false
diff --git a/src/cmd/compile/internal/gc/syntax.go b/src/cmd/compile/internal/gc/syntax.go
index 7a230c0b74..7a33fc0708 100644
--- a/src/cmd/compile/internal/gc/syntax.go
+++ b/src/cmd/compile/internal/gc/syntax.go
@@ -52,7 +52,7 @@ type Node struct {
Op Op
Ullman uint8 // sethi/ullman number
Addable bool // addressable
- Etype EType // op for OASOP, etype for OTYPE, exclam for export, 6g saved reg, ChanDir for OTCHAN
+ Etype EType // op for OASOP, etype for OTYPE, exclam for export, 6g saved reg, ChanDir for OTCHAN, for OINDEXMAP 1=LHS,0=RHS
Bounded bool // bounds check unnecessary
NonNil bool // guaranteed to be non-nil
Class Class // PPARAM, PAUTO, PEXTERN, etc
diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go
index ddd36e7b18..dcb80f72c9 100644
--- a/src/cmd/compile/internal/gc/walk.go
+++ b/src/cmd/compile/internal/gc/walk.go
@@ -1292,44 +1292,48 @@ opswitch:
}
case OINDEXMAP:
- if n.Etype == 1 {
- break
- }
+ // Replace m[k] with *map{access1,assign}(maptype, m, &k)
n.Left = walkexpr(n.Left, init)
n.Right = walkexpr(n.Right, init)
-
- t := n.Left.Type
- p := ""
- if t.Val().Width <= 128 { // Check ../../runtime/hashmap.go:maxValueSize before changing.
- switch algtype(t.Key()) {
- case AMEM32:
- p = "mapaccess1_fast32"
- case AMEM64:
- p = "mapaccess1_fast64"
- case ASTRING:
- p = "mapaccess1_faststr"
+ map_ := n.Left
+ key := n.Right
+ t := map_.Type
+ if n.Etype == 1 {
+ // This m[k] expression is on the left-hand side of an assignment.
+ // orderexpr made sure key is addressable.
+ key = nod(OADDR, key, nil)
+ n = mkcall1(mapfn("mapassign", t), nil, init, typename(t), map_, key)
+ } else {
+ // m[k] is not the target of an assignment.
+ p := ""
+ if t.Val().Width <= 128 { // Check ../../runtime/hashmap.go:maxValueSize before changing.
+ switch algtype(t.Key()) {
+ case AMEM32:
+ p = "mapaccess1_fast32"
+ case AMEM64:
+ p = "mapaccess1_fast64"
+ case ASTRING:
+ p = "mapaccess1_faststr"
+ }
}
- }
- var key *Node
- if p != "" {
- // fast versions take key by value
- key = n.Right
- } else {
- // standard version takes key by reference.
- // orderexpr made sure key is addressable.
- key = nod(OADDR, n.Right, nil)
- p = "mapaccess1"
- }
+ if p == "" {
+ // standard version takes key by reference.
+ // orderexpr made sure key is addressable.
+ key = nod(OADDR, key, nil)
+ p = "mapaccess1"
+ }
- if w := t.Val().Width; w <= 1024 { // 1024 must match ../../../../runtime/hashmap.go:maxZero
- n = mkcall1(mapfn(p, t), ptrto(t.Val()), init, typename(t), n.Left, key)
- } else {
- p = "mapaccess1_fat"
- z := zeroaddr(w)
- n = mkcall1(mapfn(p, t), ptrto(t.Val()), init, typename(t), n.Left, key, z)
+ if w := t.Val().Width; w <= 1024 { // 1024 must match ../../../../runtime/hashmap.go:maxZero
+ n = mkcall1(mapfn(p, t), ptrto(t.Val()), init, typename(t), map_, key)
+ } else {
+ p = "mapaccess1_fat"
+ z := zeroaddr(w)
+ n = mkcall1(mapfn(p, t), ptrto(t.Val()), init, typename(t), map_, key, z)
+ }
}
- n.NonNil = true // mapaccess always returns a non-nil pointer
+ n.Type = ptrto(t.Val())
+ n.NonNil = true // mapaccess1* and mapassign always return non-nil pointers.
n = nod(OIND, n, nil)
n.Type = t.Val()
n.Typecheck = 1
@@ -2306,22 +2310,6 @@ func convas(n *Node, init *Nodes) *Node {
goto out
}
- if n.Left.Op == OINDEXMAP {
- map_ := n.Left.Left
- key := n.Left.Right
- val := n.Right
- map_ = walkexpr(map_, init)
- key = walkexpr(key, init)
- val = walkexpr(val, init)
-
- // orderexpr made sure key and val are addressable.
- key = nod(OADDR, key, nil)
-
- val = nod(OADDR, val, nil)
- n = mkcall1(mapfn("mapassign1", map_.Type), nil, init, typename(map_.Type), map_, key, val)
- goto out
- }
-
if !eqtype(lt, rt) {
n.Right = assignconv(n.Right, lt, "assignment")
n.Right = walkexpr(n.Right, init)
diff --git a/src/runtime/hashmap.go b/src/runtime/hashmap.go
index ab99d24c35..68f4c8b841 100644
--- a/src/runtime/hashmap.go
+++ b/src/runtime/hashmap.go
@@ -481,20 +481,19 @@ func mapaccess2_fat(t *maptype, h *hmap, key, zero unsafe.Pointer) (unsafe.Point
return v, true
}
-func mapassign1(t *maptype, h *hmap, key unsafe.Pointer, val unsafe.Pointer) {
+// Like mapaccess, but allocates a slot for the key if it is not present in the map.
+func mapassign(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer {
if h == nil {
panic(plainError("assignment to entry in nil map"))
}
if raceenabled {
callerpc := getcallerpc(unsafe.Pointer(&t))
- pc := funcPC(mapassign1)
+ pc := funcPC(mapassign)
racewritepc(unsafe.Pointer(h), callerpc, pc)
raceReadObjectPC(t.key, key, callerpc, pc)
- raceReadObjectPC(t.elem, val, callerpc, pc)
}
if msanenabled {
msanread(key, t.key.size)
- msanread(val, t.elem.size)
}
if h.flags&hashWriting != 0 {
throw("concurrent map writes")
@@ -521,35 +520,29 @@ again:
var inserti *uint8
var insertk unsafe.Pointer
- var insertv unsafe.Pointer
+ var val unsafe.Pointer
for {
for i := uintptr(0); i < bucketCnt; i++ {
if b.tophash[i] != top {
if b.tophash[i] == empty && inserti == nil {
inserti = &b.tophash[i]
insertk = add(unsafe.Pointer(b), dataOffset+i*uintptr(t.keysize))
- insertv = add(unsafe.Pointer(b), dataOffset+bucketCnt*uintptr(t.keysize)+i*uintptr(t.valuesize))
+ val = add(unsafe.Pointer(b), dataOffset+bucketCnt*uintptr(t.keysize)+i*uintptr(t.valuesize))
}
continue
}
k := add(unsafe.Pointer(b), dataOffset+i*uintptr(t.keysize))
- k2 := k
if t.indirectkey {
- k2 = *((*unsafe.Pointer)(k2))
+ k = *((*unsafe.Pointer)(k))
}
- if !alg.equal(key, k2) {
+ if !alg.equal(key, k) {
continue
}
// already have a mapping for key. Update it.
if t.needkeyupdate {
- typedmemmove(t.key, k2, key)
+ typedmemmove(t.key, k, key)
}
- v := add(unsafe.Pointer(b), dataOffset+bucketCnt*uintptr(t.keysize)+i*uintptr(t.valuesize))
- v2 := v
- if t.indirectvalue {
- v2 = *((*unsafe.Pointer)(v2))
- }
- typedmemmove(t.elem, v2, val)
+ val = add(unsafe.Pointer(b), dataOffset+bucketCnt*uintptr(t.keysize)+i*uintptr(t.valuesize))
goto done
}
ovf := b.overflow(t)
@@ -574,7 +567,7 @@ again:
h.setoverflow(t, b, newb)
inserti = &newb.tophash[0]
insertk = add(unsafe.Pointer(newb), dataOffset)
- insertv = add(insertk, bucketCnt*uintptr(t.keysize))
+ val = add(insertk, bucketCnt*uintptr(t.keysize))
}
// store new key/value at insert position
@@ -585,11 +578,9 @@ again:
}
if t.indirectvalue {
vmem := newobject(t.elem)
- *(*unsafe.Pointer)(insertv) = vmem
- insertv = vmem
+ *(*unsafe.Pointer)(val) = vmem
}
typedmemmove(t.key, insertk, key)
- typedmemmove(t.elem, insertv, val)
*inserti = top
h.count++
@@ -598,6 +589,10 @@ done:
throw("concurrent map writes")
}
h.flags &^= hashWriting
+ if t.indirectvalue {
+ val = *((*unsafe.Pointer)(val))
+ }
+ return val
}
func mapdelete(t *maptype, h *hmap, key unsafe.Pointer) {
@@ -1128,7 +1123,8 @@ func reflect_mapaccess(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer {
//go:linkname reflect_mapassign reflect.mapassign
func reflect_mapassign(t *maptype, h *hmap, key unsafe.Pointer, val unsafe.Pointer) {
- mapassign1(t, h, key, val)
+ p := mapassign(t, h, key)
+ typedmemmove(t.elem, p, val)
}
//go:linkname reflect_mapdelete reflect.mapdelete