]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: refactor onebitwalktype1
authorMatthew Dempsky <mdempsky@google.com>
Tue, 19 Sep 2017 06:29:46 +0000 (23:29 -0700)
committerMatthew Dempsky <mdempsky@google.com>
Wed, 20 Sep 2017 18:11:52 +0000 (18:11 +0000)
The existing logic tried to advance the offset for each variable's
width, but then tried to undo this logic with the array and struct
handling code. It can all be much simpler by only worrying about
computing offsets within the array and struct code.

While here, include a short-circuit for zero-width arrays to fix a
pedantic compiler failure case.

Passes toolstash-check.

Fixes #20739.

Change-Id: I98af9bb512a33e3efe82b8bf1803199edb480640
Reviewed-on: https://go-review.googlesource.com/64471
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
src/cmd/compile/internal/gc/pgen.go
src/cmd/compile/internal/gc/plive.go
src/cmd/compile/internal/gc/reflect.go
test/fixedbugs/issue20739.go [new file with mode: 0644]

index 54fdb30d108ee15f9b7d682f9da2e7d1189ef81c..417f1ba716759a455d191008ff311249fc27eb5c 100644 (file)
@@ -42,21 +42,17 @@ func emitptrargsmap() {
        }
        off := duint32(lsym, 0, uint32(nbitmap))
        off = duint32(lsym, off, uint32(bv.n))
-       var xoffset int64
+
        if Curfn.IsMethod() {
-               xoffset = 0
-               onebitwalktype1(Curfn.Type.Recvs(), &xoffset, bv)
+               onebitwalktype1(Curfn.Type.Recvs(), 0, bv)
        }
-
        if Curfn.Type.NumParams() > 0 {
-               xoffset = 0
-               onebitwalktype1(Curfn.Type.Params(), &xoffset, bv)
+               onebitwalktype1(Curfn.Type.Params(), 0, bv)
        }
-
        off = dbvec(lsym, off, bv)
+
        if Curfn.Type.NumResults() > 0 {
-               xoffset = 0
-               onebitwalktype1(Curfn.Type.Results(), &xoffset, bv)
+               onebitwalktype1(Curfn.Type.Results(), 0, bv)
                off = dbvec(lsym, off, bv)
        }
 
