[dev.typeparams] all: merge master (16e82be) into dev.typeparams

Merge List:

+ 2021-06-21 16e82be454 runtime: fix crash during VDSO calls on PowerPC
+ 2021-06-21 2e542c3c06 runtime/pprof: deflake TestMorestack more
+ 2021-06-21 ced0fdbad0 doc/go1.17: note deprecation of 'go get' for installing commands
+ 2021-06-21 7a5e7047a4 doc/go1.17: add Go 1.18 pre-announcements
+ 2021-06-21 85a2e24afd doc/go1.17: add security-related release notes
+ 2021-06-21 1de332996c doc/go1.17: document go/parser.SkipObjectResolution
+ 2021-06-21 117ebe0f52 cmd/go: do not require the module cache to exist for 'go mod edit'
+ 2021-06-20 460900a7b5 os/signal: test with a significantly longer fatal timeout
+ 2021-06-19 b73cc4b02b database/sql: do not rely on timeout for deadlock test
+ 2021-06-18 86743e7d86 image: add RGBA64Image interface
+ 2021-06-18 9401172166 runtime: clarify Frames.Next documentation
+ 2021-06-18 57aaa19aae runtime: disable CPU profiling before removing the SIGPROF handler
+ 2021-06-18 6f22d2c682 doc/go1.17: fix typo
+ 2021-06-17 45f251ad6c cmd/pprof,runtime/pprof: disable test on more broken platforms
+ 2021-06-17 ed834853ad cmd/go: replace a TODO with an explanatory comment
+ 2021-06-17 4dede02550 cmd/pprof: make ObjAddr a no-op
+ 2021-06-17 97cee43c93 testing: drop unusual characters from TempDir directory name
+ 2021-06-17 b0355a3e72 time: fix receiver for Time.IsDST method
+ 2021-06-17 881b6ea7ba doc/go1.17: fix redundant space
+ 2021-06-16 0e67ce3d28 cmd/go: in lazy modules, add transitive imports for 'go get' arguments
+ 2021-06-16 6ea2af0890 cmd/go: add a regression test for #45979
+ 2021-06-16 a294e4e798 math/rand: mention half-open intervals explicitly
+ 2021-06-16 a6a853f94c cmd/asm: restore supporting of *1 scaling on ARM64

Change-Id: Ifdcb817fd44b4fa9c477042b41da55d1d769b016
This commit is contained in:
Cuong Manh Le 2021-06-22 00:35:07 +07:00
commit d626ba27bb
30 changed files with 967 additions and 96 deletions

View File

@ -28,6 +28,38 @@ pkg encoding/csv, method (*Reader) FieldPos(int) (int, int)
pkg go/build, type Context struct, ToolTags []string pkg go/build, type Context struct, ToolTags []string
pkg go/parser, const SkipObjectResolution = 64 pkg go/parser, const SkipObjectResolution = 64
pkg go/parser, const SkipObjectResolution Mode pkg go/parser, const SkipObjectResolution Mode
pkg image, method (*Alpha) RGBA64At(int, int) color.RGBA64
pkg image, method (*Alpha) SetRGBA64(int, int, color.RGBA64)
pkg image, method (*Alpha16) RGBA64At(int, int) color.RGBA64
pkg image, method (*Alpha16) SetRGBA64(int, int, color.RGBA64)
pkg image, method (*CMYK) RGBA64At(int, int) color.RGBA64
pkg image, method (*CMYK) SetRGBA64(int, int, color.RGBA64)
pkg image, method (*Gray) RGBA64At(int, int) color.RGBA64
pkg image, method (*Gray) SetRGBA64(int, int, color.RGBA64)
pkg image, method (*Gray16) RGBA64At(int, int) color.RGBA64
pkg image, method (*Gray16) SetRGBA64(int, int, color.RGBA64)
pkg image, method (*NRGBA) RGBA64At(int, int) color.RGBA64
pkg image, method (*NRGBA) SetRGBA64(int, int, color.RGBA64)
pkg image, method (*NRGBA64) RGBA64At(int, int) color.RGBA64
pkg image, method (*NRGBA64) SetRGBA64(int, int, color.RGBA64)
pkg image, method (*NYCbCrA) RGBA64At(int, int) color.RGBA64
pkg image, method (*Paletted) RGBA64At(int, int) color.RGBA64
pkg image, method (*Paletted) SetRGBA64(int, int, color.RGBA64)
pkg image, method (*RGBA) RGBA64At(int, int) color.RGBA64
pkg image, method (*RGBA) SetRGBA64(int, int, color.RGBA64)
pkg image, method (*YCbCr) RGBA64At(int, int) color.RGBA64
pkg image, type RGBA64Image interface { At, Bounds, ColorModel, RGBA64At }
pkg image, type RGBA64Image interface, At(int, int) color.Color
pkg image, type RGBA64Image interface, Bounds() Rectangle
pkg image, type RGBA64Image interface, ColorModel() color.Model
pkg image, type RGBA64Image interface, RGBA64At(int, int) color.RGBA64
pkg image/draw, type RGBA64Image interface { At, Bounds, ColorModel, RGBA64At, Set, SetRGBA64 }
pkg image/draw, type RGBA64Image interface, At(int, int) color.Color
pkg image/draw, type RGBA64Image interface, Bounds() image.Rectangle
pkg image/draw, type RGBA64Image interface, ColorModel() color.Model
pkg image/draw, type RGBA64Image interface, RGBA64At(int, int) color.RGBA64
pkg image/draw, type RGBA64Image interface, Set(int, int, color.Color)
pkg image/draw, type RGBA64Image interface, SetRGBA64(int, int, color.RGBA64)
pkg io/fs, func FileInfoToDirEntry(FileInfo) DirEntry pkg io/fs, func FileInfoToDirEntry(FileInfo) DirEntry
pkg math, const MaxFloat64 = 1.79769e+308 // 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368 pkg math, const MaxFloat64 = 1.79769e+308 // 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368
pkg math, const MaxInt = 9223372036854775807 pkg math, const MaxInt = 9223372036854775807
@ -153,7 +185,7 @@ pkg time, const Layout = "01/02 03:04:05PM '06 -0700"
pkg time, const Layout ideal-string pkg time, const Layout ideal-string
pkg time, func UnixMicro(int64) Time pkg time, func UnixMicro(int64) Time
pkg time, func UnixMilli(int64) Time pkg time, func UnixMilli(int64) Time
pkg time, method (*Time) IsDST() bool
pkg time, method (Time) GoString() string pkg time, method (Time) GoString() string
pkg time, method (Time) IsDST() bool
pkg time, method (Time) UnixMicro() int64 pkg time, method (Time) UnixMicro() int64
pkg time, method (Time) UnixMilli() int64 pkg time, method (Time) UnixMilli() int64

View File

