aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Bleecher Snyder <josharian@gmail.com>2016-08-07 09:25:15 -0700
committerJosh Bleecher Snyder <josharian@gmail.com>2016-08-16 00:21:27 +0000
commitdf9eeb192227257e8399c629372cd8cc79513406 (patch)
treec700c5a1c06cc55eb7f56db6550cc00fd3d8a07e
parent133d231a89c2d9f8bbceeb42cf47d8cd68fde357 (diff)
downloadgo-df9eeb192227257e8399c629372cd8cc79513406.tar.gz
go-df9eeb192227257e8399c629372cd8cc79513406.zip
go/types: remove struct Sizeof cache
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>
-rw-r--r--src/go/types/sizes.go38
-rw-r--r--src/go/types/sizes_test.go60
-rw-r--r--src/go/types/type.go11
3 files changed, 74 insertions, 35 deletions
diff --git a/src/go/types/sizes.go b/src/go/types/sizes.go
index 87c3ce4159..73d8274284 100644
--- a/src/go/types/sizes.go
+++ b/src/go/types/sizes.go
@@ -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
index 0000000000..e809a2b05c
--- /dev/null
+++ b/src/go/types/sizes_test.go
@@ -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)
+ }
+}
diff --git a/src/go/types/type.go b/src/go/types/type.go
index 4e00da3212..01adee8a3e 100644
--- a/src/go/types/type.go
+++ b/src/go/types/type.go
@@ -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.