index c3bc753d078dbf112dc754deefa83a5ae5862eee..57295a72772080c79a465c4404e6278396f7bbe5 100644 (file)
@@ -355,85 +355,63 @@ func (lv *Liveness) blockEffects(b *ssa.Block) *BlockEffects {
 // and then simply copied into bv at the correct offset on future calls with
 // the same type t. On https://rsc.googlecode.com/hg/testdata/slow.go, onebitwalktype1
 // accounts for 40% of the 6g execution time.
-func onebitwalktype1(t *types.Type, xoffset *int64, bv bvec) {
-       if t.Align > 0 && *xoffset&int64(t.Align-1) != 0 {
+func onebitwalktype1(t *types.Type, off int64, bv bvec) {
+       if t.Align > 0 && off&int64(t.Align-1) != 0 {
                Fatalf("onebitwalktype1: invalid initial alignment, %v", t)
        }
 
        switch t.Etype {
-       case TINT8,
-               TUINT8,
-               TINT16,
-               TUINT16,
-               TINT32,
-               TUINT32,
-               TINT64,
-               TUINT64,
-               TINT,
-               TUINT,
-               TUINTPTR,
-               TBOOL,
-               TFLOAT32,
-               TFLOAT64,
-               TCOMPLEX64,
-               TCOMPLEX128:
-               *xoffset += t.Width
+       case TINT8, TUINT8, TINT16, TUINT16,
+               TINT32, TUINT32, TINT64, TUINT64,
+               TINT, TUINT, TUINTPTR, TBOOL,
+               TFLOAT32, TFLOAT64, TCOMPLEX64, TCOMPLEX128:
 
-       case TPTR32,
-               TPTR64,
-               TUNSAFEPTR,
-               TFUNC,
-               TCHAN,
-               TMAP:
-               if *xoffset&int64(Widthptr-1) != 0 {
+       case TPTR32, TPTR64, TUNSAFEPTR, TFUNC, TCHAN, TMAP:
+               if off&int64(Widthptr-1) != 0 {
                        Fatalf("onebitwalktype1: invalid alignment, %v", t)
                }
-               bv.Set(int32(*xoffset / int64(Widthptr))) // pointer
-               *xoffset += t.Width
+               bv.Set(int32(off / int64(Widthptr))) // pointer
 
        case TSTRING:
                // struct { byte *str; intgo len; }
-               if *xoffset&int64(Widthptr-1) != 0 {
+               if off&int64(Widthptr-1) != 0 {
                        Fatalf("onebitwalktype1: invalid alignment, %v", t)
                }
-               bv.Set(int32(*xoffset / int64(Widthptr))) //pointer in first slot
-               *xoffset += t.Width
+               bv.Set(int32(off / int64(Widthptr))) //pointer in first slot
 
        case TINTER:
                // struct { Itab *tab;  void *data; }
                // or, when isnilinter(t)==true:
                // struct { Type *type; void *data; }
-               if *xoffset&int64(Widthptr-1) != 0 {
+               if off&int64(Widthptr-1) != 0 {
                        Fatalf("onebitwalktype1: invalid alignment, %v", t)
                }
-               bv.Set(int32(*xoffset / int64(Widthptr)))   // pointer in first slot
-               bv.Set(int32(*xoffset/int64(Widthptr) + 1)) // pointer in second slot
-               *xoffset += t.Width
+               bv.Set(int32(off / int64(Widthptr)))   // pointer in first slot
+               bv.Set(int32(off/int64(Widthptr) + 1)) // pointer in second slot
 
        case TSLICE:
                // struct { byte *array; uintgo len; uintgo cap; }
-               if *xoffset&int64(Widthptr-1) != 0 {
+               if off&int64(Widthptr-1) != 0 {
                        Fatalf("onebitwalktype1: invalid TARRAY alignment, %v", t)
                }
-               bv.Set(int32(*xoffset / int64(Widthptr))) // pointer in first slot (BitsPointer)
-               *xoffset += t.Width
+               bv.Set(int32(off / int64(Widthptr))) // pointer in first slot (BitsPointer)
 
        case TARRAY:
+               elt := t.Elem()
+               if elt.Width == 0 {
+                       // Short-circuit for #20739.
+                       break
+               }
                for i := int64(0); i < t.NumElem(); i++ {
-                       onebitwalktype1(t.Elem(), xoffset, bv)
+                       onebitwalktype1(elt, off, bv)
+                       off += elt.Width
                }
 
        case TSTRUCT:
-               var o int64
-               for _, t1 := range t.Fields().Slice() {
-                       fieldoffset := t1.Offset
-                       *xoffset += fieldoffset - o
-                       onebitwalktype1(t1.Type, xoffset, bv)
-                       o = fieldoffset + t1.Type.Width
+               for _, f := range t.Fields().Slice() {
+                       onebitwalktype1(f.Type, off+f.Offset, bv)
                }
 
-               *xoffset += t.Width - o
-
        default:
                Fatalf("onebitwalktype1: unexpected type, %v", t)
        }
@@ -453,8 +431,6 @@ func argswords(lv *Liveness) int32 {
 // this argument and the in arguments are always assumed live. The vars
 // argument is a slice of *Nodes.
 func onebitlivepointermap(lv *Liveness, liveout bvec, vars []*Node, args bvec, locals bvec) {
-       var xoffset int64
-
        for i := int32(0); ; i++ {
                i = liveout.Next(i)
                if i < 0 {
@@ -463,12 +439,10 @@ func onebitlivepointermap(lv *Liveness, liveout bvec, vars []*Node, args bvec, l
                node := vars[i]
                switch node.Class() {
                case PAUTO:
-                       xoffset = node.Xoffset + lv.stkptrsize
-                       onebitwalktype1(node.Type, &xoffset, locals)
+                       onebitwalktype1(node.Type, node.Xoffset+lv.stkptrsize, locals)
 
                case PPARAM, PPARAMOUT:
-                       xoffset = node.Xoffset
-                       onebitwalktype1(node.Type, &xoffset, args)
+                       onebitwalktype1(node.Type, node.Xoffset, args)
                }
        }
 }
index 0bc0c53631bb1fc6e1910163b198a2a51bd3006d..d268c89e69a057e1b5e4615db49a623ae504244f 100644 (file)
@@ -1774,8 +1774,7 @@ func fillptrmask(t *types.Type, ptrmask []byte) {
        }
 
        vec := bvalloc(8 * int32(len(ptrmask)))
-       xoffset := int64(0)
-       onebitwalktype1(t, &xoffset, vec)
+       onebitwalktype1(t, 0, vec)
 
        nptr := typeptrdata(t) / int64(Widthptr)
        for i := int64(0); i < nptr; i++ {
diff --git a/test/fixedbugs/issue20739.go b/test/fixedbugs/issue20739.go
new file mode 100644 (file)
index 0000000..b71a25d
--- /dev/null
@@ -0,0 +1,16 @@
+// compile
+
+// Copyright 2017 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 p
+
+func F() {
+       var x struct {
+               x *int
+               w [1e9][1e9][1e9][0]*int
+               y *int
+       }
+       println(&x)
+}