@ -162,7 +162,7 @@ Do not send CLs removing the interior tags from such phrases.
By default, <code>go</code> <code>mod</code> <code>tidy</code> verifies that By default, <code>go</code> <code>mod</code> <code>tidy</code> verifies that
the selected versions of dependencies relevant to the main module are the same the selected versions of dependencies relevant to the main module are the same
versions that would be used by the prior Go release (Go 1.16 for a module that versions that would be used by the prior Go release (Go 1.16 for a module that
spsecifies <code>go</code> <code>1.17</code>), and preserves specifies <code>go</code> <code>1.17</code>), and preserves
the <code>go.sum</code> entries needed by that release even for dependencies the <code>go.sum</code> entries needed by that release even for dependencies
that are not normally needed by other commands. that are not normally needed by other commands.
</p> </p>
@ -214,6 +214,16 @@ Do not send CLs removing the interior tags from such phrases.
<code>environment</code> for details. <code>environment</code> for details.
</p> </p>
<p><!-- golang.org/issue/43684 -->
<code>go</code> <code>get</code> prints a deprecation warning when installing
commands outside the main module (without the <code>-d</code> flag).
<code>go</code> <code>install</code> <code>cmd@version</code> should be used
instead to install a command at a specific version, using a suffix like
<code>@latest</code> or <code>@v1.2.3</code>. In Go 1.18, the <code>-d</code>
flag will always be enabled, and <code>go</code> <code>get</code> will only
be used to change dependencies in <code>go.mod</code>.
</p>
<h4 id="missing-go-directive"><code>go.mod</code> files missing <code>go</code> directives</h4> <h4 id="missing-go-directive"><code>go.mod</code> files missing <code>go</code> directives</h4>
<p><!-- golang.org/issue/44976 --> <p><!-- golang.org/issue/44976 -->
@ -441,6 +451,67 @@ func Foo() bool {
<a href="/pkg/runtime/cgo#Handle">runtime/cgo.Handle</a> for more information. <a href="/pkg/runtime/cgo#Handle">runtime/cgo.Handle</a> for more information.
</p> </p>
<h3 id="semicolons">URL query parsing</h3>
<!-- CL 325697, CL 326309 -->
<p>
The <code>net/url</code> and <code>net/http</code> packages used to accept
<code>";"</code> (semicolon) as a setting separator in URL queries, in
addition to <code>"&"</code> (ampersand). Now, settings with non-percent-encoded
semicolons are rejected and <code>net/http</code> servers will log a warning to
<a href="/pkg/net/http#Server.ErrorLog"><code>Server.ErrorLog</code></a>
when encountering one in a request URL.
</p>
<p>
For example, before Go 1.17 the <a href="/pkg/net/url#URL.Query"><code>Query</code></a>
method of the URL <code>example?a=1;b=2&c=3</code> would have returned
<code>map[a:[1] b:[2] c:[3]]</code>, while now it returns <code>map[c:[3]]</code>.
</p>
<p>
When encountering such a query string,
<a href="/pkg/net/url#URL.Query"><code>URL.Query</code></a>
and
<a href="/pkg/net/http#Request.FormValue"><code>Request.FormValue</code></a>
ignore any settings that contain a semicolon,
<a href="/pkg/net/url#ParseQuery"><code>ParseQuery</code></a>
returns the remaining settings and an error, and
<a href="/pkg/net/http#Request.ParseForm"><code>Request.ParseForm</code></a>
and
<a href="/pkg/net/http#Request.ParseMultipartForm"><code>Request.ParseMultipartForm</code></a>
return an error but still set <code>Request</code> fields based on the
remaining settings.
</p>
<p>
<code>net/http</code> users can restore the original behavior by using the new
<a href="/pkg/net/http#AllowQuerySemicolons"><code>AllowQuerySemicolons</code></a>
handler wrapper. This will also suppress the <code>ErrorLog</code> warning.
Note that accepting semicolons as query separators can lead to security issues
if different systems interpret cache keys differently.
See <a href="https://golang.org/issue/25192">issue 25192</a> for more information.
</p>
<h3 id="ALPN">TLS strict ALPN</h3>
<!-- CL 289209, CL 325432 -->
<p>
When <a href="/pkg/crypto/tls#Config.NextProtos"><code>Config.NextProtos</code></a>
is set, servers now enforce that there is an overlap between the configured
protocols and the ALPN protocols advertised by the client, if any. If there is
no mutually supported protocol, the connection is closed with the
<code>no_application_protocol</code> alert, as required by RFC 7301. This
helps mitigate <a href="https://alpaca-attack.com/">the ALPACA cross-protocol attack</a>.
</p>
<p>
As an exception, when the value <code>"h2"</code> is included in the server's
<code>Config.NextProtos</code>, HTTP/1.1 clients will be allowed to connect as
if they didn't support ALPN.
See <a href="https://golang.org/issue/46310">issue 46310</a> for more information.
</p>
<h3 id="minor_library_changes">Minor changes to the library</h3> <h3 id="minor_library_changes">Minor changes to the library</h3>
<p> <p>
@ -549,14 +620,6 @@ func Foo() bool {
methods. Canceling the context after the handshake has finished has no effect. methods. Canceling the context after the handshake has finished has no effect.
</p> </p>
<p><!-- CL 289209 -->
When <a href="/pkg/crypto/tls#Config.NextProtos"><code>Config.NextProtos</code></a>
is set, servers now enforce that there is an overlap between the
configured protocols and the protocols advertised by the client, if any.
If there is no overlap the connection is closed with the
<code>no_application_protocol</code> alert, as required by RFC 7301.
</p>
<p><!-- CL 314609 --> <p><!-- CL 314609 -->
Cipher suite ordering is now handled entirely by the Cipher suite ordering is now handled entirely by the
<code>crypto/tls</code> package. Currently, cipher suites are sorted based <code>crypto/tls</code> package. Currently, cipher suites are sorted based
@ -576,6 +639,15 @@ func Foo() bool {
weakness</a>. They are still enabled by default but only as a last resort, weakness</a>. They are still enabled by default but only as a last resort,
thanks to the cipher suite ordering change above. thanks to the cipher suite ordering change above.
</p> </p>
<p><!-- golang.org/issue/45428 -->
Beginning in the next release, Go 1.18, the
<a href="/pkg/crypto/tls/#Config.MinVersion"><code>Config.MinVersion</code></a>
for <code>crypto/tls</code> clients will default to TLS 1.2, disabling TLS 1.0
and TLS 1.1 by default. Applications will be able to override the change by
explicitly setting <code>Config.MinVersion</code>.
This will not affect <code>crypto/tls</code> servers.
</p>
</dd> </dd>
</dl><!-- crypto/tls --> </dl><!-- crypto/tls -->
@ -603,6 +675,14 @@ func Foo() bool {
roots. This adds support for the new system trusted certificate store in roots. This adds support for the new system trusted certificate store in
FreeBSD 12.2+. FreeBSD 12.2+.
</p> </p>
<p><!-- golang.org/issue/41682 -->
Beginning in the next release, Go 1.18, <code>crypto/x509</code> will
reject certificates signed with the SHA-1 hash function. This doesn't
apply to self-signed root certificates. Practical attacks against SHA-1
<a href="https://shattered.io/">have been demonstrated in 2017</a> and publicly
trusted Certificate Authorities have not issued SHA-1 certificates since 2015.
</p>
</dd> </dd>
</dl><!-- crypto/x509 --> </dl><!-- crypto/x509 -->
@ -658,6 +738,22 @@ func Foo() bool {
</dd> </dd>
</dl><!-- encoding/csv --> </dl><!-- encoding/csv -->
<dl id="encoding/xml"><dt><a href="/pkg/encoding/xml/">encoding/xml</a></dt>
<dd>
<p><!-- CL 277893 -->
When a comment appears within a
<a href="/pkg/encoding/xml/#Directive"><code>Directive</code></a>, it is now replaced
with a single space instead of being completely elided.
</p>
<p>
Invalid element or attribute names with leading, trailing, or multiple
colons are now stored unmodified into the
<a href="/pkg/encoding/xml/#Name"><code>Name.Local</code></a> field.
</p>
</dd>
</dl><!-- encoding/xml -->
<dl id="flag"><dt><a href="/pkg/flag/">flag</a></dt> <dl id="flag"><dt><a href="/pkg/flag/">flag</a></dt>
<dd> <dd>
<p><!-- CL 271788 --> <p><!-- CL 271788 -->
@ -693,6 +789,29 @@ func Foo() bool {
</dd> </dd>
</dl><!-- go/format --> </dl><!-- go/format -->
<dl id="go/parser"><dt><a href="/pkg/go/parser/">go/parser</a></dt>
<dd>
<p><!-- CL 306149 -->
The new <a href="/pkg/go/parser/#SkipObjectResolution"><code>SkipObjectResolution</code></a>
<code>Mode</code> value instructs the parser not to resolve identifiers to
their declaration. This may improve parsing speed.
</p>
</dd>
</dl><!-- go/parser -->
<dl id="image"><dt><a href="/pkg/image/">image</a></dt>
<dd>
<p><!-- CL 311129 -->
The concrete image types (<code>RGBA</code>, <code>Gray16</code> and so on)
now implement a new <a href="/pkg/image/#RGBA64Image"><code>RGBA64Image</code></a>
interface. Those concrete types, other than the chroma-subsampling
related <code>YCbCr</code> and <code>NYCbCrA</code>, also now implement
<a href="/pkg/image/draw/#RGBA64Image"><code>draw.RGBA64Image</code></a>, a
new interface in the <code>image/draw</code> package.
</p>
</dd>
</dl><!-- image -->
<dl id="io/fs"><dt><a href="/pkg/io/fs/">io/fs</a></dt> <dl id="io/fs"><dt><a href="/pkg/io/fs/">io/fs</a></dt>
<dd> <dd>
<p><!-- CL 293649 --> <p><!-- CL 293649 -->
@ -721,6 +840,20 @@ func Foo() bool {
</dd> </dd>
</dl><!-- mime --> </dl><!-- mime -->
<dl id="mime/multipart"><dt><a href="/pkg/mime/multipart/">mime/multipart</a></dt>
<dd>
<p><!-- CL 313809 -->
<a href="/pkg/mime/multipart/#Part.FileName"><code>Part.FileName</code></a>
now applies
<a href="/pkg/path/filepath/#Base"><code>filepath.Base</code></a> to the
return value. This mitigates potential path traversal vulnerabilities in
applications that accept multipart messages, such as <code>net/http</code>
servers that call
<a href="/pkg/net/http/#Request.FormFile"><code>Request.FormFile</code></a>.
</p>
</dd>
</dl><!-- mime/multipart -->
<dl id="net"><dt><a href="/pkg/net/">net</a></dt> <dl id="net"><dt><a href="/pkg/net/">net</a></dt>
<dd> <dd>
<p><!-- CL 272668 --> <p><!-- CL 272668 -->
@ -771,6 +904,29 @@ func Foo() bool {
The <a href="/pkg/net/http/#ReadRequest"><code>ReadRequest</code></a> function The <a href="/pkg/net/http/#ReadRequest"><code>ReadRequest</code></a> function
now returns an error when the request has multiple Host headers. now returns an error when the request has multiple Host headers.
</p> </p>
<p><!-- CL 313950 -->
When producing a redirect to the cleaned version of a URL,
<a href="/pkg/net/http/#ServeMux"><code>ServeMux</code></a> now always
uses relative URLs in the <code>Location</code> header. Previously it
would echo the full URL of the request, which could lead to unintended
redirects if the client could be made to send an absolute request URL.
</p>
<p><!-- CL 308009, CL 313489 -->
When interpreting certain HTTP headers handled by <code>net/http</code>,
non-ASCII characters are now ignored or rejected.
</p>
<p><!-- CL 325697 -->
If
<a href="/pkg/net/http/#Request.ParseForm"><code>Request.ParseForm</code></a>
returns an error when called by
<a href="/pkg/net/http/#Request.ParseMultipartForm"><code>Request.ParseMultipartForm</code></a>,
the latter now continues populating
<a href="/pkg/net/http/#Request.MultipartForm"><code>Request.MultipartForm</code></a>
before returning it.
</p>
</dd> </dd>
</dl><!-- net/http --> </dl><!-- net/http -->

View File

@ -1003,7 +1003,8 @@ func (p *Parser) registerIndirect(a *obj.Addr, prefix rune) {
p.errorf("unimplemented two-register form") p.errorf("unimplemented two-register form")
} }
a.Index = r1 a.Index = r1
if scale != 0 && p.arch.Family == sys.ARM64 { if scale != 0 && scale != 1 && p.arch.Family == sys.ARM64 {
// Support (R1)(R2) (no scaling) and (R1)(R2*1).
p.errorf("arm64 doesn't support scaled register format") p.errorf("arm64 doesn't support scaled register format")
} else { } else {
a.Scale = int16(scale) a.Scale = int16(scale)

View File

@ -547,6 +547,7 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
// shifted or extended register offset. // shifted or extended register offset.
MOVD (R2)(R6.SXTW), R4 // 44c866f8 MOVD (R2)(R6.SXTW), R4 // 44c866f8
MOVD (R3)(R6), R5 // 656866f8 MOVD (R3)(R6), R5 // 656866f8
MOVD (R3)(R6*1), R5 // 656866f8
MOVD (R2)(R6), R4 // 446866f8 MOVD (R2)(R6), R4 // 446866f8
MOVWU (R19)(R20<<2), R20 // 747a74b8 MOVWU (R19)(R20<<2), R20 // 747a74b8
MOVD (R2)(R6<<3), R4 // 447866f8 MOVD (R2)(R6<<3), R4 // 447866f8
@ -579,6 +580,7 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
MOVB R4, (R2)(R6.SXTX) // 44e82638 MOVB R4, (R2)(R6.SXTX) // 44e82638
MOVB R8, (R3)(R9.UXTW) // 68482938 MOVB R8, (R3)(R9.UXTW) // 68482938
MOVB R10, (R5)(R8) // aa682838 MOVB R10, (R5)(R8) // aa682838
MOVB R10, (R5)(R8*1) // aa682838
MOVH R11, (R2)(R7.SXTW<<1) // 4bd82778 MOVH R11, (R2)(R7.SXTW<<1) // 4bd82778
MOVH R5, (R1)(R2<<1) // 25782278 MOVH R5, (R1)(R2<<1) // 25782278
MOVH R7, (R2)(R5.SXTX<<1) // 47f82578 MOVH R7, (R2)(R5.SXTX<<1) // 47f82578

View File

@ -152,7 +152,7 @@ func lockVersion(mod module.Version) (unlock func(), err error) {
// If err is nil, the caller MUST eventually call the unlock function. // If err is nil, the caller MUST eventually call the unlock function.
func SideLock() (unlock func(), err error) { func SideLock() (unlock func(), err error) {
if err := checkCacheDir(); err != nil { if err := checkCacheDir(); err != nil {
base.Fatalf("go: %v", err) return nil, err
} }
path := filepath.Join(cfg.GOMODCACHE, "cache", "lock") path := filepath.Join(cfg.GOMODCACHE, "cache", "lock")

View File

@ -1153,6 +1153,7 @@ func (r *resolver) loadPackages(ctx context.Context, patterns []string, findPack
Tags: imports.AnyTags(), Tags: imports.AnyTags(),
VendorModulesInGOROOTSrc: true, VendorModulesInGOROOTSrc: true,
LoadTests: *getT, LoadTests: *getT,
AssumeRootsImported: true, // After 'go get foo', imports of foo should build.
SilencePackageErrors: true, // May be fixed by subsequent upgrades or downgrades. SilencePackageErrors: true, // May be fixed by subsequent upgrades or downgrades.
} }

View File

@ -443,7 +443,7 @@ func expandGraph(ctx context.Context, rs *Requirements) (*Requirements, *ModuleG
// roots — but in a lazy module it may pull in previously-irrelevant // roots — but in a lazy module it may pull in previously-irrelevant
// transitive dependencies. // transitive dependencies.
newRS, rsErr := updateRoots(ctx, rs.direct, rs, nil, nil) newRS, rsErr := updateRoots(ctx, rs.direct, rs, nil, nil, false)
if rsErr != nil { if rsErr != nil {
// Failed to update roots, perhaps because of an error in a transitive // Failed to update roots, perhaps because of an error in a transitive
// dependency needed for the update. Return the original Requirements // dependency needed for the update. Return the original Requirements
@ -517,11 +517,11 @@ func tidyRoots(ctx context.Context, rs *Requirements, pkgs []*loadPkg) (*Require
return tidyLazyRoots(ctx, rs.direct, pkgs) return tidyLazyRoots(ctx, rs.direct, pkgs)
} }
func updateRoots(ctx context.Context, direct map[string]bool, rs *Requirements, pkgs []*loadPkg, add []module.Version) (*Requirements, error) { func updateRoots(ctx context.Context, direct map[string]bool, rs *Requirements, pkgs []*loadPkg, add []module.Version, rootsImported bool) (*Requirements, error) {
if rs.depth == eager { if rs.depth == eager {
return updateEagerRoots(ctx, direct, rs, add) return updateEagerRoots(ctx, direct, rs, add)
} }
return updateLazyRoots(ctx, direct, rs, pkgs, add) return updateLazyRoots(ctx, direct, rs, pkgs, add, rootsImported)
} }
// tidyLazyRoots returns a minimal set of root requirements that maintains the // tidyLazyRoots returns a minimal set of root requirements that maintains the
@ -661,7 +661,7 @@ func tidyLazyRoots(ctx context.Context, direct map[string]bool, pkgs []*loadPkg)
// //
// (See https://golang.org/design/36460-lazy-module-loading#invariants for more // (See https://golang.org/design/36460-lazy-module-loading#invariants for more
// detail.) // detail.)
func updateLazyRoots(ctx context.Context, direct map[string]bool, rs *Requirements, pkgs []*loadPkg, add []module.Version) (*Requirements, error) { func updateLazyRoots(ctx context.Context, direct map[string]bool, rs *Requirements, pkgs []*loadPkg, add []module.Version, rootsImported bool) (*Requirements, error) {
roots := rs.rootModules roots := rs.rootModules
rootsUpgraded := false rootsUpgraded := false
@ -688,6 +688,10 @@ func updateLazyRoots(ctx context.Context, direct map[string]bool, rs *Requiremen
// //
// (This is the “import invariant” that makes lazy loading possible.) // (This is the “import invariant” that makes lazy loading possible.)
case rootsImported && pkg.flags.has(pkgFromRoot):
// pkg is a transitive dependency of some root, and we are treating the
// roots as if they are imported by the main module (as in 'go get').
case pkg.flags.has(pkgIsRoot): case pkg.flags.has(pkgIsRoot):
// pkg is a root of the package-import graph. (Generally this means that // pkg is a root of the package-import graph. (Generally this means that
// it matches a command-line argument.) We want future invocations of the // it matches a command-line argument.) We want future invocations of the

View File

@ -661,7 +661,7 @@ func requirementsFromModFile(ctx context.Context) *Requirements {
for _, n := range mPathCount { for _, n := range mPathCount {
if n > 1 { if n > 1 {
var err error var err error
rs, err = updateRoots(ctx, rs.direct, rs, nil, nil) rs, err = updateRoots(ctx, rs.direct, rs, nil, nil, false)
if err != nil { if err != nil {
base.Fatalf("go: %v", err) base.Fatalf("go: %v", err)
} }

View File

@ -171,6 +171,11 @@ type PackageOpts struct {
// if the flag is set to "readonly" (the default) or "vendor". // if the flag is set to "readonly" (the default) or "vendor".
ResolveMissingImports bool ResolveMissingImports bool
// AssumeRootsImported indicates that the transitive dependencies of the root
// packages should be treated as if those roots will be imported by the main
// module.
AssumeRootsImported bool
// AllowPackage, if non-nil, is called after identifying the module providing // AllowPackage, if non-nil, is called after identifying the module providing
// each package. If AllowPackage returns a non-nil error, that error is set // each package. If AllowPackage returns a non-nil error, that error is set
// for the package, and the imports and test of that package will not be // for the package, and the imports and test of that package will not be
@ -875,6 +880,11 @@ const (
// are also roots (and must be marked pkgIsRoot). // are also roots (and must be marked pkgIsRoot).
pkgIsRoot pkgIsRoot
// pkgFromRoot indicates that the package is in the transitive closure of
// imports starting at the roots. (Note that every package marked as pkgIsRoot
// is also trivially marked pkgFromRoot.)
pkgFromRoot
// pkgImportsLoaded indicates that the imports and testImports fields of a // pkgImportsLoaded indicates that the imports and testImports fields of a
// loadPkg have been populated. // loadPkg have been populated.
pkgImportsLoaded pkgImportsLoaded
@ -1068,7 +1078,7 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader {
// iteration so we don't need to also update it here. (That would waste time // iteration so we don't need to also update it here. (That would waste time
// computing a "direct" map that we'll have to recompute later anyway.) // computing a "direct" map that we'll have to recompute later anyway.)
direct := ld.requirements.direct direct := ld.requirements.direct
rs, err := updateRoots(ctx, direct, ld.requirements, noPkgs, toAdd) rs, err := updateRoots(ctx, direct, ld.requirements, noPkgs, toAdd, ld.AssumeRootsImported)
if err != nil { if err != nil {
// If an error was found in a newly added module, report the package // If an error was found in a newly added module, report the package
// import stack instead of the module requirement stack. Packages // import stack instead of the module requirement stack. Packages
@ -1274,7 +1284,7 @@ func (ld *loader) updateRequirements(ctx context.Context) (changed bool, err err
addRoots = tidy.rootModules addRoots = tidy.rootModules
} }
rs, err = updateRoots(ctx, direct, rs, ld.pkgs, addRoots) rs, err = updateRoots(ctx, direct, rs, ld.pkgs, addRoots, ld.AssumeRootsImported)
if err != nil { if err != nil {
// We don't actually know what even the root requirements are supposed to be, // We don't actually know what even the root requirements are supposed to be,
// so we can't proceed with loading. Return the error to the caller // so we can't proceed with loading. Return the error to the caller
@ -1433,6 +1443,9 @@ func (ld *loader) applyPkgFlags(ctx context.Context, pkg *loadPkg, flags loadPkg
// This package matches a root pattern by virtue of being in "all". // This package matches a root pattern by virtue of being in "all".
flags |= pkgIsRoot flags |= pkgIsRoot
} }
if flags.has(pkgIsRoot) {
flags |= pkgFromRoot
}
old := pkg.flags.update(flags) old := pkg.flags.update(flags)
new := old | flags new := old | flags
@ -1487,6 +1500,12 @@ func (ld *loader) applyPkgFlags(ctx context.Context, pkg *loadPkg, flags loadPkg
ld.applyPkgFlags(ctx, dep, pkgInAll) ld.applyPkgFlags(ctx, dep, pkgInAll)
} }
} }
if new.has(pkgFromRoot) && !old.has(pkgFromRoot|pkgImportsLoaded) {
for _, dep := range pkg.imports {
ld.applyPkgFlags(ctx, dep, pkgFromRoot)
}
}
} }
// preloadRootModules loads the module requirements needed to identify the // preloadRootModules loads the module requirements needed to identify the
@ -1549,7 +1568,7 @@ func (ld *loader) preloadRootModules(ctx context.Context, rootPkgs []string) (ch
} }
module.Sort(toAdd) module.Sort(toAdd)
rs, err := updateRoots(ctx, ld.requirements.direct, ld.requirements, nil, toAdd) rs, err := updateRoots(ctx, ld.requirements.direct, ld.requirements, nil, toAdd, ld.AssumeRootsImported)
if err != nil { if err != nil {
// We are missing some root dependency, and for some reason we can't load // We are missing some root dependency, and for some reason we can't load
// enough of the module dependency graph to add the missing root. Package // enough of the module dependency graph to add the missing root. Package

View File

@ -0,0 +1,15 @@
# 'go mod edit' opportunistically locks the side-lock file in the module cache,
# for compatibility with older versions of the 'go' command.
# It does not otherwise depend on the module cache, so it should not
# fail if the module cache directory cannot be created.
[root] skip
mkdir $WORK/readonly
chmod 0555 $WORK/readonly
env GOPATH=$WORK/readonly/nonexist
go mod edit -go=1.17
-- go.mod --
module example.com/m

View File

@ -0,0 +1,44 @@
# https://golang.org/issue/45979: after 'go get' on a package,
# that package should be importable without error.
# We start out with an unresolved dependency.
# 'go list' suggests that we run 'go get' on that dependency.
! go list -deps .
stderr '^m.go:3:8: no required module provides package rsc\.io/quote; to add it:\n\tgo get rsc.io/quote$'
# When we run the suggested 'go get' command, the new dependency can be used
# immediately.
#
# 'go get' marks the new dependency as 'indirect', because it doesn't scan
# enough source code to know whether it is direct, and it is easier and less
# invasive to remove an incorrect indirect mark (e.g. using 'go get') than to
# add one that is missing ('go mod tidy' or 'go mod vendor').
go get rsc.io/quote
grep 'rsc.io/quote v\d+\.\d+\.\d+ // indirect$' go.mod
! grep 'rsc.io/quote v\d+\.\d+\.\d+$' go.mod
go list -deps .
! stderr .
[!short] go build .
[!short] ! stderr .
# 'go get .' (or 'go mod tidy') removes the indirect mark.
go get .
grep 'rsc.io/quote v\d+\.\d+\.\d+$' go.mod
! grep 'rsc.io/quote v\d+\.\d+\.\d+ // indirect$' go.mod
-- go.mod --
module example.com/m
go 1.17
-- m.go --
package m
import _ "rsc.io/quote"

View File

@ -10,45 +10,73 @@ go env GOSUMDB
stdout '^sum.golang.org$' stdout '^sum.golang.org$'
# Download direct from github. # Download direct from github.
[!net] skip [!net] skip
[!exec:git] skip [!exec:git] skip
env GOSUMDB=sum.golang.org env GOSUMDB=sum.golang.org
env GOPROXY=direct env GOPROXY=direct
go get -d rsc.io/quote@v1.5.2 go get -d rsc.io/quote@v1.5.2
cp go.sum saved.sum cp go.sum saved.sum
# Download from proxy.golang.org with go.sum entry already. # Download from proxy.golang.org with go.sum entry already.
# Use 'go list' instead of 'go get' since the latter may download extra go.mod # Use 'go list' instead of 'go get' since the latter may download extra go.mod
# files not listed in go.sum. # files not listed in go.sum.
go clean -modcache go clean -modcache
env GOSUMDB= env GOSUMDB=
env GOPROXY= env GOPROXY=
go list -x -deps rsc.io/quote
go list -x -m all # Download go.mod files.
! stderr github ! stderr github
stderr proxy.golang.org/rsc.io/quote stderr proxy.golang.org/rsc.io/quote
! stderr sum.golang.org/tile ! stderr sum.golang.org/tile
! stderr sum.golang.org/lookup/rsc.io/quote ! stderr sum.golang.org/lookup/rsc.io/quote
go list -x -deps rsc.io/quote # Download module source.
! stderr github
stderr proxy.golang.org/rsc.io/quote
! stderr sum.golang.org/tile
! stderr sum.golang.org/lookup/rsc.io/quote
cmp go.sum saved.sum cmp go.sum saved.sum
# Download again. # Download again.
# Should use the checksum database to validate new go.sum lines, # Should use the checksum database to validate new go.sum lines,
# but not need to fetch any new data from the proxy. # but not need to fetch any new data from the proxy.
rm go.sum rm go.sum
go list -mod=mod -x rsc.io/quote
go list -mod=mod -x -m all # Add checksums for go.mod files.
stderr sum.golang.org/tile
! stderr github ! stderr github
! stderr proxy.golang.org/rsc.io/quote ! stderr proxy.golang.org/rsc.io/quote
stderr sum.golang.org/tile
stderr sum.golang.org/lookup/rsc.io/quote stderr sum.golang.org/lookup/rsc.io/quote
go list -mod=mod -x rsc.io/quote # Add checksums for module source.
! stderr . # Adds checksums, but for entities already in the module cache.
cmp go.sum saved.sum cmp go.sum saved.sum
# test fallback to direct # test fallback to direct
env TESTGOPROXY404=1 env TESTGOPROXY404=1
go clean -modcache go clean -modcache
rm go.sum rm go.sum
go list -mod=mod -x rsc.io/quote
go list -mod=mod -x -m all # Download go.mod files
stderr 'proxy.golang.org.*404 testing' stderr 'proxy.golang.org.*404 testing'
stderr github.com/rsc stderr github.com/rsc
go list -mod=mod -x rsc.io/quote # Download module source.
stderr 'proxy.golang.org.*404 testing'
stderr github.com/rsc
cmp go.sum saved.sum cmp go.sum saved.sum
-- go.mod -- -- go.mod --
module m module m

View File

@ -233,8 +233,8 @@ func (f *file) Name() string {
} }
func (f *file) ObjAddr(addr uint64) (uint64, error) { func (f *file) ObjAddr(addr uint64) (uint64, error) {
// No support for shared libraries. // No support for shared libraries, so translation is a no-op.
return 0, nil return addr, nil
} }
func (f *file) BuildID() string { func (f *file) BuildID() string {

127
src/cmd/pprof/pprof_test.go Normal file
View File

@ -0,0 +1,127 @@
// Copyright 2021 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 main
import (
"fmt"
"internal/testenv"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"testing"
)
var tmp, pprofExe string // populated by buildPprof
func TestMain(m *testing.M) {
if !testenv.HasGoBuild() {
return
}
var exitcode int
if err := buildPprof(); err == nil {
exitcode = m.Run()
} else {
fmt.Println(err)
exitcode = 1
}
os.RemoveAll(tmp)
os.Exit(exitcode)
}
func buildPprof() error {
var err error
tmp, err = os.MkdirTemp("", "TestPprof")
if err != nil {
return fmt.Errorf("TempDir failed: %v", err)
}
pprofExe = filepath.Join(tmp, "testpprof.exe")
gotool, err := testenv.GoTool()
if err != nil {
return err
}
out, err := exec.Command(gotool, "build", "-o", pprofExe, "cmd/pprof").CombinedOutput()
if err != nil {
os.RemoveAll(tmp)
return fmt.Errorf("go build -o %v cmd/pprof: %v\n%s", pprofExe, err, string(out))
}
return nil
}
// See also runtime/pprof.cpuProfilingBroken.
func mustHaveCPUProfiling(t *testing.T) {
switch runtime.GOOS {
case "plan9":
t.Skipf("skipping on %s, unimplemented", runtime.GOOS)
case "aix":
t.Skipf("skipping on %s, issue 45170", runtime.GOOS)
case "ios", "dragonfly", "netbsd", "illumos", "solaris":
t.Skipf("skipping on %s, issue 13841", runtime.GOOS)
case "openbsd":
if runtime.GOARCH == "arm" || runtime.GOARCH == "arm64" {
t.Skipf("skipping on %s/%s, issue 13841", runtime.GOOS, runtime.GOARCH)
}
}
}
func mustHaveDisasm(t *testing.T) {
switch runtime.GOARCH {
case "mips", "mipsle", "mips64", "mips64le":
t.Skipf("skipping on %s, issue 12559", runtime.GOARCH)
case "riscv64":
t.Skipf("skipping on %s, issue 36738", runtime.GOARCH)
case "s390x":
t.Skipf("skipping on %s, issue 15255", runtime.GOARCH)
}
// Skip PIE platforms, pprof can't disassemble PIE.
if runtime.GOOS == "windows" {
t.Skipf("skipping on %s, issue 46639", runtime.GOOS)
}
if runtime.GOOS == "darwin" && runtime.GOARCH == "arm64" {
t.Skipf("skipping on %s/%s, issue 46639", runtime.GOOS, runtime.GOARCH)
}
}
// TestDisasm verifies that cmd/pprof can successfully disassemble functions.
//
// This is a regression test for issue 46636.
func TestDisasm(t *testing.T) {
mustHaveCPUProfiling(t)
mustHaveDisasm(t)
testenv.MustHaveGoBuild(t)
tmpdir := t.TempDir()
cpuExe := filepath.Join(tmpdir, "cpu.exe")
cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", cpuExe, "cpu.go")
cmd.Dir = "testdata/"
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("build failed: %v\n%s", err, out)
}
profile := filepath.Join(tmpdir, "cpu.pprof")
cmd = exec.Command(cpuExe, "-output", profile)
out, err = cmd.CombinedOutput()
if err != nil {
t.Fatalf("cpu failed: %v\n%s", err, out)
}
cmd = exec.Command(pprofExe, "-disasm", "main.main", cpuExe, profile)
out, err = cmd.CombinedOutput()
if err != nil {
t.Fatalf("pprof failed: %v\n%s", err, out)
}
sout := string(out)
want := "ROUTINE ======================== main.main"
if !strings.Contains(sout, want) {
t.Errorf("pprof disasm got %s want contains %q", sout, want)
}
}

41
src/cmd/pprof/testdata/cpu.go vendored Normal file
View File

@ -0,0 +1,41 @@
// Copyright 2021 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 main
import (
"flag"
"fmt"
"os"
"runtime/pprof"
"time"
)
var output = flag.String("output", "", "pprof profile output file")
func main() {
flag.Parse()
if *output == "" {
fmt.Fprintf(os.Stderr, "usage: %s -output file.pprof\n", os.Args[0])
os.Exit(2)
}
f, err := os.Create(*output)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(2)
}
defer f.Close()
if err := pprof.StartCPUProfile(f); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(2)
}
defer pprof.StopCPUProfile()
// Spin for long enough to collect some samples.
start := time.Now()
for time.Since(start) < time.Second {
}
}

View File

@ -2838,9 +2838,10 @@ func TestTxStmtDeadlock(t *testing.T) {
db := newTestDB(t, "people") db := newTestDB(t, "people")
defer closeDB(t, db) defer closeDB(t, db)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Millisecond) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
tx, err := db.BeginTx(ctx, nil) tx, err := db.BeginTx(ctx, nil)
cancel()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -23,6 +23,16 @@ type Image interface {
Set(x, y int, c color.Color) Set(x, y int, c color.Color)
} }
// RGBA64Image extends both the Image and image.RGBA64Image interfaces with a
// SetRGBA64 method to change a single pixel. SetRGBA64 is equivalent to
// calling Set, but it can avoid allocations from converting concrete color
// types to the color.Color interface type.
type RGBA64Image interface {
image.RGBA64Image
Set(x, y int, c color.Color)
SetRGBA64(x, y int, c color.RGBA64)
}
// Quantizer produces a palette for an image. // Quantizer produces a palette for an image.
type Quantizer interface { type Quantizer interface {
// Quantize appends up to cap(p) - len(p) colors to p and returns the // Quantize appends up to cap(p) - len(p) colors to p and returns the

View File

@ -45,6 +45,17 @@ type Image interface {
At(x, y int) color.Color At(x, y int) color.Color
} }
// RGBA64Image is an Image whose pixels can be converted directly to a
// color.RGBA64.
type RGBA64Image interface {
// RGBA64At returns the RGBA64 color of the pixel at (x, y). It is
// equivalent to calling At(x, y).RGBA() and converting the resulting
// 32-bit return values to a color.RGBA64, but it can avoid allocations
// from converting concrete color types to the color.Color interface type.
RGBA64At(x, y int) color.RGBA64
Image
}
// PalettedImage is an image whose colors may come from a limited palette. // PalettedImage is an image whose colors may come from a limited palette.
// If m is a PalettedImage and m.ColorModel() returns a color.Palette p, // If m is a PalettedImage and m.ColorModel() returns a color.Palette p,
// then m.At(x, y) should be equivalent to p[m.ColorIndexAt(x, y)]. If m's // then m.At(x, y) should be equivalent to p[m.ColorIndexAt(x, y)]. If m's
@ -90,6 +101,24 @@ func (p *RGBA) At(x, y int) color.Color {
return p.RGBAAt(x, y) return p.RGBAAt(x, y)
} }
func (p *RGBA) RGBA64At(x, y int) color.RGBA64 {
if !(Point{x, y}.In(p.Rect)) {
return color.RGBA64{}
}
i := p.PixOffset(x, y)
s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
r := uint16(s[0])
g := uint16(s[1])
b := uint16(s[2])
a := uint16(s[3])
return color.RGBA64{
(r << 8) | r,
(g << 8) | g,
(b << 8) | b,
(a << 8) | a,
}
}
func (p *RGBA) RGBAAt(x, y int) color.RGBA { func (p *RGBA) RGBAAt(x, y int) color.RGBA {
if !(Point{x, y}.In(p.Rect)) { if !(Point{x, y}.In(p.Rect)) {
return color.RGBA{} return color.RGBA{}
@ -118,6 +147,18 @@ func (p *RGBA) Set(x, y int, c color.Color) {
s[3] = c1.A s[3] = c1.A
} }
func (p *RGBA) SetRGBA64(x, y int, c color.RGBA64) {
if !(Point{x, y}.In(p.Rect)) {
return
}
i := p.PixOffset(x, y)
s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
s[0] = uint8(c.R >> 8)
s[1] = uint8(c.G >> 8)
s[2] = uint8(c.B >> 8)
s[3] = uint8(c.A >> 8)
}
func (p *RGBA) SetRGBA(x, y int, c color.RGBA) { func (p *RGBA) SetRGBA(x, y int, c color.RGBA) {
if !(Point{x, y}.In(p.Rect)) { if !(Point{x, y}.In(p.Rect)) {
return return
@ -311,6 +352,11 @@ func (p *NRGBA) At(x, y int) color.Color {
return p.NRGBAAt(x, y) return p.NRGBAAt(x, y)
} }
func (p *NRGBA) RGBA64At(x, y int) color.RGBA64 {
r, g, b, a := p.NRGBAAt(x, y).RGBA()
return color.RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)}
}
func (p *NRGBA) NRGBAAt(x, y int) color.NRGBA { func (p *NRGBA) NRGBAAt(x, y int) color.NRGBA {
if !(Point{x, y}.In(p.Rect)) { if !(Point{x, y}.In(p.Rect)) {
return color.NRGBA{} return color.NRGBA{}
@ -339,6 +385,24 @@ func (p *NRGBA) Set(x, y int, c color.Color) {
s[3] = c1.A s[3] = c1.A
} }
func (p *NRGBA) SetRGBA64(x, y int, c color.RGBA64) {
if !(Point{x, y}.In(p.Rect)) {
return
}
r, g, b, a := uint32(c.R), uint32(c.G), uint32(c.B), uint32(c.A)
if (a != 0) && (a != 0xffff) {
r = (r * 0xffff) / a
g = (g * 0xffff) / a
b = (b * 0xffff) / a
}
i := p.PixOffset(x, y)
s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
s[0] = uint8(r >> 8)
s[1] = uint8(g >> 8)
s[2] = uint8(b >> 8)
s[3] = uint8(a >> 8)
}
func (p *NRGBA) SetNRGBA(x, y int, c color.NRGBA) { func (p *NRGBA) SetNRGBA(x, y int, c color.NRGBA) {
if !(Point{x, y}.In(p.Rect)) { if !(Point{x, y}.In(p.Rect)) {
return return
@ -415,6 +479,11 @@ func (p *NRGBA64) At(x, y int) color.Color {
return p.NRGBA64At(x, y) return p.NRGBA64At(x, y)
} }
func (p *NRGBA64) RGBA64At(x, y int) color.RGBA64 {
r, g, b, a := p.NRGBA64At(x, y).RGBA()
return color.RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)}
}
func (p *NRGBA64) NRGBA64At(x, y int) color.NRGBA64 { func (p *NRGBA64) NRGBA64At(x, y int) color.NRGBA64 {
if !(Point{x, y}.In(p.Rect)) { if !(Point{x, y}.In(p.Rect)) {
return color.NRGBA64{} return color.NRGBA64{}
@ -452,6 +521,28 @@ func (p *NRGBA64) Set(x, y int, c color.Color) {
s[7] = uint8(c1.A) s[7] = uint8(c1.A)
} }
func (p *NRGBA64) SetRGBA64(x, y int, c color.RGBA64) {
if !(Point{x, y}.In(p.Rect)) {
return
}
r, g, b, a := uint32(c.R), uint32(c.G), uint32(c.B), uint32(c.A)
if (a != 0) && (a != 0xffff) {
r = (r * 0xffff) / a
g = (g * 0xffff) / a
b = (b * 0xffff) / a
}
i := p.PixOffset(x, y)
s := p.Pix[i : i+8 : i+8] // Small cap improves performance, see https://golang.org/issue/27857
s[0] = uint8(r >> 8)
s[1] = uint8(r)
s[2] = uint8(g >> 8)
s[3] = uint8(g)
s[4] = uint8(b >> 8)
s[5] = uint8(b)
s[6] = uint8(a >> 8)
s[7] = uint8(a)
}
func (p *NRGBA64) SetNRGBA64(x, y int, c color.NRGBA64) { func (p *NRGBA64) SetNRGBA64(x, y int, c color.NRGBA64) {
if !(Point{x, y}.In(p.Rect)) { if !(Point{x, y}.In(p.Rect)) {
return return
@ -532,6 +623,12 @@ func (p *Alpha) At(x, y int) color.Color {
return p.AlphaAt(x, y) return p.AlphaAt(x, y)
} }
func (p *Alpha) RGBA64At(x, y int) color.RGBA64 {
a := uint16(p.AlphaAt(x, y).A)
a |= a << 8
return color.RGBA64{a, a, a, a}
}
func (p *Alpha) AlphaAt(x, y int) color.Alpha { func (p *Alpha) AlphaAt(x, y int) color.Alpha {
if !(Point{x, y}.In(p.Rect)) { if !(Point{x, y}.In(p.Rect)) {
return color.Alpha{} return color.Alpha{}
@ -554,6 +651,14 @@ func (p *Alpha) Set(x, y int, c color.Color) {
p.Pix[i] = color.AlphaModel.Convert(c).(color.Alpha).A p.Pix[i] = color.AlphaModel.Convert(c).(color.Alpha).A
} }
func (p *Alpha) SetRGBA64(x, y int, c color.RGBA64) {
if !(Point{x, y}.In(p.Rect)) {
return
}
i := p.PixOffset(x, y)
p.Pix[i] = uint8(c.A >> 8)
}
func (p *Alpha) SetAlpha(x, y int, c color.Alpha) { func (p *Alpha) SetAlpha(x, y int, c color.Alpha) {
if !(Point{x, y}.In(p.Rect)) { if !(Point{x, y}.In(p.Rect)) {
return return
@ -626,6 +731,11 @@ func (p *Alpha16) At(x, y int) color.Color {
return p.Alpha16At(x, y) return p.Alpha16At(x, y)
} }
func (p *Alpha16) RGBA64At(x, y int) color.RGBA64 {
a := p.Alpha16At(x, y).A
return color.RGBA64{a, a, a, a}
}
func (p *Alpha16) Alpha16At(x, y int) color.Alpha16 { func (p *Alpha16) Alpha16At(x, y int) color.Alpha16 {
if !(Point{x, y}.In(p.Rect)) { if !(Point{x, y}.In(p.Rect)) {
return color.Alpha16{} return color.Alpha16{}
@ -650,6 +760,15 @@ func (p *Alpha16) Set(x, y int, c color.Color) {
p.Pix[i+1] = uint8(c1.A) p.Pix[i+1] = uint8(c1.A)
} }
func (p *Alpha16) SetRGBA64(x, y int, c color.RGBA64) {
if !(Point{x, y}.In(p.Rect)) {
return
}
i := p.PixOffset(x, y)
p.Pix[i+0] = uint8(c.A >> 8)
p.Pix[i+1] = uint8(c.A)
}
func (p *Alpha16) SetAlpha16(x, y int, c color.Alpha16) { func (p *Alpha16) SetAlpha16(x, y int, c color.Alpha16) {
if !(Point{x, y}.In(p.Rect)) { if !(Point{x, y}.In(p.Rect)) {
return return
@ -723,6 +842,12 @@ func (p *Gray) At(x, y int) color.Color {
return p.GrayAt(x, y) return p.GrayAt(x, y)
} }
func (p *Gray) RGBA64At(x, y int) color.RGBA64 {
gray := uint16(p.GrayAt(x, y).Y)
gray |= gray << 8
return color.RGBA64{gray, gray, gray, 0xffff}
}
func (p *Gray) GrayAt(x, y int) color.Gray { func (p *Gray) GrayAt(x, y int) color.Gray {
if !(Point{x, y}.In(p.Rect)) { if !(Point{x, y}.In(p.Rect)) {
return color.Gray{} return color.Gray{}
@ -745,6 +870,16 @@ func (p *Gray) Set(x, y int, c color.Color) {
p.Pix[i] = color.GrayModel.Convert(c).(color.Gray).Y p.Pix[i] = color.GrayModel.Convert(c).(color.Gray).Y
} }
func (p *Gray) SetRGBA64(x, y int, c color.RGBA64) {
if !(Point{x, y}.In(p.Rect)) {
return
}
// This formula is the same as in color.grayModel.
gray := (19595*uint32(c.R) + 38470*uint32(c.G) + 7471*uint32(c.B) + 1<<15) >> 24
i := p.PixOffset(x, y)
p.Pix[i] = uint8(gray)
}
func (p *Gray) SetGray(x, y int, c color.Gray) { func (p *Gray) SetGray(x, y int, c color.Gray) {
if !(Point{x, y}.In(p.Rect)) { if !(Point{x, y}.In(p.Rect)) {
return return
@ -804,6 +939,11 @@ func (p *Gray16) At(x, y int) color.Color {
return p.Gray16At(x, y) return p.Gray16At(x, y)
} }
func (p *Gray16) RGBA64At(x, y int) color.RGBA64 {
gray := p.Gray16At(x, y).Y
return color.RGBA64{gray, gray, gray, 0xffff}
}
func (p *Gray16) Gray16At(x, y int) color.Gray16 { func (p *Gray16) Gray16At(x, y int) color.Gray16 {
if !(Point{x, y}.In(p.Rect)) { if !(Point{x, y}.In(p.Rect)) {
return color.Gray16{} return color.Gray16{}
@ -828,6 +968,17 @@ func (p *Gray16) Set(x, y int, c color.Color) {
p.Pix[i+1] = uint8(c1.Y) p.Pix[i+1] = uint8(c1.Y)
} }
func (p *Gray16) SetRGBA64(x, y int, c color.RGBA64) {
if !(Point{x, y}.In(p.Rect)) {
return
}
// This formula is the same as in color.gray16Model.
gray := (19595*uint32(c.R) + 38470*uint32(c.G) + 7471*uint32(c.B) + 1<<15) >> 16
i := p.PixOffset(x, y)
p.Pix[i+0] = uint8(gray >> 8)
p.Pix[i+1] = uint8(gray)
}
func (p *Gray16) SetGray16(x, y int, c color.Gray16) { func (p *Gray16) SetGray16(x, y int, c color.Gray16) {
if !(Point{x, y}.In(p.Rect)) { if !(Point{x, y}.In(p.Rect)) {
return return
@ -888,6 +1039,11 @@ func (p *CMYK) At(x, y int) color.Color {
return p.CMYKAt(x, y) return p.CMYKAt(x, y)
} }
func (p *CMYK) RGBA64At(x, y int) color.RGBA64 {
r, g, b, a := p.CMYKAt(x, y).RGBA()
return color.RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)}
}
func (p *CMYK) CMYKAt(x, y int) color.CMYK { func (p *CMYK) CMYKAt(x, y int) color.CMYK {
if !(Point{x, y}.In(p.Rect)) { if !(Point{x, y}.In(p.Rect)) {
return color.CMYK{} return color.CMYK{}
@ -916,6 +1072,19 @@ func (p *CMYK) Set(x, y int, c color.Color) {
s[3] = c1.K s[3] = c1.K
} }
func (p *CMYK) SetRGBA64(x, y int, c color.RGBA64) {
if !(Point{x, y}.In(p.Rect)) {
return
}
cc, mm, yy, kk := color.RGBToCMYK(uint8(c.R>>8), uint8(c.G>>8), uint8(c.B>>8))
i := p.PixOffset(x, y)
s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
s[0] = cc
s[1] = mm
s[2] = yy
s[3] = kk
}
func (p *CMYK) SetCMYK(x, y int, c color.CMYK) { func (p *CMYK) SetCMYK(x, y int, c color.CMYK) {
if !(Point{x, y}.In(p.Rect)) { if !(Point{x, y}.In(p.Rect)) {
return return
@ -988,6 +1157,26 @@ func (p *Paletted) At(x, y int) color.Color {
return p.Palette[p.Pix[i]] return p.Palette[p.Pix[i]]
} }
func (p *Paletted) RGBA64At(x, y int) color.RGBA64 {
if len(p.Palette) == 0 {
return color.RGBA64{}
}
c := color.Color(nil)
if !(Point{x, y}.In(p.Rect)) {
c = p.Palette[0]
} else {
i := p.PixOffset(x, y)
c = p.Palette[p.Pix[i]]
}
r, g, b, a := c.RGBA()
return color.RGBA64{
uint16(r),
uint16(g),
uint16(b),
uint16(a),
}
}
// PixOffset returns the index of the first element of Pix that corresponds to // PixOffset returns the index of the first element of Pix that corresponds to
// the pixel at (x, y). // the pixel at (x, y).
func (p *Paletted) PixOffset(x, y int) int { func (p *Paletted) PixOffset(x, y int) int {
@ -1002,6 +1191,14 @@ func (p *Paletted) Set(x, y int, c color.Color) {
p.Pix[i] = uint8(p.Palette.Index(c)) p.Pix[i] = uint8(p.Palette.Index(c))
} }
func (p *Paletted) SetRGBA64(x, y int, c color.RGBA64) {
if !(Point{x, y}.In(p.Rect)) {
return
}
i := p.PixOffset(x, y)
p.Pix[i] = uint8(p.Palette.Index(c))
}
func (p *Paletted) ColorIndexAt(x, y int) uint8 { func (p *Paletted) ColorIndexAt(x, y int) uint8 {
if !(Point{x, y}.In(p.Rect)) { if !(Point{x, y}.In(p.Rect)) {
return 0 return 0

View File

@ -6,6 +6,7 @@ package image
import ( import (
"image/color" "image/color"
"image/color/palette"
"testing" "testing"
) )
@ -191,6 +192,80 @@ func Test16BitsPerColorChannel(t *testing.T) {
} }
} }
func TestRGBA64Image(t *testing.T) {
// memset sets every element of s to v.
memset := func(s []byte, v byte) {
for i := range s {
s[i] = v
}
}
r := Rect(0, 0, 3, 2)
testCases := []Image{
NewAlpha(r),
NewAlpha16(r),
NewCMYK(r),
NewGray(r),
NewGray16(r),
NewNRGBA(r),
NewNRGBA64(r),
NewNYCbCrA(r, YCbCrSubsampleRatio444),
NewPaletted(r, palette.Plan9),
NewRGBA(r),
NewRGBA64(r),
NewYCbCr(r, YCbCrSubsampleRatio444),
}
for _, tc := range testCases {
switch tc := tc.(type) {
// Most of the concrete image types in the testCases implement the
// draw.RGBA64Image interface: they have a SetRGBA64 method. We use an
// interface literal here, instead of importing "image/draw", to avoid
// an import cycle.
//
// The YCbCr and NYCbCrA types are special-cased. Chroma subsampling
// means that setting one pixel can modify neighboring pixels. They
// don't have Set or SetRGBA64 methods because that side effect could
// be surprising. Here, we just memset the channel buffers instead.
case interface {
SetRGBA64(x, y int, c color.RGBA64)
}:
tc.SetRGBA64(1, 1, color.RGBA64{0x7FFF, 0x3FFF, 0x0000, 0x7FFF})
case *NYCbCrA:
memset(tc.YCbCr.Y, 0x77)
memset(tc.YCbCr.Cb, 0x88)
memset(tc.YCbCr.Cr, 0x99)
memset(tc.A, 0xAA)
case *YCbCr:
memset(tc.Y, 0x77)
memset(tc.Cb, 0x88)
memset(tc.Cr, 0x99)
default:
t.Errorf("could not initialize pixels for %T", tc)
continue
}
// Check that RGBA64At(x, y) is equivalent to At(x, y).RGBA().
rgba64Image, ok := tc.(RGBA64Image)
if !ok {
t.Errorf("%T is not an RGBA64Image", tc)
continue
}
got := rgba64Image.RGBA64At(1, 1)
wantR, wantG, wantB, wantA := tc.At(1, 1).RGBA()
if (uint32(got.R) != wantR) || (uint32(got.G) != wantG) ||
(uint32(got.B) != wantB) || (uint32(got.A) != wantA) {
t.Errorf("%T:\ngot (0x%04X, 0x%04X, 0x%04X, 0x%04X)\n"+
"want (0x%04X, 0x%04X, 0x%04X, 0x%04X)", tc,
got.R, got.G, got.B, got.A,
wantR, wantG, wantB, wantA)
continue
}
}
}
func BenchmarkAt(b *testing.B) { func BenchmarkAt(b *testing.B) {
for _, tc := range testImages { for _, tc := range testImages {
b.Run(tc.name, func(b *testing.B) { b.Run(tc.name, func(b *testing.B) {

View File

@ -71,6 +71,11 @@ func (p *YCbCr) At(x, y int) color.Color {
return p.YCbCrAt(x, y) return p.YCbCrAt(x, y)
} }
func (p *YCbCr) RGBA64At(x, y int) color.RGBA64 {
r, g, b, a := p.YCbCrAt(x, y).RGBA()
return color.RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)}
}
func (p *YCbCr) YCbCrAt(x, y int) color.YCbCr { func (p *YCbCr) YCbCrAt(x, y int) color.YCbCr {
if !(Point{x, y}.In(p.Rect)) { if !(Point{x, y}.In(p.Rect)) {
return color.YCbCr{} return color.YCbCr{}
@ -210,6 +215,11 @@ func (p *NYCbCrA) At(x, y int) color.Color {
return p.NYCbCrAAt(x, y) return p.NYCbCrAAt(x, y)
} }
func (p *NYCbCrA) RGBA64At(x, y int) color.RGBA64 {
r, g, b, a := p.NYCbCrAAt(x, y).RGBA()
return color.RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)}
}
func (p *NYCbCrA) NYCbCrAAt(x, y int) color.NYCbCrA { func (p *NYCbCrA) NYCbCrAAt(x, y int) color.NYCbCrA {
if !(Point{X: x, Y: y}.In(p.Rect)) { if !(Point{X: x, Y: y}.In(p.Rect)) {
return color.NYCbCrA{} return color.NYCbCrA{}

View File

@ -12,9 +12,6 @@
// The default Source is safe for concurrent use by multiple goroutines, but // The default Source is safe for concurrent use by multiple goroutines, but
// Sources created by NewSource are not. // Sources created by NewSource are not.
// //
// Mathematical interval notation such as [0, n) is used throughout the
// documentation for this package.
//
// This package's outputs might be easily predictable regardless of how it's // This package's outputs might be easily predictable regardless of how it's
// seeded. For random numbers suitable for security-sensitive work, see the // seeded. For random numbers suitable for security-sensitive work, see the
// crypto/rand package. // crypto/rand package.
@ -106,7 +103,7 @@ func (r *Rand) Int() int {
return int(u << 1 >> 1) // clear sign bit if int == int32 return int(u << 1 >> 1) // clear sign bit if int == int32
} }
// Int63n returns, as an int64, a non-negative pseudo-random number in [0,n). // Int63n returns, as an int64, a non-negative pseudo-random number in the half-open interval [0,n).
// It panics if n <= 0. // It panics if n <= 0.
func (r *Rand) Int63n(n int64) int64 { func (r *Rand) Int63n(n int64) int64 {
if n <= 0 { if n <= 0 {
@ -123,7 +120,7 @@ func (r *Rand) Int63n(n int64) int64 {
return v % n return v % n
} }
// Int31n returns, as an int32, a non-negative pseudo-random number in [0,n). // Int31n returns, as an int32, a non-negative pseudo-random number in the half-open interval [0,n).
// It panics if n <= 0. // It panics if n <= 0.
func (r *Rand) Int31n(n int32) int32 { func (r *Rand) Int31n(n int32) int32 {
if n <= 0 { if n <= 0 {
@ -140,7 +137,7 @@ func (r *Rand) Int31n(n int32) int32 {
return v % n return v % n
} }
// int31n returns, as an int32, a non-negative pseudo-random number in [0,n). // int31n returns, as an int32, a non-negative pseudo-random number in the half-open interval [0,n).
// n must be > 0, but int31n does not check this; the caller must ensure it. // n must be > 0, but int31n does not check this; the caller must ensure it.
// int31n exists because Int31n is inefficient, but Go 1 compatibility // int31n exists because Int31n is inefficient, but Go 1 compatibility
// requires that the stream of values produced by math/rand remain unchanged. // requires that the stream of values produced by math/rand remain unchanged.
@ -164,7 +161,7 @@ func (r *Rand) int31n(n int32) int32 {
return int32(prod >> 32) return int32(prod >> 32)
} }
// Intn returns, as an int, a non-negative pseudo-random number in [0,n). // Intn returns, as an int, a non-negative pseudo-random number in the half-open interval [0,n).
// It panics if n <= 0. // It panics if n <= 0.
func (r *Rand) Intn(n int) int { func (r *Rand) Intn(n int) int {
if n <= 0 { if n <= 0 {
@ -176,7 +173,7 @@ func (r *Rand) Intn(n int) int {
return int(r.Int63n(int64(n))) return int(r.Int63n(int64(n)))
} }
// Float64 returns, as a float64, a pseudo-random number in [0.0,1.0). // Float64 returns, as a float64, a pseudo-random number in the half-open interval [0.0,1.0).
func (r *Rand) Float64() float64 { func (r *Rand) Float64() float64 {
// A clearer, simpler implementation would be: // A clearer, simpler implementation would be:
// return float64(r.Int63n(1<<53)) / (1<<53) // return float64(r.Int63n(1<<53)) / (1<<53)
@ -202,7 +199,7 @@ again:
return f return f
} }
// Float32 returns, as a float32, a pseudo-random number in [0.0,1.0). // Float32 returns, as a float32, a pseudo-random number in the half-open interval [0.0,1.0).
func (r *Rand) Float32() float32 { func (r *Rand) Float32() float32 {
// Same rationale as in Float64: we want to preserve the Go 1 value // Same rationale as in Float64: we want to preserve the Go 1 value
// stream except we want to fix it not to return 1.0 // stream except we want to fix it not to return 1.0
@ -215,7 +212,8 @@ again:
return f return f
} }
// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n). // Perm returns, as a slice of n ints, a pseudo-random permutation of the integers
// in the half-open interval [0,n).
func (r *Rand) Perm(n int) []int { func (r *Rand) Perm(n int) []int {
m := make([]int, n) m := make([]int, n)
// In the following loop, the iteration when i=0 always swaps m[0] with m[0]. // In the following loop, the iteration when i=0 always swaps m[0] with m[0].
@ -323,31 +321,31 @@ func Int31() int32 { return globalRand.Int31() }
// Int returns a non-negative pseudo-random int from the default Source. // Int returns a non-negative pseudo-random int from the default Source.
func Int() int { return globalRand.Int() } func Int() int { return globalRand.Int() }
// Int63n returns, as an int64, a non-negative pseudo-random number in [0,n) // Int63n returns, as an int64, a non-negative pseudo-random number in the half-open interval [0,n)
// from the default Source. // from the default Source.
// It panics if n <= 0. // It panics if n <= 0.
func Int63n(n int64) int64 { return globalRand.Int63n(n) } func Int63n(n int64) int64 { return globalRand.Int63n(n) }
// Int31n returns, as an int32, a non-negative pseudo-random number in [0,n) // Int31n returns, as an int32, a non-negative pseudo-random number in the half-open interval [0,n)
// from the default Source. // from the default Source.
// It panics if n <= 0. // It panics if n <= 0.
func Int31n(n int32) int32 { return globalRand.Int31n(n) } func Int31n(n int32) int32 { return globalRand.Int31n(n) }
// Intn returns, as an int, a non-negative pseudo-random number in [0,n) // Intn returns, as an int, a non-negative pseudo-random number in the half-open interval [0,n)
// from the default Source. // from the default Source.
// It panics if n <= 0. // It panics if n <= 0.
func Intn(n int) int { return globalRand.Intn(n) } func Intn(n int) int { return globalRand.Intn(n) }
// Float64 returns, as a float64, a pseudo-random number in [0.0,1.0) // Float64 returns, as a float64, a pseudo-random number in the half-open interval [0.0,1.0)
// from the default Source. // from the default Source.
func Float64() float64 { return globalRand.Float64() } func Float64() float64 { return globalRand.Float64() }
// Float32 returns, as a float32, a pseudo-random number in [0.0,1.0) // Float32 returns, as a float32, a pseudo-random number in the half-open interval [0.0,1.0)
// from the default Source. // from the default Source.
func Float32() float32 { return globalRand.Float32() } func Float32() float32 { return globalRand.Float32() }
// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n) // Perm returns, as a slice of n ints, a pseudo-random permutation of the integers
// from the default Source. // in the half-open interval [0,n) from the default Source.
func Perm(n int) []int { return globalRand.Perm(n) } func Perm(n int) []int { return globalRand.Perm(n) }
// Shuffle pseudo-randomizes the order of elements using the default Source. // Shuffle pseudo-randomizes the order of elements using the default Source.

View File

@ -32,6 +32,11 @@ import (
// The current value is set based on flakes observed in the Go builders. // The current value is set based on flakes observed in the Go builders.
var settleTime = 100 * time.Millisecond var settleTime = 100 * time.Millisecond
// fatalWaitingTime is an absurdly long time to wait for signals to be
// delivered but, using it, we (hopefully) eliminate test flakes on the
// build servers. See #46736 for discussion.
var fatalWaitingTime = 30 * time.Second
func init() { func init() {
if testenv.Builder() == "solaris-amd64-oraclerel" { if testenv.Builder() == "solaris-amd64-oraclerel" {
// The solaris-amd64-oraclerel builder has been observed to time out in // The solaris-amd64-oraclerel builder has been observed to time out in
@ -84,7 +89,7 @@ func waitSig1(t *testing.T, c <-chan os.Signal, sig os.Signal, all bool) {
// General user code should filter out all unexpected signals instead of just // General user code should filter out all unexpected signals instead of just
// SIGURG, but since os/signal is tightly coupled to the runtime it seems // SIGURG, but since os/signal is tightly coupled to the runtime it seems
// appropriate to be stricter here. // appropriate to be stricter here.
for time.Since(start) < settleTime { for time.Since(start) < fatalWaitingTime {
select { select {
case s := <-c: case s := <-c:
if s == sig { if s == sig {
@ -97,7 +102,7 @@ func waitSig1(t *testing.T, c <-chan os.Signal, sig os.Signal, all bool) {
timer.Reset(settleTime / 10) timer.Reset(settleTime / 10)
} }
} }
t.Fatalf("timeout after %v waiting for %v", settleTime, sig) t.Fatalf("timeout after %v waiting for %v", fatalWaitingTime, sig)
} }
// quiesce waits until we can be reasonably confident that all pending signals // quiesce waits until we can be reasonably confident that all pending signals

View File

@ -12,12 +12,15 @@ import (
func ExampleFrames() { func ExampleFrames() {
c := func() { c := func() {
// Ask runtime.Callers for up to 10 pcs, including runtime.Callers itself. // Ask runtime.Callers for up to 10 PCs, including runtime.Callers itself.
pc := make([]uintptr, 10) pc := make([]uintptr, 10)
n := runtime.Callers(0, pc) n := runtime.Callers(0, pc)
if n == 0 { if n == 0 {
// No pcs available. Stop now. // No PCs available. This can happen if the first argument to
// This can happen if the first argument to runtime.Callers is large. // runtime.Callers is large.
//
// Return now to avoid processing the zero Frame that would
// otherwise be returned by frames.Next below.
return return
} }
@ -25,9 +28,12 @@ func ExampleFrames() {
frames := runtime.CallersFrames(pc) frames := runtime.CallersFrames(pc)
// Loop to get frames. // Loop to get frames.
// A fixed number of pcs can expand to an indefinite number of Frames. // A fixed number of PCs can expand to an indefinite number of Frames.
for { for {
frame, more := frames.Next() frame, more := frames.Next()
// Process this frame.
//
// To keep this example's output stable // To keep this example's output stable
// even if there are changes in the testing package, // even if there are changes in the testing package,
// stop unwinding when we leave package runtime. // stop unwinding when we leave package runtime.
@ -35,6 +41,8 @@ func ExampleFrames() {
break break
} }
fmt.Printf("- more:%v | %s\n", more, frame.Function) fmt.Printf("- more:%v | %s\n", more, frame.Function)
// Check whether there are more frames to process after this one.
if !more { if !more {
break break
} }

View File

@ -261,6 +261,27 @@ func parseProfile(t *testing.T, valBytes []byte, f func(uintptr, []*profile.Loca
return p return p
} }
func cpuProfilingBroken() bool {
switch runtime.GOOS {
case "plan9":
// Profiling unimplemented.
return true
case "aix":
// See https://golang.org/issue/45170.
return true
case "ios", "dragonfly", "netbsd", "illumos", "solaris":
// See https://golang.org/issue/13841.
return true
case "openbsd":
if runtime.GOARCH == "arm" || runtime.GOARCH == "arm64" {
// See https://golang.org/issue/13841.
return true
}
}
return false
}
// testCPUProfile runs f under the CPU profiler, checking for some conditions specified by need, // testCPUProfile runs f under the CPU profiler, checking for some conditions specified by need,
// as interpreted by matches, and returns the parsed profile. // as interpreted by matches, and returns the parsed profile.
func testCPUProfile(t *testing.T, matches matchFunc, need []string, avoid []string, f func(dur time.Duration)) *profile.Profile { func testCPUProfile(t *testing.T, matches matchFunc, need []string, avoid []string, f func(dur time.Duration)) *profile.Profile {
@ -276,16 +297,7 @@ func testCPUProfile(t *testing.T, matches matchFunc, need []string, avoid []stri
t.Skip("skipping on plan9") t.Skip("skipping on plan9")
} }
broken := false broken := cpuProfilingBroken()
switch runtime.GOOS {
// See https://golang.org/issue/45170 for AIX.
case "ios", "dragonfly", "netbsd", "illumos", "solaris", "aix":
broken = true
case "openbsd":
if runtime.GOARCH == "arm" || runtime.GOARCH == "arm64" {
broken = true
}
}
maxDuration := 5 * time.Second maxDuration := 5 * time.Second
if testing.Short() && broken { if testing.Short() && broken {
@ -612,7 +624,7 @@ func growstack1() {
//go:noinline //go:noinline
func growstack(n int) { func growstack(n int) {
var buf [8 << 16]byte var buf [8 << 18]byte
use(buf) use(buf)
if n > 0 { if n > 0 {
growstack(n - 1) growstack(n - 1)
@ -620,7 +632,7 @@ func growstack(n int) {
} }
//go:noinline //go:noinline
func use(x [8 << 16]byte) {} func use(x [8 << 18]byte) {}
func TestBlockProfile(t *testing.T) { func TestBlockProfile(t *testing.T) {
type TestCase struct { type TestCase struct {

View File

@ -281,6 +281,8 @@ func setProcessCPUProfiler(hz int32) {
it.it_value = it.it_interval it.it_value = it.it_interval
setitimer(_ITIMER_PROF, &it, nil) setitimer(_ITIMER_PROF, &it, nil)
} else { } else {
setitimer(_ITIMER_PROF, &itimerval{}, nil)
// If the Go signal handler should be disabled by default, // If the Go signal handler should be disabled by default,
// switch back to the signal handler that was installed // switch back to the signal handler that was installed
// when we enabled profiling. We don't try to handle the case // when we enabled profiling. We don't try to handle the case
@ -304,8 +306,6 @@ func setProcessCPUProfiler(hz int32) {
setsig(_SIGPROF, h) setsig(_SIGPROF, h)
} }
} }
setitimer(_ITIMER_PROF, &itimerval{}, nil)
} }
} }
@ -383,7 +383,7 @@ func preemptM(mp *m) {
//go:nosplit //go:nosplit
func sigFetchG(c *sigctxt) *g { func sigFetchG(c *sigctxt) *g {
switch GOARCH { switch GOARCH {
case "arm", "arm64": case "arm", "arm64", "ppc64", "ppc64le":
if !iscgo && inVDSOPage(c.sigpc()) { if !iscgo && inVDSOPage(c.sigpc()) {
// When using cgo, we save the g on TLS and load it from there // When using cgo, we save the g on TLS and load it from there
// in sigtramp. Just use that. // in sigtramp. Just use that.

View File

@ -69,8 +69,15 @@ func CallersFrames(callers []uintptr) *Frames {
return f return f
} }
// Next returns frame information for the next caller. // Next returns a Frame representing the next call frame in the slice
// If more is false, there are no more callers (the Frame value is valid). // of PC values. If it has already returned all call frames, Next
// returns a zero Frame.
//
// The more result indicates whether the next call to Next will return
// a valid Frame. It does not necessarily indicate whether this call
// returned one.
//
// See the Frames example for idiomatic usage.
func (ci *Frames) Next() (frame Frame, more bool) { func (ci *Frames) Next() (frame Frame, more bool) {
for len(ci.frames) < 2 { for len(ci.frames) < 2 {
// Find the next frame. // Find the next frame.

View File

@ -220,7 +220,37 @@ noswitch:
RLDICR $0, R1, $59, R1 // Align for C code RLDICR $0, R1, $59, R1 // Align for C code
MOVD R12, CTR MOVD R12, CTR
MOVD R1, R4 MOVD R1, R4
// Store g on gsignal's stack, so if we receive a signal
// during VDSO code we can find the g.
// If we don't have a signal stack, we won't receive signal,
// so don't bother saving g.
// When using cgo, we already saved g on TLS, also don't save
// g here.
// Also don't save g if we are already on the signal stack.
// We won't get a nested signal.
MOVBZ runtime·iscgo(SB), R22
CMP R22, $0
BNE nosaveg
MOVD m_gsignal(R21), R22 // g.m.gsignal
CMP R22, $0
BEQ nosaveg
CMP g, R22
BEQ nosaveg
MOVD (g_stack+stack_lo)(R22), R22 // g.m.gsignal.stack.lo
MOVD g, (R22)
BL (CTR) // Call from VDSO BL (CTR) // Call from VDSO
MOVD $0, (R22) // clear g slot, R22 is unchanged by C code
JMP finish
nosaveg:
BL (CTR) // Call from VDSO
finish:
MOVD $0, R0 // Restore R0 MOVD $0, R0 // Restore R0
MOVD 0(R1), R3 // sec MOVD 0(R1), R3 // sec
MOVD 8(R1), R5 // nsec MOVD 8(R1), R5 // nsec
@ -236,7 +266,7 @@ noswitch:
MOVD 32(R1), R6 MOVD 32(R1), R6
MOVD R6, m_vdsoPC(R21) MOVD R6, m_vdsoPC(R21)
finish: return:
MOVD R3, sec+0(FP) MOVD R3, sec+0(FP)
MOVW R5, nsec+8(FP) MOVW R5, nsec+8(FP)
RET RET
@ -247,7 +277,7 @@ fallback:
SYSCALL $SYS_clock_gettime SYSCALL $SYS_clock_gettime
MOVD 32(R1), R3 MOVD 32(R1), R3
MOVD 40(R1), R5 MOVD 40(R1), R5
JMP finish JMP return
TEXT runtime·nanotime1(SB),NOSPLIT,$16-8 TEXT runtime·nanotime1(SB),NOSPLIT,$16-8
MOVD $1, R3 // CLOCK_MONOTONIC MOVD $1, R3 // CLOCK_MONOTONIC
@ -283,7 +313,37 @@ noswitch:
RLDICR $0, R1, $59, R1 // Align for C code RLDICR $0, R1, $59, R1 // Align for C code
MOVD R12, CTR MOVD R12, CTR
MOVD R1, R4 MOVD R1, R4
// Store g on gsignal's stack, so if we receive a signal
// during VDSO code we can find the g.
// If we don't have a signal stack, we won't receive signal,
// so don't bother saving g.
// When using cgo, we already saved g on TLS, also don't save
// g here.
// Also don't save g if we are already on the signal stack.
// We won't get a nested signal.
MOVBZ runtime·iscgo(SB), R22
CMP R22, $0
BNE nosaveg
MOVD m_gsignal(R21), R22 // g.m.gsignal
CMP R22, $0
BEQ nosaveg
CMP g, R22
BEQ nosaveg
MOVD (g_stack+stack_lo)(R22), R22 // g.m.gsignal.stack.lo
MOVD g, (R22)
BL (CTR) // Call from VDSO BL (CTR) // Call from VDSO
MOVD $0, (R22) // clear g slot, R22 is unchanged by C code
JMP finish
nosaveg:
BL (CTR) // Call from VDSO
finish:
MOVD $0, R0 // Restore R0 MOVD $0, R0 // Restore R0
MOVD 0(R1), R3 // sec MOVD 0(R1), R3 // sec
MOVD 8(R1), R5 // nsec MOVD 8(R1), R5 // nsec
@ -299,7 +359,7 @@ noswitch:
MOVD 32(R1), R6 MOVD 32(R1), R6
MOVD R6, m_vdsoPC(R21) MOVD R6, m_vdsoPC(R21)
finish: return:
// sec is in R3, nsec in R5 // sec is in R3, nsec in R5
// return nsec in R3 // return nsec in R3
MOVD $1000000000, R4 MOVD $1000000000, R4
@ -314,7 +374,7 @@ fallback:
SYSCALL $SYS_clock_gettime SYSCALL $SYS_clock_gettime
MOVD 32(R1), R3 MOVD 32(R1), R3
MOVD 40(R1), R5 MOVD 40(R1), R5
JMP finish JMP return
TEXT runtime·rtsigprocmask(SB),NOSPLIT|NOFRAME,$0-28 TEXT runtime·rtsigprocmask(SB),NOSPLIT|NOFRAME,$0-28
MOVW how+0(FP), R3 MOVW how+0(FP), R3

View File

@ -252,6 +252,8 @@ import (
"sync" "sync"
"sync/atomic" "sync/atomic"
"time" "time"
"unicode"
"unicode/utf8"
) )
var initRan bool var initRan bool
@ -908,11 +910,6 @@ func (c *common) Cleanup(f func()) {
c.cleanups = append(c.cleanups, fn) c.cleanups = append(c.cleanups, fn)
} }
var tempDirReplacer struct {
sync.Once
r *strings.Replacer
}
// TempDir returns a temporary directory for the test to use. // TempDir returns a temporary directory for the test to use.
// The directory is automatically removed by Cleanup when the test and // The directory is automatically removed by Cleanup when the test and
// all its subtests complete. // all its subtests complete.
@ -936,13 +933,26 @@ func (c *common) TempDir() string {
if nonExistent { if nonExistent {
c.Helper() c.Helper()
// os.MkdirTemp doesn't like path separators in its pattern, // Drop unusual characters (such as path separators or
// so mangle the name to accommodate subtests. // characters interacting with globs) from the directory name to
tempDirReplacer.Do(func() { // avoid surprising os.MkdirTemp behavior.
tempDirReplacer.r = strings.NewReplacer("/", "_", "\\", "_", ":", "_") mapper := func(r rune) rune {
}) if r < utf8.RuneSelf {
pattern := tempDirReplacer.r.Replace(c.Name()) const allowed = "!#$%&()+,-.=@^_{}~ "
if '0' <= r && r <= '9' ||
'a' <= r && r <= 'z' ||
'A' <= r && r <= 'Z' {
return r
}
if strings.ContainsRune(allowed, r) {
return r
}
} else if unicode.IsLetter(r) || unicode.IsNumber(r) {
return r
}
return -1
}
pattern := strings.Map(mapper, c.Name())
c.tempDir, c.tempDirErr = os.MkdirTemp("", pattern) c.tempDir, c.tempDirErr = os.MkdirTemp("", pattern)
if c.tempDirErr == nil { if c.tempDirErr == nil {
c.Cleanup(func() { c.Cleanup(func() {

View File

@ -58,6 +58,9 @@ func TestTempDir(t *testing.T) {
t.Run("test:subtest", testTempDir) t.Run("test:subtest", testTempDir)
t.Run("test/..", testTempDir) t.Run("test/..", testTempDir)
t.Run("../test", testTempDir) t.Run("../test", testTempDir)
t.Run("test[]", testTempDir)
t.Run("test*", testTempDir)
t.Run("äöüéè", testTempDir)
} }
func testTempDir(t *testing.T) { func testTempDir(t *testing.T) {
@ -74,7 +77,7 @@ func testTempDir(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
t.Errorf("directory %q stil exists: %v, isDir=%v", dir, fi, fi.IsDir()) t.Errorf("directory %q still exists: %v, isDir=%v", dir, fi, fi.IsDir())
default: default:
if !t.Failed() { if !t.Failed() {
t.Fatal("never received dir channel") t.Fatal("never received dir channel")
@ -108,6 +111,11 @@ func testTempDir(t *testing.T) {
if len(files) > 0 { if len(files) > 0 {
t.Errorf("unexpected %d files in TempDir: %v", len(files), files) t.Errorf("unexpected %d files in TempDir: %v", len(files), files)
} }
glob := filepath.Join(dir, "*.txt")
if _, err := filepath.Glob(glob); err != nil {
t.Error(err)
}
} }
func TestSetenv(t *testing.T) { func TestSetenv(t *testing.T) {

View File

@ -1340,7 +1340,7 @@ func UnixMicro(usec int64) Time {
} }
// IsDST reports whether the time in the configured location is in Daylight Savings Time. // IsDST reports whether the time in the configured location is in Daylight Savings Time.
func (t *Time) IsDST() bool { func (t Time) IsDST() bool {
_, _, _, _, isDST := t.loc.lookup(t.Unix()) _, _, _, _, isDST := t.loc.lookup(t.Unix())
return isDST return isDST
} }