]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: skip convT2E for empty structs
authorJosh Bleecher Snyder <josharian@gmail.com>
Sun, 22 Jan 2017 18:17:12 +0000 (10:17 -0800)
committerJosh Bleecher Snyder <josharian@gmail.com>
Thu, 2 Feb 2017 21:06:28 +0000 (21:06 +0000)
Fixes #18402

Change-Id: I5af800857fb2e365ce4224eece9171277106ec7d
Reviewed-on: https://go-review.googlesource.com/35562
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
src/cmd/compile/internal/gc/go.go
src/cmd/compile/internal/gc/walk.go

index 7c205f43c499a38f79b3813f39166c5c80e5eb01..22e64b3764c79351b00dcce34ca6e69790f8a02d 100644 (file)
@@ -365,6 +365,7 @@ var Thearch Arch
 
 var (
        staticbytes,
+       zerobase,
        Newproc,
        Deferproc,
        Deferreturn,
index 148e629bd0c8836252b0e0dee4b493e504eb969d..c57d15c2a1a21842e4881237125c15f90ec6bb78 100644 (file)
@@ -894,26 +894,35 @@ opswitch:
                        staticbytes = newname(Pkglookup("staticbytes", Runtimepkg))
                        staticbytes.Class = PEXTERN
                        staticbytes.Type = typArray(Types[TUINT8], 256)
+                       zerobase = newname(Pkglookup("zerobase", Runtimepkg))
+                       zerobase.Class = PEXTERN
+                       zerobase.Type = Types[TUINTPTR]
                }
 
-               // Optimize convT2{E,I} when T is not pointer-shaped,
-               // but the value does not escape or is a readonly global or is a bool/byte.
+               // Optimize convT2{E,I} for many cases in which T is not pointer-shaped,
+               // by using an existing addressable value identical to n.Left
+               // or creating one on the stack.
                var value *Node
                switch {
-               case !n.Left.Type.IsInterface() && n.Esc == EscNone && n.Left.Type.Width <= 1024:
-                       // 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.
-                       value = temp(n.Left.Type)
-                       init.Append(typecheck(nod(OAS, value, n.Left), Etop))
-               case n.Left.Class == PEXTERN && n.Left.Name != nil && n.Left.Name.Readonly:
-                       // readonly global; use directly.
-                       value = n.Left
+               case n.Left.Type.Size() == 0:
+                       // n.Left is zero-sized. Use zerobase.
+                       value = zerobase
                case n.Left.Type.IsBoolean() || (n.Left.Type.Size() == 1 && n.Left.Type.IsInteger()):
+                       // n.Left is a bool/byte. Use staticbytes[n.Left].
                        value = nod(OINDEX, staticbytes, byteindex(n.Left))
                        value.Bounded = true
+               case n.Left.Class == PEXTERN && n.Left.Name != nil && n.Left.Name.Readonly:
+                       // n.Left is a readonly global; use it directly.
+                       value = n.Left
+               case !n.Left.Type.IsInterface() && n.Esc == EscNone && n.Left.Type.Width <= 1024:
+                       // n.Left does not escape. Use a stack temporary initialized to n.Left.
+                       value = temp(n.Left.Type)
+                       init.Append(typecheck(nod(OAS, value, n.Left), Etop))
                }
 
                if value != nil {
+                       // Value is identical to n.Left.
+                       // Construct the interface directly: {type/itab, &value}.
                        var t *Node
                        if n.Type.IsEmptyInterface() {
                                t = typename(n.Left.Type)