Commit c5decc83 by Ian Lance Taylor

libgo: update to final Go1.14 release

Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/221158
parent 051b9873
658fe4f48374167bf8688e8dbd5f85eee155749e 5fc21bb0d91d916940c21e6d4a3e10ad3f45343d
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the gofrontend repository. merge done from the gofrontend repository.
a068054af141c01df5a4519844f4b77273605f4e 20a838ab94178c55bc4dc23ddc332fce8545a493
The first line of this file holds the git revision number of the The first line of this file holds the git revision number of the
last merge done from the master library sources. last merge done from the master library sources.
...@@ -7,7 +7,6 @@ package modcmd ...@@ -7,7 +7,6 @@ package modcmd
import ( import (
"cmd/go/internal/base" "cmd/go/internal/base"
"cmd/go/internal/cfg"
) )
var CmdMod = &base.Command{ var CmdMod = &base.Command{
...@@ -32,7 +31,3 @@ See 'go help modules' for an overview of module functionality. ...@@ -32,7 +31,3 @@ See 'go help modules' for an overview of module functionality.
cmdWhy, cmdWhy,
}, },
} }
func addModFlags(cmd *base.Command) {
cmd.Flag.StringVar(&cfg.ModFile, "modfile", "", "")
}
...@@ -184,9 +184,10 @@ func Import(path string) (m module.Version, dir string, err error) { ...@@ -184,9 +184,10 @@ func Import(path string) (m module.Version, dir string, err error) {
if !pathIsStd { if !pathIsStd {
if cfg.BuildModReason == "" { if cfg.BuildModReason == "" {
queryErr = fmt.Errorf("import lookup disabled by -mod=%s", cfg.BuildMod) queryErr = fmt.Errorf("import lookup disabled by -mod=%s", cfg.BuildMod)
} } else {
queryErr = fmt.Errorf("import lookup disabled by -mod=%s\n\t(%s)", cfg.BuildMod, cfg.BuildModReason) queryErr = fmt.Errorf("import lookup disabled by -mod=%s\n\t(%s)", cfg.BuildMod, cfg.BuildModReason)
} }
}
return module.Version{}, "", &ImportMissingError{Path: path, QueryErr: queryErr} return module.Version{}, "", &ImportMissingError{Path: path, QueryErr: queryErr}
} }
if modRoot == "" && !allowMissingModuleImports { if modRoot == "" && !allowMissingModuleImports {
......
...@@ -51,7 +51,9 @@ func runVet(cmd *base.Command, args []string) { ...@@ -51,7 +51,9 @@ func runVet(cmd *base.Command, args []string) {
work.BuildInit() work.BuildInit()
work.VetFlags = vetFlags work.VetFlags = vetFlags
if len(vetFlags) > 0 {
work.VetExplicit = true work.VetExplicit = true
}
if vetTool != "" { if vetTool != "" {
var err error var err error
work.VetTool, err = filepath.Abs(vetTool) work.VetTool, err = filepath.Abs(vetTool)
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// Package web defines minimal helper routines for accessing HTTP/HTTPS // Package web defines minimal helper routines for accessing HTTP/HTTPS
// resources without requiring external dependenicies on the net package. // resources without requiring external dependencies on the net package.
// //
// If the cmd_go_bootstrap build tag is present, web avoids the use of the net // If the cmd_go_bootstrap build tag is present, web avoids the use of the net
// package and returns errors for all network operations. // package and returns errors for all network operations.
......
...@@ -2,49 +2,67 @@ ...@@ -2,49 +2,67 @@
# go/build's Import should find modules by invoking the go command # go/build's Import should find modules by invoking the go command
go build -o $WORK/testimport.exe ./testimport go build -o $WORK ./testimport ./testfindonly
# GO111MODULE=off # GO111MODULE=off
env GO111MODULE=off env GO111MODULE=off
! exec $WORK/testimport.exe gobuild.example.com/x/y/z/w . ! exec $WORK/testimport$GOEXE gobuild.example.com/x/y/z/w .
# GO111MODULE=auto in GOPATH/src # GO111MODULE=auto in GOPATH/src
env GO111MODULE=auto env GO111MODULE=auto
exec $WORK/testimport.exe gobuild.example.com/x/y/z/w . exec $WORK/testimport$GOEXE gobuild.example.com/x/y/z/w .
# GO111MODULE=auto outside GOPATH/src # GO111MODULE=auto outside GOPATH/src
cd $GOPATH/other cd $GOPATH/other
env GO111MODULE=auto env GO111MODULE=auto
exec $WORK/testimport.exe other/x/y/z/w . exec $WORK/testimport$GOEXE other/x/y/z/w .
stdout w2.go stdout w2.go
! exec $WORK/testimport.exe gobuild.example.com/x/y/z/w . ! exec $WORK/testimport$GOEXE gobuild.example.com/x/y/z/w .
stderr 'cannot find module providing package gobuild.example.com/x/y/z/w' stderr 'cannot find module providing package gobuild.example.com/x/y/z/w'
cd z cd z
exec $WORK/testimport.exe other/x/y/z/w . exec $WORK/testimport$GOEXE other/x/y/z/w .
stdout w2.go stdout w2.go
# GO111MODULE=on outside GOPATH/src # GO111MODULE=on outside GOPATH/src
env GO111MODULE= env GO111MODULE=
exec $WORK/testimport.exe other/x/y/z/w . exec $WORK/testimport$GOEXE other/x/y/z/w .
stdout w2.go stdout w2.go
env GO111MODULE=on env GO111MODULE=on
exec $WORK/testimport.exe other/x/y/z/w . exec $WORK/testimport$GOEXE other/x/y/z/w .
stdout w2.go stdout w2.go
# GO111MODULE=on in GOPATH/src # GO111MODULE=on in GOPATH/src
cd $GOPATH/src cd $GOPATH/src
env GO111MODULE= env GO111MODULE=
exec $WORK/testimport.exe gobuild.example.com/x/y/z/w . exec $WORK/testimport$GOEXE gobuild.example.com/x/y/z/w .
stdout w1.go stdout w1.go
env GO111MODULE=on env GO111MODULE=on
exec $WORK/testimport.exe gobuild.example.com/x/y/z/w . exec $WORK/testimport$GOEXE gobuild.example.com/x/y/z/w .
stdout w1.go stdout w1.go
cd w cd w
exec $WORK/testimport.exe gobuild.example.com/x/y/z/w .. exec $WORK/testimport$GOEXE gobuild.example.com/x/y/z/w ..
stdout w1.go stdout w1.go
# go/build's Import in FindOnly mode should find directories by invoking the go command
#
# Calling build.Import in build.FindOnly mode on an import path of a Go package
# that produces errors when loading (e.g., due to build constraints not matching
# the current build context) should return the package directory and nil error.
# Issue 31603: Import with non-empty srcDir should work.
env GO111MODULE=on
exec $WORK/testfindonly$GOEXE gobuild.example.com/x/y/z/i $WORK
! stdout 'build constraints'
stdout '^dir=\$WORK.+i err=<nil>$'
# Issue 37153: Import with empty srcDir should work.
env GO111MODULE=on
exec $WORK/testfindonly$GOEXE gobuild.example.com/x/y/z/i ''
! stdout 'build constraints'
stdout '^dir=\$WORK.+i err=<nil>$'
-- go.mod -- -- go.mod --
module gobuild.example.com/x/y/z module gobuild.example.com/x/y/z
...@@ -54,6 +72,11 @@ package z ...@@ -54,6 +72,11 @@ package z
-- w/w1.go -- -- w/w1.go --
package w package w
-- i/i.go --
// +build i
package i
-- testimport/x.go -- -- testimport/x.go --
package main package main
...@@ -89,6 +112,20 @@ func main() { ...@@ -89,6 +112,20 @@ func main() {
fmt.Printf("%s\n%s\n", p1.Dir, strings.Join(p1.GoFiles, " ")) fmt.Printf("%s\n%s\n", p1.Dir, strings.Join(p1.GoFiles, " "))
} }
-- testfindonly/x.go --
package main
import (
"fmt"
"go/build"
"os"
)
func main() {
p, err := build.Import(os.Args[1], os.Args[2], build.FindOnly)
fmt.Printf("dir=%s err=%v\n", p.Dir, err)
}
-- $GOPATH/other/go.mod -- -- $GOPATH/other/go.mod --
module other/x/y module other/x/y
......
...@@ -7,6 +7,7 @@ go mod edit -fmt ...@@ -7,6 +7,7 @@ go mod edit -fmt
cp go.mod go.mod.empty cp go.mod go.mod.empty
! go list all ! go list all
stderr '^can''t load package: x.go:2:8: cannot find module providing package rsc\.io/quote: import lookup disabled by -mod=readonly' stderr '^can''t load package: x.go:2:8: cannot find module providing package rsc\.io/quote: import lookup disabled by -mod=readonly'
! stderr '\(\)' # If we don't have a reason for -mod=readonly, don't log an empty one.
cmp go.mod go.mod.empty cmp go.mod go.mod.empty
# -mod=readonly should be set implicitly if the go.mod file is read-only # -mod=readonly should be set implicitly if the go.mod file is read-only
......
...@@ -9,6 +9,17 @@ go vet -n -unreachable=false encoding/binary ...@@ -9,6 +9,17 @@ go vet -n -unreachable=false encoding/binary
stderr '-unreachable=false' stderr '-unreachable=false'
! stderr '-unsafeptr=false' ! stderr '-unsafeptr=false'
# Issue 37030: "go vet <std package>" without other flags should disable the
# unsafeptr check by default.
go vet -n encoding/binary
stderr '-unsafeptr=false'
! stderr '-unreachable=false'
# However, it should be enabled if requested explicitly.
go vet -n -unsafeptr encoding/binary
stderr '-unsafeptr'
! stderr '-unsafeptr=false'
[short] stop [short] stop
env GOCACHE=$WORK/gocache env GOCACHE=$WORK/gocache
env GOTMPDIR=$WORK/tmp env GOTMPDIR=$WORK/tmp
......
...@@ -86,7 +86,8 @@ func NewGCM(cipher Block) (AEAD, error) { ...@@ -86,7 +86,8 @@ func NewGCM(cipher Block) (AEAD, error) {
} }
// NewGCMWithNonceSize returns the given 128-bit, block cipher wrapped in Galois // NewGCMWithNonceSize returns the given 128-bit, block cipher wrapped in Galois
// Counter Mode, which accepts nonces of the given length. // Counter Mode, which accepts nonces of the given length. The length must not
// be zero.
// //
// Only use this function if you require compatibility with an existing // Only use this function if you require compatibility with an existing
// cryptosystem that uses non-standard nonce lengths. All other users should use // cryptosystem that uses non-standard nonce lengths. All other users should use
...@@ -112,6 +113,10 @@ func newGCMWithNonceAndTagSize(cipher Block, nonceSize, tagSize int) (AEAD, erro ...@@ -112,6 +113,10 @@ func newGCMWithNonceAndTagSize(cipher Block, nonceSize, tagSize int) (AEAD, erro
return nil, errors.New("cipher: incorrect tag size given to GCM") return nil, errors.New("cipher: incorrect tag size given to GCM")
} }
if nonceSize <= 0 {
return nil, errors.New("cipher: the nonce can't have zero length, or the security of the key will be immediately compromised")
}
if cipher, ok := cipher.(gcmAble); ok { if cipher, ok := cipher.(gcmAble); ok {
return cipher.NewGCM(nonceSize, tagSize) return cipher.NewGCM(nonceSize, tagSize)
} }
......
...@@ -217,6 +217,13 @@ var aesGCMTests = []struct { ...@@ -217,6 +217,13 @@ var aesGCMTests = []struct {
"2b9680b886b3efb7c6354b38c63b5373", "2b9680b886b3efb7c6354b38c63b5373",
"e2b7e5ed5ff27fc8664148f5a628a46dcbf2015184fffb82f2651c36", "e2b7e5ed5ff27fc8664148f5a628a46dcbf2015184fffb82f2651c36",
}, },
{
"11754cd72aec309bf52f7687212e8957",
"",
"",
"",
"250327c674aaf477aef2675748cf6971",
},
} }
func TestAESGCM(t *testing.T) { func TestAESGCM(t *testing.T) {
...@@ -234,14 +241,22 @@ func TestAESGCM(t *testing.T) { ...@@ -234,14 +241,22 @@ func TestAESGCM(t *testing.T) {
var aesgcm cipher.AEAD var aesgcm cipher.AEAD
switch { switch {
// Handle non-standard nonce sizes // Handle non-standard tag sizes
case tagSize != 16: case tagSize != 16:
aesgcm, err = cipher.NewGCMWithTagSize(aes, tagSize) aesgcm, err = cipher.NewGCMWithTagSize(aes, tagSize)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
// Handle non-standard tag sizes // Handle 0 nonce size (expect error and continue)
case len(nonce) == 0:
aesgcm, err = cipher.NewGCMWithNonceSize(aes, 0)
if err == nil {
t.Fatal("expected error for zero nonce size")
}
continue
// Handle non-standard nonce sizes
case len(nonce) != 12: case len(nonce) != 12:
aesgcm, err = cipher.NewGCMWithNonceSize(aes, len(nonce)) aesgcm, err = cipher.NewGCMWithNonceSize(aes, len(nonce))
if err != nil { if err != nil {
......
...@@ -372,7 +372,12 @@ func initP521() { ...@@ -372,7 +372,12 @@ func initP521() {
p521.BitSize = 521 p521.BitSize = 521
} }
// P256 returns a Curve which implements P-256 (see FIPS 186-3, section D.2.3) // P256 returns a Curve which implements NIST P-256 (FIPS 186-3, section D.2.3),
// also known as secp256r1 or prime256v1. The CurveParams.Name of this Curve is
// "P-256".
//
// Multiple invocations of this function will return the same value, so it can
// be used for equality checks and switch statements.
// //
// The cryptographic operations are implemented using constant-time algorithms. // The cryptographic operations are implemented using constant-time algorithms.
func P256() Curve { func P256() Curve {
...@@ -380,7 +385,11 @@ func P256() Curve { ...@@ -380,7 +385,11 @@ func P256() Curve {
return p256 return p256
} }
// P384 returns a Curve which implements P-384 (see FIPS 186-3, section D.2.4) // P384 returns a Curve which implements NIST P-384 (FIPS 186-3, section D.2.4),
// also known as secp384r1. The CurveParams.Name of this Curve is "P-384".
//
// Multiple invocations of this function will return the same value, so it can
// be used for equality checks and switch statements.
// //
// The cryptographic operations do not use constant-time algorithms. // The cryptographic operations do not use constant-time algorithms.
func P384() Curve { func P384() Curve {
...@@ -388,7 +397,11 @@ func P384() Curve { ...@@ -388,7 +397,11 @@ func P384() Curve {
return p384 return p384
} }
// P521 returns a Curve which implements P-521 (see FIPS 186-3, section D.2.5) // P521 returns a Curve which implements NIST P-521 (FIPS 186-3, section D.2.5),
// also known as secp521r1. The CurveParams.Name of this Curve is "P-521".
//
// Multiple invocations of this function will return the same value, so it can
// be used for equality checks and switch statements.
// //
// The cryptographic operations do not use constant-time algorithms. // The cryptographic operations do not use constant-time algorithms.
func P521() Curve { func P521() Curve {
......
...@@ -79,7 +79,7 @@ func ParsePKCS8PrivateKey(der []byte) (key interface{}, err error) { ...@@ -79,7 +79,7 @@ func ParsePKCS8PrivateKey(der []byte) (key interface{}, err error) {
} }
} }
// MarshalPKCS8PrivateKey converts an RSA private key to PKCS#8, ASN.1 DER form. // MarshalPKCS8PrivateKey converts a private key to PKCS#8, ASN.1 DER form.
// //
// The following key types are currently supported: *rsa.PrivateKey, *ecdsa.PrivateKey // The following key types are currently supported: *rsa.PrivateKey, *ecdsa.PrivateKey
// and ed25519.PrivateKey. Unsupported key types result in an error. // and ed25519.PrivateKey. Unsupported key types result in an error.
......
...@@ -1017,8 +1017,6 @@ var errNoModules = errors.New("not using modules") ...@@ -1017,8 +1017,6 @@ var errNoModules = errors.New("not using modules")
// Then we reinvoke it for every dependency. But this is still better than not working at all. // Then we reinvoke it for every dependency. But this is still better than not working at all.
// See golang.org/issue/26504. // See golang.org/issue/26504.
func (ctxt *Context) importGo(p *Package, path, srcDir string, mode ImportMode) error { func (ctxt *Context) importGo(p *Package, path, srcDir string, mode ImportMode) error {
const debugImportGo = false
// To invoke the go command, // To invoke the go command,
// we must not being doing special things like AllowBinary or IgnoreVendor, // we must not being doing special things like AllowBinary or IgnoreVendor,
// and all the file system callbacks must be nil (we're meant to use the local file system). // and all the file system callbacks must be nil (we're meant to use the local file system).
...@@ -1137,15 +1135,15 @@ func (ctxt *Context) importGo(p *Package, path, srcDir string, mode ImportMode) ...@@ -1137,15 +1135,15 @@ func (ctxt *Context) importGo(p *Package, path, srcDir string, mode ImportMode)
} }
dir := f[0] dir := f[0]
errStr := strings.TrimSpace(f[4]) errStr := strings.TrimSpace(f[4])
if errStr != "" && p.Dir == "" { if errStr != "" && dir == "" {
// If 'go list' could not locate the package, return the same error that // If 'go list' could not locate the package (dir is empty),
// 'go list' reported. // return the same error that 'go list' reported.
// If 'go list' did locate the package (p.Dir is not empty), ignore the
// error. It was probably related to loading source files, and we'll
// encounter it ourselves shortly.
return errors.New(errStr) return errors.New(errStr)
} }
// If 'go list' did locate the package, ignore the error.
// It was probably related to loading source files, and we'll
// encounter it ourselves shortly if the FindOnly flag isn't set.
p.Dir = dir p.Dir = dir
p.ImportPath = f[1] p.ImportPath = f[1]
p.Root = f[2] p.Root = f[2]
......
...@@ -138,9 +138,12 @@ func New(pkg *ast.Package, importPath string, mode Mode) *Package { ...@@ -138,9 +138,12 @@ func New(pkg *ast.Package, importPath string, mode Mode) *Package {
// NewFromFiles computes documentation for a package. // NewFromFiles computes documentation for a package.
// //
// The package is specified by a list of *ast.Files and corresponding // The package is specified by a list of *ast.Files and corresponding
// file set, which must not be nil. NewFromFiles does not skip files // file set, which must not be nil.
// based on build constraints, so it is the caller's responsibility to // NewFromFiles uses all provided files when computing documentation,
// provide only the files that are matched by the build context. // so it is the caller's responsibility to provide only the files that
// match the desired build context. "go/build".Context.MatchFile can
// be used for determining whether a file matches a build context with
// the desired GOOS and GOARCH values, and other build constraints.
// The import path of the package is specified by importPath. // The import path of the package is specified by importPath.
// //
// Examples found in _test.go files are associated with the corresponding // Examples found in _test.go files are associated with the corresponding
......
...@@ -5,10 +5,13 @@ ...@@ -5,10 +5,13 @@
// Package maphash provides hash functions on byte sequences. // Package maphash provides hash functions on byte sequences.
// These hash functions are intended to be used to implement hash tables or // These hash functions are intended to be used to implement hash tables or
// other data structures that need to map arbitrary strings or byte // other data structures that need to map arbitrary strings or byte
// sequences to a uniform distribution of integers. // sequences to a uniform distribution on unsigned 64-bit integers.
// //
// The hash functions are collision-resistant but not cryptographically secure. // The hash functions are collision-resistant but not cryptographically secure.
// (See crypto/sha256 and crypto/sha512 for cryptographic use.) // (See crypto/sha256 and crypto/sha512 for cryptographic use.)
//
// The hash value of a given byte sequence is consistent within a
// single process, but will be different in different processes.
package maphash package maphash
import "unsafe" import "unsafe"
...@@ -66,7 +69,7 @@ type Hash struct { ...@@ -66,7 +69,7 @@ type Hash struct {
// which does call h.initSeed.) // which does call h.initSeed.)
func (h *Hash) initSeed() { func (h *Hash) initSeed() {
if h.seed.s == 0 { if h.seed.s == 0 {
h.SetSeed(MakeSeed()) h.setSeed(MakeSeed())
} }
} }
...@@ -121,12 +124,17 @@ func (h *Hash) Seed() Seed { ...@@ -121,12 +124,17 @@ func (h *Hash) Seed() Seed {
// Two Hash objects with different seeds will very likely behave differently. // Two Hash objects with different seeds will very likely behave differently.
// Any bytes added to h before this call will be discarded. // Any bytes added to h before this call will be discarded.
func (h *Hash) SetSeed(seed Seed) { func (h *Hash) SetSeed(seed Seed) {
h.setSeed(seed)
h.n = 0
}
// setSeed sets seed without discarding accumulated data.
func (h *Hash) setSeed(seed Seed) {
if seed.s == 0 { if seed.s == 0 {
panic("maphash: use of uninitialized Seed") panic("maphash: use of uninitialized Seed")
} }
h.seed = seed h.seed = seed
h.state = seed h.state = seed
h.n = 0
} }
// Reset discards all bytes added to h. // Reset discards all bytes added to h.
......
...@@ -83,6 +83,29 @@ func TestHashHighBytes(t *testing.T) { ...@@ -83,6 +83,29 @@ func TestHashHighBytes(t *testing.T) {
} }
} }
func TestRepeat(t *testing.T) {
h1 := new(Hash)
h1.WriteString("testing")
sum1 := h1.Sum64()
h1.Reset()
h1.WriteString("testing")
sum2 := h1.Sum64()
if sum1 != sum2 {
t.Errorf("different sum after reseting: %#x != %#x", sum1, sum2)
}
h2 := new(Hash)
h2.SetSeed(h1.Seed())
h2.WriteString("testing")
sum3 := h2.Sum64()
if sum1 != sum3 {
t.Errorf("different sum on the same seed: %#x != %#x", sum1, sum3)
}
}
// Make sure a Hash implements the hash.Hash and hash.Hash64 interfaces. // Make sure a Hash implements the hash.Hash and hash.Hash64 interfaces.
var _ hash.Hash = &Hash{} var _ hash.Hash = &Hash{}
var _ hash.Hash64 = &Hash{} var _ hash.Hash64 = &Hash{}
...@@ -505,8 +505,8 @@ func (z *Int) Exp(x, y, m *Int) *Int { ...@@ -505,8 +505,8 @@ func (z *Int) Exp(x, y, m *Int) *Int {
// GCD sets z to the greatest common divisor of a and b and returns z. // GCD sets z to the greatest common divisor of a and b and returns z.
// If x or y are not nil, GCD sets their value such that z = a*x + b*y. // If x or y are not nil, GCD sets their value such that z = a*x + b*y.
// //
// a and b may be positive, zero or negative. // a and b may be positive, zero or negative. (Before Go 1.14 both had
// Regardless of the signs of a and b, z is always >= 0. // to be > 0.) Regardless of the signs of a and b, z is always >= 0.
// //
// If a == b == 0, GCD sets z = x = y = 0. // If a == b == 0, GCD sets z = x = y = 0.
// //
......
...@@ -62,9 +62,10 @@ ...@@ -62,9 +62,10 @@
// Allocating and freeing a large object uses the mheap // Allocating and freeing a large object uses the mheap
// directly, bypassing the mcache and mcentral. // directly, bypassing the mcache and mcentral.
// //
// Free object slots in an mspan are zeroed only if mspan.needzero is // If mspan.needzero is false, then free object slots in the mspan are
// false. If needzero is true, objects are zeroed as they are // already zeroed. Otherwise if needzero is true, objects are zeroed as
// allocated. There are various benefits to delaying zeroing this way: // they are allocated. There are various benefits to delaying zeroing
// this way:
// //
// 1. Stack frame allocation can avoid zeroing altogether. // 1. Stack frame allocation can avoid zeroing altogether.
// //
......
...@@ -244,6 +244,15 @@ func genAMD64() { ...@@ -244,6 +244,15 @@ func genAMD64() {
// TODO: MXCSR register? // TODO: MXCSR register?
// Apparently, the signal handling code path in darwin kernel leaves
// the upper bits of Y registers in a dirty state, which causes
// many SSE operations (128-bit and narrower) become much slower.
// Clear the upper bits to get to a clean state. See issue #37174.
// It is safe here as Go code don't use the upper bits of Y registers.
p("#ifdef GOOS_darwin")
p("VZEROUPPER")
p("#endif")
p("PUSHQ BP") p("PUSHQ BP")
p("MOVQ SP, BP") p("MOVQ SP, BP")
p("// Save flags before clobbering them") p("// Save flags before clobbering them")
......
...@@ -13,16 +13,23 @@ var netpollWaiters uint32 ...@@ -13,16 +13,23 @@ var netpollWaiters uint32
var netpollStubLock mutex var netpollStubLock mutex
var netpollNote note var netpollNote note
var netpollBroken uint32
// netpollBroken, protected by netpollBrokenLock, avoids a double notewakeup.
var netpollBrokenLock mutex
var netpollBroken bool
func netpollGenericInit() { func netpollGenericInit() {
atomic.Store(&netpollInited, 1) atomic.Store(&netpollInited, 1)
} }
func netpollBreak() { func netpollBreak() {
if atomic.Cas(&netpollBroken, 0, 1) { lock(&netpollBrokenLock)
broken := netpollBroken
netpollBroken = true
if !broken {
notewakeup(&netpollNote) notewakeup(&netpollNote)
} }
unlock(&netpollBrokenLock)
} }
// Polls for ready network connections. // Polls for ready network connections.
...@@ -34,8 +41,12 @@ func netpoll(delay int64) gList { ...@@ -34,8 +41,12 @@ func netpoll(delay int64) gList {
// This lock ensures that only one goroutine tries to use // This lock ensures that only one goroutine tries to use
// the note. It should normally be completely uncontended. // the note. It should normally be completely uncontended.
lock(&netpollStubLock) lock(&netpollStubLock)
lock(&netpollBrokenLock)
noteclear(&netpollNote) noteclear(&netpollNote)
atomic.Store(&netpollBroken, 0) netpollBroken = false
unlock(&netpollBrokenLock)
notetsleep(&netpollNote, delay) notetsleep(&netpollNote, delay)
unlock(&netpollStubLock) unlock(&netpollStubLock)
} }
......
...@@ -179,6 +179,7 @@ func (b *B) ReportAllocs() { ...@@ -179,6 +179,7 @@ func (b *B) ReportAllocs() {
func (b *B) runN(n int) { func (b *B) runN(n int) {
benchmarkLock.Lock() benchmarkLock.Lock()
defer benchmarkLock.Unlock() defer benchmarkLock.Unlock()
defer b.runCleanup(normalPanic)
// Try to get a comparable environment for each run // Try to get a comparable environment for each run
// by clearing garbage from previous runs. // by clearing garbage from previous runs.
runtime.GC() runtime.GC()
......
...@@ -613,6 +613,46 @@ func TestBRun(t *T) { ...@@ -613,6 +613,46 @@ func TestBRun(t *T) {
t.Errorf("MemBytes was %v; want %v", got, 2*bufSize) t.Errorf("MemBytes was %v; want %v", got, 2*bufSize)
} }
}, },
}, {
desc: "cleanup is called",
f: func(b *B) {
var calls, cleanups, innerCalls, innerCleanups int
b.Run("", func(b *B) {
calls++
b.Cleanup(func() {
cleanups++
})
b.Run("", func(b *B) {
b.Cleanup(func() {
innerCleanups++
})
innerCalls++
})
work(b)
})
if calls == 0 || calls != cleanups {
t.Errorf("mismatched cleanups; got %d want %d", cleanups, calls)
}
if innerCalls == 0 || innerCalls != innerCleanups {
t.Errorf("mismatched cleanups; got %d want %d", cleanups, calls)
}
},
}, {
desc: "cleanup is called on failure",
failed: true,
f: func(b *B) {
var calls, cleanups int
b.Run("", func(b *B) {
calls++
b.Cleanup(func() {
cleanups++
})
b.Fatalf("failure")
})
if calls == 0 || calls != cleanups {
t.Errorf("mismatched cleanups; got %d want %d", cleanups, calls)
}
},
}} }}
for _, tc := range testCases { for _, tc := range testCases {
var ok bool var ok bool
......
...@@ -571,7 +571,6 @@ var _ TB = (*T)(nil) ...@@ -571,7 +571,6 @@ var _ TB = (*T)(nil)
var _ TB = (*B)(nil) var _ TB = (*B)(nil)
// T is a type passed to Test functions to manage test state and support formatted test logs. // T is a type passed to Test functions to manage test state and support formatted test logs.
// Logs are accumulated during execution and dumped to standard output when done.
// //
// A test ends when its Test function returns or calls any of the methods // A test ends when its Test function returns or calls any of the methods
// FailNow, Fatal, Fatalf, SkipNow, Skip, or Skipf. Those methods, as well as // FailNow, Fatal, Fatalf, SkipNow, Skip, or Skipf. Those methods, as well as
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment