From: Josh Bleecher Snyder Date: Sun, 7 Aug 2016 16:25:15 +0000 (-0700) Subject: go/types: remove struct Sizeof cache X-Git-Tag: go1.8beta1~1886 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=df9eeb192227257e8399c629372cd8cc79513406;p=gostls13.git 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 TryBot-Result: Gobot Gobot Reviewed-by: Robert Griesemer --- 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.