]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: inline convT2{I,E} when result doesn't escape
authorKeith Randall <khr@golang.org>
Sat, 17 Sep 2016 22:04:36 +0000 (15:04 -0700)
committerKeith Randall <khr@golang.org>
Mon, 19 Sep 2016 02:37:08 +0000 (02:37 +0000)
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>
src/cmd/compile/internal/gc/builtin.go
src/cmd/compile/internal/gc/builtin/runtime.go
src/cmd/compile/internal/gc/fixedbugs_test.go
src/cmd/compile/internal/gc/iface_test.go [new file with mode: 0644]
src/cmd/compile/internal/gc/walk.go
src/runtime/iface.go
test/live.go

index cec02220ae54d53a8adfcf4cf05ff13ffb4926d1..e78b1ace742f5e09f21b28761f10d992146f296d 100644 (file)
@@ -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" +
index 762abbaf1cf54d4188b2fc29c5955e055df1e642..4d71e4eec3718e419f5fdcac5ac06a56abcf0a4c 100644 (file)
@@ -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)
index 19b1d9adf641c6bac5cf2741100b2637859a0a2a..095b816a5367beb95d55bf5ecd14c394e100d353 100644 (file)
@@ -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 (file)
index 0000000..21c6587
--- /dev/null
@@ -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)
+}
index 5d5022fea74eee0eee834389d0495cdca04b6b10..6373b5d08e25b69b1e4bd7a23010bdaca68a2d6a 100644 (file)
@@ -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)
index 7f24a6e69cccf7d7ec3b598279ca2f121c3e473d..476ec7e8b2591634ca338baa318c53537b7ef423 100644 (file)
@@ -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
index dabf82e8f215d144753edd9e7b3b79162e2cffef..2ae8b8f7b6d75d1a282e7c60433220e9005f5e60 100644 (file)
@@ -139,7 +139,9 @@ var i9 interface{}
 func f9() bool {
        g8()
        x := i9
-       return x != interface{}(99.0i) // ERROR "live at call to convT2E: x.data x.type$"
+       y := interface{}(99.0i) // ERROR "live at call to convT2E: x.data x.type$"
+       i9 = y                  // make y escape so the line above has to call convT2E
+       return x != y
 }
 
 // liveness formerly confused by UNDEF followed by RET,