]> Cypherpunks repositories - gostls13.git/commitdiff
go/types: remove struct Sizeof cache
authorJosh Bleecher Snyder <josharian@gmail.com>
Sun, 7 Aug 2016 16:25:15 +0000 (09:25 -0700)
committerJosh Bleecher Snyder <josharian@gmail.com>
Tue, 16 Aug 2016 00:21:27 +0000 (00:21 +0000)
It was not responsive to the sizes param.
Remove it, and unwind the extra layers.

Fixes #16316

Change-Id: I940a57184a1601f52348d4bff8638f3f7462f5cd
Reviewed-on: https://go-review.googlesource.com/26995
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
src/go/types/sizes.go
src/go/types/sizes_test.go [new file with mode: 0644]
src/go/types/type.go

index 87c3ce4159767db25b4746083f4c446366faa1ff..73d827428484ccf785267bfd9a3bce6503e43461 100644 (file)
@@ -132,8 +132,8 @@ func (s *StdSizes) Sizeof(T Type) int64 {
                if n == 0 {
                        return 0
                }
-               setOffsets(t, s)
-               return t.offsets[n-1] + s.Sizeof(t.fields[n-1].typ)
+               offsets := s.Offsetsof(t.fields)
+               return offsets[n-1] + s.Sizeof(t.fields[n-1].typ)
        case *Interface:
                return s.WordSize * 2
        }
@@ -158,22 +158,18 @@ func (conf *Config) offsetsof(T *Struct) []int64 {
        if T.NumFields() > 0 {
                // compute offsets on demand
                if s := conf.Sizes; s != nil {
-                       calculated := setOffsets(T, s)
-                       offsets = T.offsets
-                       if calculated {
-                               // sanity checks
-                               if len(offsets) != T.NumFields() {
-                                       panic("Config.Sizes.Offsetsof returned the wrong number of offsets")
-                               }
-                               for _, o := range offsets {
-                                       if o < 0 {
-                                               panic("Config.Sizes.Offsetsof returned an offset < 0")
-                                       }
+                       offsets := s.Offsetsof(T.fields)
+                       // sanity checks
+                       if len(offsets) != T.NumFields() {
+                               panic("Config.Sizes.Offsetsof returned the wrong number of offsets")
+                       }
+                       for _, o := range offsets {
+                               if o < 0 {
+                                       panic("Config.Sizes.Offsetsof returned an offset < 0")
                                }
                        }
                } else {
-                       setOffsets(T, &stdSizes)
-                       offsets = T.offsets
+                       offsets = stdSizes.Offsetsof(T.fields)
                }
        }
        return offsets
@@ -207,15 +203,3 @@ func align(x, a int64) int64 {
        y := x + a - 1
        return y - y%a
 }
-
-// setOffsets sets the offsets of s for the given sizes if necessary.
-// The result is true if the offsets were not set before; otherwise it
-// is false.
-func setOffsets(s *Struct, sizes Sizes) bool {
-       var calculated bool
-       s.offsetsOnce.Do(func() {
-               calculated = true
-               s.offsets = sizes.Offsetsof(s.fields)
-       })
-       return calculated
-}
diff --git a/src/go/types/sizes_test.go b/src/go/types/sizes_test.go
new file mode 100644 (file)
index 0000000..e809a2b
--- /dev/null
@@ -0,0 +1,60 @@
+// 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.
+
+// This file contains tests for sizes.
+
+package types_test
+
+import (
+       "go/ast"
+       "go/parser"
+       "go/token"
+       "go/types"
+       "testing"
+)
+
+// findStructType typechecks src and returns the first struct type encountered.
+func findStructType(t *testing.T, src string) *types.Struct {
+       fset := token.NewFileSet()
+       f, err := parser.ParseFile(fset, "x.go", src, 0)
+       if err != nil {
+               t.Fatal(err)
+       }
+       info := types.Info{Types: make(map[ast.Expr]types.TypeAndValue)}
+       var conf types.Config
+       _, err = conf.Check("x", fset, []*ast.File{f}, &info)
+       if err != nil {
+               t.Fatal(err)
+       }
+       for _, tv := range info.Types {
+               if ts, ok := tv.Type.(*types.Struct); ok {
+                       return ts
+               }
+       }
+       t.Fatalf("failed to find a struct type in src:\n%s\n", src)
+       return nil
+}
+
+// Issue 16316
+func TestMultipleSizeUse(t *testing.T) {
+       const src = `
+package main
+
+type S struct {
+    i int
+    b bool
+    s string
+    n int
+}
+`
+       ts := findStructType(t, src)
+       sizes := types.StdSizes{WordSize: 4, MaxAlign: 4}
+       if got := sizes.Sizeof(ts); got != 20 {
+               t.Errorf("Sizeof(%v) with WordSize 4 = %d want 20", ts, got)
+       }
+       sizes = types.StdSizes{WordSize: 8, MaxAlign: 8}
+       if got := sizes.Sizeof(ts); got != 40 {
+               t.Errorf("Sizeof(%v) with WordSize 8 = %d want 40", ts, got)
+       }
+}
index 4e00da3212ffa1ad7ce279cca9f8353a7530457a..01adee8a3ef471438a428f9d2358436ab4b0f5ce 100644 (file)
@@ -4,10 +4,7 @@
 
 package types
 
-import (
-       "sort"
-       "sync"
-)
+import "sort"
 
 // A Type represents a type of Go.
 // All types implement the Type interface.
@@ -121,10 +118,8 @@ func (s *Slice) Elem() Type { return s.elem }
 
 // A Struct represents a struct type.
 type Struct struct {
-       fields      []*Var
-       tags        []string  // field tags; nil if there are no tags
-       offsets     []int64   // field offsets in bytes, lazily initialized
-       offsetsOnce sync.Once // for threadsafe lazy initialization of offsets
+       fields []*Var
+       tags   []string // field tags; nil if there are no tags
 }
 
 // NewStruct returns a new struct with the given fields and corresponding field tags.