aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKeith Randall <khr@golang.org>2016-09-17 15:04:36 -0700
committerKeith Randall <khr@golang.org>2016-09-19 02:37:08 +0000
commit6129f37367686edf7c2732fbb5300d5f28203743 (patch)
tree18dfa388342ea4868caab33c299be065d558be76 /src
parent892d146a7aae17e5fe22e04b16ba4da7e3d8c767 (diff)
downloadgo-6129f37367686edf7c2732fbb5300d5f28203743.tar.xz
cmd/compile: inline convT2{I,E} when result doesn't escape
No point in calling a function when we can build the interface using a known type (or itab) and the address of a local. Get rid of third arg (preallocated stack space) to convT2{I,E}. Makes go binary smaller by 0.2% benchmark old ns/op new ns/op delta BenchmarkEfaceInteger-8 16.7 10.1 -39.52% Update #17118 Update #15375 Change-Id: I9724a1f802bfa1e3957bf1856b55558278e198a2 Reviewed-on: https://go-review.googlesource.com/29373 Run-TryBot: Keith Randall <khr@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Diffstat (limited to 'src')
-rw-r--r--src/cmd/compile/internal/gc/builtin.go151
-rw-r--r--src/cmd/compile/internal/gc/builtin/runtime.go4
-rw-r--r--src/cmd/compile/internal/gc/fixedbugs_test.go2
-rw-r--r--src/cmd/compile/internal/gc/iface_test.go128
-rw-r--r--src/cmd/compile/internal/gc/walk.go36
-rw-r--r--src/runtime/iface.go16
6 files changed, 232 insertions, 105 deletions
diff --git a/src/cmd/compile/internal/gc/builtin.go b/src/cmd/compile/internal/gc/builtin.go
index cec02220ae..e78b1ace74 100644
--- a/src/cmd/compile/internal/gc/builtin.go
+++ b/src/cmd/compile/internal/gc/builtin.go
@@ -28,82 +28,81 @@ const runtimeimport = "" +
"\x00\x00:\tfr·3\x00\x00\x16\vwid·4\x00\x1bunsafe-uintptr\x01\x02\x00\t\x1d" +
"slicestringcopy\x00\x04:X\x00\x00:Z\x00\x00\x01\x02\x00\t\rconvI2E\x00\x02:" +
"\relem·2\x00\x00\x02:\vret·1\x00\x00\t\rconvI2I\x00\x04\x17\"\x06\x00\x00:\re" +
- "lem·3\x00\x00\x02:f\x00\x00\t\rconvT2E\x00\x06\x17\"\x06\x00\x00\x17:j\x00\x00\x17:\vbuf" +
- "·4\x00\x00\x02:f\x00\x00\t\rconvT2I\x00\x06\x17\"\vtab·2\x00\x00\x17:j\x00\x00\x17:n" +
- "\x00\x00\x02:f\x00\x00\t\x11assertE2E\x00\x06\x17\"\vtyp·1\x00\x00:\x0fiface·" +
- "2\x00\x00\x17:\vret·3\x00\x00\x00\t\x13assertE2E2\x00\x06\x17\"\x06\x00\x00:\x0fifac" +
- "e·3\x00\x00\x17:\vret·4\x00\x00\x01\x00\x00\t\x11assertE2I\x00\x06\x17\"v\x00\x00:x" +
- "\x00\x00\x17:z\x00\x00\x00\t\x13assertE2I2\x00\x06\x17\"\x06\x00\x00:~\x00\x00\x17:\x80\x01\x00\x00\x01\x00\x00" +
- "\t\x11assertE2T\x00\x06\x17\"v\x00\x00:x\x00\x00\x17:z\x00\x00\x00\t\x13assertE2T2" +
- "\x00\x06\x17\"\x06\x00\x00:~\x00\x00\x17:\x80\x01\x00\x00\x01\x00\x00\t\x11assertI2E\x00\x06\x17\"v\x00\x00:x" +
- "\x00\x00\x17:z\x00\x00\x00\t\x13assertI2E2\x00\x06\x17\"\x06\x00\x00:~\x00\x00\x17:\x80\x01\x00\x00\x01\x00\x00" +
- "\t\x11assertI2I\x00\x06\x17\"v\x00\x00:x\x00\x00\x17:z\x00\x00\x00\t\x13assertI2I2" +
- "\x00\x06\x17\"\x06\x00\x00:~\x00\x00\x17:\x80\x01\x00\x00\x01\x00\x00\t\x11assertI2T\x00\x06\x17\"v\x00\x00:x" +
- "\x00\x00\x17:z\x00\x00\x00\t\x13assertI2T2\x00\x06\x17\"\x06\x00\x00:~\x00\x00\x17:\x80\x01\x00\x00\x01\x00\x00" +
- "\t\x17panicdottype\x00\x06\x17\"\rhave·1\x00\x00\x17\"\rwant·2\x00\x00" +
- "\x17\"~\x00\x00\x00\t\rifaceeq\x00\x04:\ti1·2\x00\x00:\ti2·3\x00\x00\x02\x00f\x00\x00" +
- "\t\refaceeq\x00\x04:\x9e\x01\x00\x00:\xa0\x01\x00\x00\x02\x00f\x00\x00\t\rmakemap\x00\b\x17\"\x13" +
- "mapType·2\x00\x00\n\rhint·3\x00\x00\x17:\x11mapbuf·4\x00\x00\x17:\x17" +
- "bucketbuf·5\x00\x00\x02\x1d::\rhmap·1\x00\x00\t\x13mapaccess1" +
- "\x00\x06\x17\"\xa6\x01\x00\x00\x1d::\rhmap·3\x00\x00\x17:\vkey·4\x00\x00\x02\x17:\vval\xc2" +
- "\xb71\x00\x00\t!mapaccess1_fast32\x00\x06\x17\"\xa6\x01\x00\x00\x1d::\xb2\x01\x00\x00:\xb4" +
- "\x01\x00\x00\x02\x17:\xb6\x01\x00\x00\t!mapaccess1_fast64\x00\x06\x17\"\xa6\x01\x00\x00\x1d::" +
- "\xb2\x01\x00\x00:\xb4\x01\x00\x00\x02\x17:\xb6\x01\x00\x00\t#mapaccess1_faststr\x00\x06\x17\"" +
- "\xa6\x01\x00\x00\x1d::\xb2\x01\x00\x00:\xb4\x01\x00\x00\x02\x17:\xb6\x01\x00\x00\t\x1bmapaccess1_fat\x00" +
- "\b\x17\"\xa6\x01\x00\x00\x1d::\xb2\x01\x00\x00\x17:\xb4\x01\x00\x00\x17\"\rzero·5\x00\x00\x02\x17:\xb6\x01\x00\x00\t" +
- "\x13mapaccess2\x00\x06\x17\"\x13mapType·3\x00\x00\x1d::\rhmap·4\x00" +
- "\x00\x17:\vkey·5\x00\x00\x04\x17:\xb6\x01\x00\x00\x00\rpres·2\x00\x00\t!mapacces" +
- "s2_fast32\x00\x06\x17\"\xc4\x01\x00\x00\x1d::\xc6\x01\x00\x00:\xc8\x01\x00\x00\x04\x17:\xb6\x01\x00\x00\x00\xca\x01\x00" +
- "\x00\t!mapaccess2_fast64\x00\x06\x17\"\xc4\x01\x00\x00\x1d::\xc6\x01\x00\x00:\xc8\x01\x00\x00" +
- "\x04\x17:\xb6\x01\x00\x00\x00\xca\x01\x00\x00\t#mapaccess2_faststr\x00\x06\x17\"\xc4\x01\x00\x00" +
- "\x1d::\xc6\x01\x00\x00:\xc8\x01\x00\x00\x04\x17:\xb6\x01\x00\x00\x00\xca\x01\x00\x00\t\x1bmapaccess2_fat" +
- "\x00\b\x17\"\xc4\x01\x00\x00\x1d::\xc6\x01\x00\x00\x17:\xc8\x01\x00\x00\x17\"\rzero·6\x00\x00\x04\x17:\xb6\x01\x00\x00" +
- "\x00\xca\x01\x00\x00\t\x13mapassign1\x00\b\x17\"\x13mapType·1\x00\x00\x1d::\rhm" +
- "ap·2\x00\x00\x17:\vkey·3\x00\x00\x17:\vval·4\x00\x00\x00\t\x15mapiteri" +
- "nit\x00\x06\x17\"\xd8\x01\x00\x00\x1d::\xda\x01\x00\x00\x17:\x0fhiter·3\x00\x00\x00\t\x11mapdel" +
- "ete\x00\x06\x17\"\xd8\x01\x00\x00\x1d::\xda\x01\x00\x00\x17:\xdc\x01\x00\x00\x00\t\x15mapiternext\x00\x02" +
- "\x17:\x0fhiter·1\x00\x00\x00\t\x0fmakechan\x00\x04\x17\"\x15chanType·2" +
- "\x00\x00\n\xa8\x01\x00\x00\x02\x1f\x06:\x0fhchan·1\x00\x00\t\x11chanrecv1\x00\x06\x17\"\x15ch" +
- "anType·1\x00\x00\x1f\x02:\x0fhchan·2\x00\x00\x17:j\x00\x00\x00\t\x11chanrec" +
- "v2\x00\x06\x17\"\xec\x01\x00\x00\x1f\x02:\x0fhchan·3\x00\x00\x17:\relem·4\x00\x00\x01\x00\x00\t" +
- "\x11chansend1\x00\x06\x17\"\xf2\x01\x00\x00\x1f\x04:\xf4\x01\x00\x00\x17:j\x00\x00\x00\t\x11closech" +
- "an\x00\x02:\xee\x01\x00\x00\x00\a\x17writeBarrier\x00\x15\x06\renabled\x00\x00\x00\vn" +
- "eeded\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\"v\x00\x00\x17:\v" +
- "dst·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\"\xec\x01\x00\x00\x1f\x04:\xf8\x01\x00\x00\x17:\xfa\x01\x00\x00\x01\x00\x00\t\x17selectnbrecv\x00\x06" +
- "\x17\"\xec\x01\x00\x00\x17:j\x00\x00\x1f\x02:\x0fhchan·4\x00\x00\x01\x00\x00\t\x19selectnbre" +
- "cv2\x00\b\x17\"\xec\x01\x00\x00\x17:j\x00\x00\x17\x00\x15received·4\x00\x00\x1f\x02:\x0fhcha" +
- "n·5\x00\x00\x01\x00\x00\t\x11newselect\x00\x06\x17\"\vsel·1\x00\x00\n\x13selsi" +
- "ze·2\x00\x00\b\rsize·3\x00\x00\x00\t\x13selectsend\x00\x06\x17\"\vsel\xc2" +
- "\xb72\x00\x00\x1f\x04:\xf8\x01\x00\x00\x17:\xfa\x01\x00\x00\x02\x00\x15selected·1\x00\x00\t\x13selec" +
- "trecv\x00\x06\x17\"\xb0\x02\x00\x00\x1f\x02:\xf8\x01\x00\x00\x17:\xfa\x01\x00\x00\x02\x00\xb2\x02\x00\x00\t\x15select" +
- "recv2\x00\b\x17\"\xb0\x02\x00\x00\x1f\x02:\xf8\x01\x00\x00\x17:\xfa\x01\x00\x00\x17\x00\x15received·5" +
- "\x00\x00\x02\x00\xb2\x02\x00\x00\t\x19selectdefault\x00\x02\x17\"\xb0\x02\x00\x00\x02\x00\xb2\x02\x00\x00\t\x0fs" +
- "electgo\x00\x02\x17\"\xa8\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\x15ma" +
- "keslice64\x00\x06\x17\"\x06\x00\x00\n\xc2\x02\x00\x00\n\xc4\x02\x00\x00\x02\x11:\xc6\x02\x00\x00\t\x11grows" +
- "lice\x00\x06\x17\"\x06\x00\x00\x11:\vold·3\x00\x00\x02\xc4\x02\x00\x00\x02\x11:\xc6\x02\x00\x00\t\rmemm" +
- "ove\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\x0fmem" +
- "equal\x00\x06\x17:\ax·2\x00\x00\x17:\ay·3\x00\x00\x16\rsize·4\x00^\x01\x00\x00\t" +
- "\x11memequal8\x00\x04\x17:\xde\x02\x00\x00\x17:\xe0\x02\x00\x00\x01\x00\x00\t\x13memequal16\x00" +
- "\x04\x17:\xde\x02\x00\x00\x17:\xe0\x02\x00\x00\x01\x00\x00\t\x13memequal32\x00\x04\x17:\xde\x02\x00\x00\x17:\xe0\x02" +
- "\x00\x00\x01\x00\x00\t\x13memequal64\x00\x04\x17:\xde\x02\x00\x00\x17:\xe0\x02\x00\x00\x01\x00\x00\t\x15meme" +
- "qual128\x00\x04\x17:\xde\x02\x00\x00\x17:\xe0\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\x1dfloat64touint64\x00\x01\x1a\x00\x01\x14\x00\t\x1dfloat64to" +
- "uint32\x00\x01\x1a\x00\x01\x12\x00\t\x1bint64tofloat64\x00\x01\n\x00\x01\x1a\x00\t\x1dui" +
- "nt64tofloat64\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\x19racefuncenter\x00\x01\x16^\x00\t\x17racefu" +
- "ncexit\x00\x00\x00\t\x0fraceread\x00\x01\x16^\x00\t\x11racewrite\x00\x01\x16^\x00" +
- "\t\x19racereadrange\x00\x04\x16\raddr·1\x00^\x16\rsize·2\x00^\x00" +
- "\t\x1bracewriterange\x00\x04\x16\x94\x03\x00^\x16\x96\x03\x00^\x00\t\x0fmsanread\x00" +
- "\x04\x16\x94\x03\x00^\x16\x96\x03\x00^\x00\t\x11msanwrite\x00\x04\x16\x94\x03\x00^\x16\x96\x03\x00^\x00\v\xf6\x01\v" +
- "\x00\x01\x00\n$$\n"
+ "lem·3\x00\x00\x02:f\x00\x00\t\rconvT2E\x00\x04\x17\"\x06\x00\x00\x17:j\x00\x00\x02:f\x00\x00\t" +
+ "\rconvT2I\x00\x04\x17\"\vtab·2\x00\x00\x17:j\x00\x00\x02:f\x00\x00\t\x11assertE" +
+ "2E\x00\x06\x17\"\vtyp·1\x00\x00:\x0fiface·2\x00\x00\x17:\vret·3\x00\x00\x00\t" +
+ "\x13assertE2E2\x00\x06\x17\"\x06\x00\x00:\x0fiface·3\x00\x00\x17:\vret·4\x00" +
+ "\x00\x01\x00\x00\t\x11assertE2I\x00\x06\x17\"t\x00\x00:v\x00\x00\x17:x\x00\x00\x00\t\x13assert" +
+ "E2I2\x00\x06\x17\"\x06\x00\x00:||\x00\x00\x17:~\x00\x00\x01\x00\x00\t\x11assertE2T\x00\x06\x17\"t" +
+ "\x00\x00:v\x00\x00\x17:x\x00\x00\x00\t\x13assertE2T2\x00\x06\x17\"\x06\x00\x00:||\x00\x00\x17:~\x00" +
+ "\x00\x01\x00\x00\t\x11assertI2E\x00\x06\x17\"t\x00\x00:v\x00\x00\x17:x\x00\x00\x00\t\x13assert" +
+ "I2E2\x00\x06\x17\"\x06\x00\x00:||\x00\x00\x17:~\x00\x00\x01\x00\x00\t\x11assertI2I\x00\x06\x17\"t" +
+ "\x00\x00:v\x00\x00\x17:x\x00\x00\x00\t\x13assertI2I2\x00\x06\x17\"\x06\x00\x00:||\x00\x00\x17:~\x00" +
+ "\x00\x01\x00\x00\t\x11assertI2T\x00\x06\x17\"t\x00\x00:v\x00\x00\x17:x\x00\x00\x00\t\x13assert" +
+ "I2T2\x00\x06\x17\"\x06\x00\x00:||\x00\x00\x17:~\x00\x00\x01\x00\x00\t\x17panicdottype\x00\x06" +
+ "\x17\"\rhave·1\x00\x00\x17\"\rwant·2\x00\x00\x17\"||\x00\x00\x00\t\rifaceeq" +
+ "\x00\x04:\ti1·2\x00\x00:\ti2·3\x00\x00\x02\x00f\x00\x00\t\refaceeq\x00\x04:\x9c\x01\x00" +
+ "\x00:\x9e\x01\x00\x00\x02\x00f\x00\x00\t\rmakemap\x00\b\x17\"\x13mapType·2\x00\x00\n\rh" +
+ "int·3\x00\x00\x17:\x11mapbuf·4\x00\x00\x17:\x17bucketbuf·5\x00\x00\x02" +
+ "\x1d::\rhmap·1\x00\x00\t\x13mapaccess1\x00\x06\x17\"\xa4\x01\x00\x00\x1d::\rhma" +
+ "p·3\x00\x00\x17:\vkey·4\x00\x00\x02\x17:\vval·1\x00\x00\t!mapaccess" +
+ "1_fast32\x00\x06\x17\"\xa4\x01\x00\x00\x1d::\xb0\x01\x00\x00:\xb2\x01\x00\x00\x02\x17:\xb4\x01\x00\x00\t!map" +
+ "access1_fast64\x00\x06\x17\"\xa4\x01\x00\x00\x1d::\xb0\x01\x00\x00:\xb2\x01\x00\x00\x02\x17:\xb4\x01\x00" +
+ "\x00\t#mapaccess1_faststr\x00\x06\x17\"\xa4\x01\x00\x00\x1d::\xb0\x01\x00\x00:\xb2\x01\x00" +
+ "\x00\x02\x17:\xb4\x01\x00\x00\t\x1bmapaccess1_fat\x00\b\x17\"\xa4\x01\x00\x00\x1d::\xb0\x01\x00\x00\x17" +
+ ":\xb2\x01\x00\x00\x17\"\rzero·5\x00\x00\x02\x17:\xb4\x01\x00\x00\t\x13mapaccess2\x00\x06\x17\"" +
+ "\x13mapType·3\x00\x00\x1d::\rhmap·4\x00\x00\x17:\vkey·5\x00\x00\x04\x17:" +
+ "\xb4\x01\x00\x00\x00\rpres·2\x00\x00\t!mapaccess2_fast32\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!mapaccess2_f" +
+ "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"
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 762abbaf1c..4d71e4eec3 100644
--- a/src/cmd/compile/internal/gc/builtin/runtime.go
+++ b/src/cmd/compile/internal/gc/builtin/runtime.go
@@ -60,8 +60,8 @@ func slicestringcopy(to any, fr any) int
// interface conversions
func convI2E(elem any) (ret any)
func convI2I(typ *byte, elem any) (ret any)
-func convT2E(typ *byte, elem, buf *any) (ret any)
-func convT2I(tab *byte, elem, buf *any) (ret any)
+func convT2E(typ *byte, elem *any) (ret any)
+func convT2I(tab *byte, elem *any) (ret any)
// interface type assertions x.(T)
func assertE2E(typ *byte, iface any, ret *any)
diff --git a/src/cmd/compile/internal/gc/fixedbugs_test.go b/src/cmd/compile/internal/gc/fixedbugs_test.go
index 19b1d9adf6..095b816a53 100644
--- a/src/cmd/compile/internal/gc/fixedbugs_test.go
+++ b/src/cmd/compile/internal/gc/fixedbugs_test.go
@@ -18,7 +18,7 @@ func makeT() T {
var g T
-var sink []byte
+var sink interface{}
func TestIssue15854(t *testing.T) {
for i := 0; i < 10000; i++ {
diff --git a/src/cmd/compile/internal/gc/iface_test.go b/src/cmd/compile/internal/gc/iface_test.go
new file mode 100644
index 0000000000..21c6587217
--- /dev/null
+++ b/src/cmd/compile/internal/gc/iface_test.go
@@ -0,0 +1,128 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gc
+
+// Test to make sure we make copies of the values we
+// put in interfaces.
+
+import (
+ "testing"
+)
+
+var x int
+
+func TestEfaceConv1(t *testing.T) {
+ a := 5
+ i := interface{}(a)
+ a += 2
+ if got := i.(int); got != 5 {
+ t.Errorf("wanted 5, got %d\n", got)
+ }
+}
+
+func TestEfaceConv2(t *testing.T) {
+ a := 5
+ sink = &a
+ i := interface{}(a)
+ a += 2
+ if got := i.(int); got != 5 {
+ t.Errorf("wanted 5, got %d\n", got)
+ }
+}
+
+func TestEfaceConv3(t *testing.T) {
+ x = 5
+ if got := e2int3(x); got != 5 {
+ t.Errorf("wanted 5, got %d\n", got)
+ }
+}
+
+//go:noinline
+func e2int3(i interface{}) int {
+ x = 7
+ return i.(int)
+}
+
+func TestEfaceConv4(t *testing.T) {
+ a := 5
+ if got := e2int4(a, &a); got != 5 {
+ t.Errorf("wanted 5, got %d\n", got)
+ }
+}
+
+//go:noinline
+func e2int4(i interface{}, p *int) int {
+ *p = 7
+ return i.(int)
+}
+
+type Int int
+
+var y Int
+
+type I interface {
+ foo()
+}
+
+func (i Int) foo() {
+}
+
+func TestIfaceConv1(t *testing.T) {
+ a := Int(5)
+ i := interface{}(a)
+ a += 2
+ if got := i.(Int); got != 5 {
+ t.Errorf("wanted 5, got %d\n", int(got))
+ }
+}
+
+func TestIfaceConv2(t *testing.T) {
+ a := Int(5)
+ sink = &a
+ i := interface{}(a)
+ a += 2
+ if got := i.(Int); got != 5 {
+ t.Errorf("wanted 5, got %d\n", int(got))
+ }
+}
+
+func TestIfaceConv3(t *testing.T) {
+ y = 5
+ if got := i2Int3(y); got != 5 {
+ t.Errorf("wanted 5, got %d\n", int(got))
+ }
+}
+
+//go:noinline
+func i2Int3(i I) Int {
+ y = 7
+ return i.(Int)
+}
+
+func TestIfaceConv4(t *testing.T) {
+ a := Int(5)
+ if got := i2Int4(a, &a); got != 5 {
+ t.Errorf("wanted 5, got %d\n", int(got))
+ }
+}
+
+//go:noinline
+func i2Int4(i I, p *Int) Int {
+ *p = 7
+ return i.(Int)
+}
+
+func BenchmarkEfaceInteger(b *testing.B) {
+ sum := 0
+ for i := 0; i < b.N; i++ {
+ sum += i2int(i)
+ }
+ sink = sum
+}
+
+//go:noinline
+func i2int(i interface{}) int {
+ return i.(int)
+}
diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go
index 5d5022fea7..6373b5d08e 100644
--- a/src/cmd/compile/internal/gc/walk.go
+++ b/src/cmd/compile/internal/gc/walk.go
@@ -1058,6 +1058,25 @@ opswitch:
n = l
break
}
+ // Optimize convT2{E,I} when T is not pointer-shaped.
+ // We make the interface by initializing a stack temporary to
+ // the value we want to put in the interface, then using the address of
+ // that stack temporary for the interface data word.
+ if !n.Left.Type.IsInterface() && n.Esc == EscNone && n.Left.Type.Width <= 1024 {
+ tmp := temp(n.Left.Type)
+ init.Append(typecheck(nod(OAS, tmp, n.Left), Etop))
+ var t *Node
+ if n.Type.IsEmptyInterface() {
+ t = typename(n.Left.Type)
+ } else {
+ t = itabname(n.Left.Type, n.Type)
+ }
+ l := nod(OEFACE, t, typecheck(nod(OADDR, tmp, nil), Erv))
+ l.Type = n.Type
+ l.Typecheck = n.Typecheck
+ n = l
+ break
+ }
var ll []*Node
if n.Type.IsEmptyInterface() {
@@ -1087,25 +1106,10 @@ opswitch:
ll = append(ll, nod(OADDR, copyexpr(n.Left, n.Left.Type, init), nil))
}
dowidth(n.Left.Type)
- r := nodnil()
- if n.Esc == EscNone && n.Left.Type.Width <= 1024 {
- // Allocate stack buffer for value stored in interface.
- r = temp(n.Left.Type)
- r = nod(OAS, r, nil) // zero temp
- r = typecheck(r, Etop)
- init.Append(r)
- r = nod(OADDR, r.Left, nil)
- r = typecheck(r, Erv)
- }
- ll = append(ll, r)
}
fn := syslook(convFuncName(n.Left.Type, n.Type))
- if !n.Left.Type.IsInterface() {
- fn = substArgTypes(fn, n.Left.Type, n.Left.Type, n.Type)
- } else {
- fn = substArgTypes(fn, n.Left.Type, n.Type)
- }
+ fn = substArgTypes(fn, n.Left.Type, n.Type)
dowidth(fn.Type)
n = nod(OCALL, fn, nil)
n.List.Set(ll)
diff --git a/src/runtime/iface.go b/src/runtime/iface.go
index 7f24a6e69c..476ec7e8b2 100644
--- a/src/runtime/iface.go
+++ b/src/runtime/iface.go
@@ -152,7 +152,7 @@ func itabsinit() {
unlock(&ifaceLock)
}
-func convT2E(t *_type, elem unsafe.Pointer, x unsafe.Pointer) (e eface) {
+func convT2E(t *_type, elem unsafe.Pointer) (e eface) {
if raceenabled {
raceReadObjectPC(t, elem, getcallerpc(unsafe.Pointer(&t)), funcPC(convT2E))
}
@@ -162,18 +162,16 @@ func convT2E(t *_type, elem unsafe.Pointer, x unsafe.Pointer) (e eface) {
if isDirectIface(t) {
throw("direct convT2E")
}
- if x == nil {
- x = newobject(t)
- // TODO: We allocate a zeroed object only to overwrite it with
- // actual data. Figure out how to avoid zeroing. Also below in convT2I.
- }
+ x := newobject(t)
+ // TODO: We allocate a zeroed object only to overwrite it with
+ // actual data. Figure out how to avoid zeroing. Also below in convT2I.
typedmemmove(t, x, elem)
e._type = t
e.data = x
return
}
-func convT2I(tab *itab, elem unsafe.Pointer, x unsafe.Pointer) (i iface) {
+func convT2I(tab *itab, elem unsafe.Pointer) (i iface) {
t := tab._type
if raceenabled {
raceReadObjectPC(t, elem, getcallerpc(unsafe.Pointer(&tab)), funcPC(convT2I))
@@ -184,9 +182,7 @@ func convT2I(tab *itab, elem unsafe.Pointer, x unsafe.Pointer) (i iface) {
if isDirectIface(t) {
throw("direct convT2I")
}
- if x == nil {
- x = newobject(t)
- }
+ x := newobject(t)
typedmemmove(t, x, elem)
i.tab = tab
i.data = x