[dev.link] all: merge branch 'master' into dev.link

Change-Id: I446db56b20ef2189e23e225a91a17736c1d11e4c
This commit is contained in:
Cherry Zhang 2020-06-11 16:49:19 -04:00
commit 3187b05b87
71 changed files with 1541 additions and 832 deletions

20
.gitattributes vendored
View file

@ -1,16 +1,16 @@
# Treat all files in the Go repo as binary, with no git magic updating # Treat all files in the Go repo as binary, with no git magic updating
# line endings. Windows users contributing to Go will need to use a # line endings. This produces predictable results in different environments.
# modern version of git and editors capable of LF line endings. #
# Windows users contributing to Go will need to use a modern version
# of git and editors capable of LF line endings.
#
# Windows .bat files are known to have multiple bugs when run with LF
# endings, and so they are checked in with CRLF endings, with a test
# in test/winbatch.go to catch problems. (See golang.org/issue/37791.)
# #
# We'll prevent accidental CRLF line endings from entering the repo # We'll prevent accidental CRLF line endings from entering the repo
# via the git-review gofmt checks. # via the git-codereview gofmt checks and tests.
# #
# See golang.org/issue/9281 # See golang.org/issue/9281.
* -text * -text
# The only exception is Windows files that must absolutely be CRLF or
# might not work. Batch files are known to have multiple bugs when run
# with LF endings. See golang.org/issue/37791 for more information.
*.bat text eol=crlf

View file

@ -1397,6 +1397,7 @@ Upthere, Inc.
Uriel Mangado <uriel@berlinblue.org> Uriel Mangado <uriel@berlinblue.org>
Vadim Grek <vadimprog@gmail.com> Vadim Grek <vadimprog@gmail.com>
Vadim Vygonets <unixdj@gmail.com> Vadim Vygonets <unixdj@gmail.com>
Vee Zhang <veezhang@126.com> <vveezhang@gmail.com>
Vendasta Vendasta
Veselkov Konstantin <kostozyb@gmail.com> Veselkov Konstantin <kostozyb@gmail.com>
Victor Vrantchan <vrancean+github@gmail.com> Victor Vrantchan <vrancean+github@gmail.com>

View file

@ -2195,6 +2195,7 @@ Vadim Grek <vadimprog@gmail.com>
Vadim Vygonets <unixdj@gmail.com> Vadim Vygonets <unixdj@gmail.com>
Val Polouchkine <vpolouch@justin.tv> Val Polouchkine <vpolouch@justin.tv>
Valentin Vidic <vvidic@valentin-vidic.from.hr> Valentin Vidic <vvidic@valentin-vidic.from.hr>
Vee Zhang <veezhang@126.com> <vveezhang@gmail.com>
Vega Garcia Luis Alfonso <vegacom@gmail.com> Vega Garcia Luis Alfonso <vegacom@gmail.com>
Venil Noronha <veniln@vmware.com> Venil Noronha <veniln@vmware.com>
Veselkov Konstantin <kostozyb@gmail.com> Veselkov Konstantin <kostozyb@gmail.com>

132
api/go1.15.txt Normal file
View file

@ -0,0 +1,132 @@
pkg bufio, var ErrBadReadCount error
pkg crypto, method (Hash) String() string
pkg crypto/ecdsa, func SignASN1(io.Reader, *PrivateKey, []uint8) ([]uint8, error)
pkg crypto/ecdsa, func VerifyASN1(*PublicKey, []uint8, []uint8) bool
pkg crypto/ecdsa, method (*PrivateKey) Equal(crypto.PrivateKey) bool
pkg crypto/ecdsa, method (*PublicKey) Equal(crypto.PublicKey) bool
pkg crypto/ed25519, method (PrivateKey) Equal(crypto.PrivateKey) bool
pkg crypto/ed25519, method (PublicKey) Equal(crypto.PublicKey) bool
pkg crypto/elliptic, func MarshalCompressed(Curve, *big.Int, *big.Int) []uint8
pkg crypto/elliptic, func UnmarshalCompressed(Curve, []uint8) (*big.Int, *big.Int)
pkg crypto/rsa, method (*PrivateKey) Equal(crypto.PrivateKey) bool
pkg crypto/rsa, method (*PublicKey) Equal(crypto.PublicKey) bool
pkg crypto/tls, method (*Dialer) Dial(string, string) (net.Conn, error)
pkg crypto/tls, method (*Dialer) DialContext(context.Context, string, string) (net.Conn, error)
pkg crypto/tls, method (ClientAuthType) String() string
pkg crypto/tls, method (CurveID) String() string
pkg crypto/tls, method (SignatureScheme) String() string
pkg crypto/tls, type Config struct, VerifyConnection func(ConnectionState) error
pkg crypto/tls, type Dialer struct
pkg crypto/tls, type Dialer struct, Config *Config
pkg crypto/tls, type Dialer struct, NetDialer *net.Dialer
pkg crypto/x509, func CreateRevocationList(io.Reader, *RevocationList, *Certificate, crypto.Signer) ([]uint8, error)
pkg crypto/x509, type RevocationList struct
pkg crypto/x509, type RevocationList struct, ExtraExtensions []pkix.Extension
pkg crypto/x509, type RevocationList struct, NextUpdate time.Time
pkg crypto/x509, type RevocationList struct, Number *big.Int
pkg crypto/x509, type RevocationList struct, RevokedCertificates []pkix.RevokedCertificate
pkg crypto/x509, type RevocationList struct, SignatureAlgorithm SignatureAlgorithm
pkg crypto/x509, type RevocationList struct, ThisUpdate time.Time
pkg database/sql, method (*DB) SetConnMaxIdleTime(time.Duration)
pkg database/sql, method (*Row) Err() error
pkg database/sql, type DBStats struct, MaxIdleTimeClosed int64
pkg database/sql/driver, type Validator interface { IsValid }
pkg database/sql/driver, type Validator interface, IsValid() bool
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_APPCONTAINER = 4096
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_APPCONTAINER ideal-int
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE = 64
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE ideal-int
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY = 128
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY ideal-int
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_GUARD_CF = 16384
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_GUARD_CF ideal-int
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA = 32
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA ideal-int
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_NO_BIND = 2048
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_NO_BIND ideal-int
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_NO_ISOLATION = 512
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_NO_ISOLATION ideal-int
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_NO_SEH = 1024
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_NO_SEH ideal-int
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_NX_COMPAT = 256
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_NX_COMPAT ideal-int
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = 32768
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE ideal-int
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_WDM_DRIVER = 8192
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_WDM_DRIVER ideal-int
pkg debug/pe, const IMAGE_FILE_32BIT_MACHINE = 256
pkg debug/pe, const IMAGE_FILE_32BIT_MACHINE ideal-int
pkg debug/pe, const IMAGE_FILE_AGGRESIVE_WS_TRIM = 16
pkg debug/pe, const IMAGE_FILE_AGGRESIVE_WS_TRIM ideal-int
pkg debug/pe, const IMAGE_FILE_BYTES_REVERSED_HI = 32768
pkg debug/pe, const IMAGE_FILE_BYTES_REVERSED_HI ideal-int
pkg debug/pe, const IMAGE_FILE_BYTES_REVERSED_LO = 128
pkg debug/pe, const IMAGE_FILE_BYTES_REVERSED_LO ideal-int
pkg debug/pe, const IMAGE_FILE_DEBUG_STRIPPED = 512
pkg debug/pe, const IMAGE_FILE_DEBUG_STRIPPED ideal-int
pkg debug/pe, const IMAGE_FILE_DLL = 8192
pkg debug/pe, const IMAGE_FILE_DLL ideal-int
pkg debug/pe, const IMAGE_FILE_EXECUTABLE_IMAGE = 2
pkg debug/pe, const IMAGE_FILE_EXECUTABLE_IMAGE ideal-int
pkg debug/pe, const IMAGE_FILE_LARGE_ADDRESS_AWARE = 32
pkg debug/pe, const IMAGE_FILE_LARGE_ADDRESS_AWARE ideal-int
pkg debug/pe, const IMAGE_FILE_LINE_NUMS_STRIPPED = 4
pkg debug/pe, const IMAGE_FILE_LINE_NUMS_STRIPPED ideal-int
pkg debug/pe, const IMAGE_FILE_LOCAL_SYMS_STRIPPED = 8
pkg debug/pe, const IMAGE_FILE_LOCAL_SYMS_STRIPPED ideal-int
pkg debug/pe, const IMAGE_FILE_NET_RUN_FROM_SWAP = 2048
pkg debug/pe, const IMAGE_FILE_NET_RUN_FROM_SWAP ideal-int
pkg debug/pe, const IMAGE_FILE_RELOCS_STRIPPED = 1
pkg debug/pe, const IMAGE_FILE_RELOCS_STRIPPED ideal-int
pkg debug/pe, const IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = 1024
pkg debug/pe, const IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP ideal-int
pkg debug/pe, const IMAGE_FILE_SYSTEM = 4096
pkg debug/pe, const IMAGE_FILE_SYSTEM ideal-int
pkg debug/pe, const IMAGE_FILE_UP_SYSTEM_ONLY = 16384
pkg debug/pe, const IMAGE_FILE_UP_SYSTEM_ONLY ideal-int
pkg debug/pe, const IMAGE_SUBSYSTEM_EFI_APPLICATION = 10
pkg debug/pe, const IMAGE_SUBSYSTEM_EFI_APPLICATION ideal-int
pkg debug/pe, const IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 11
pkg debug/pe, const IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER ideal-int
pkg debug/pe, const IMAGE_SUBSYSTEM_EFI_ROM = 13
pkg debug/pe, const IMAGE_SUBSYSTEM_EFI_ROM ideal-int
pkg debug/pe, const IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER = 12
pkg debug/pe, const IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER ideal-int
pkg debug/pe, const IMAGE_SUBSYSTEM_NATIVE = 1
pkg debug/pe, const IMAGE_SUBSYSTEM_NATIVE ideal-int
pkg debug/pe, const IMAGE_SUBSYSTEM_NATIVE_WINDOWS = 8
pkg debug/pe, const IMAGE_SUBSYSTEM_NATIVE_WINDOWS ideal-int
pkg debug/pe, const IMAGE_SUBSYSTEM_OS2_CUI = 5
pkg debug/pe, const IMAGE_SUBSYSTEM_OS2_CUI ideal-int
pkg debug/pe, const IMAGE_SUBSYSTEM_POSIX_CUI = 7
pkg debug/pe, const IMAGE_SUBSYSTEM_POSIX_CUI ideal-int
pkg debug/pe, const IMAGE_SUBSYSTEM_UNKNOWN = 0
pkg debug/pe, const IMAGE_SUBSYSTEM_UNKNOWN ideal-int
pkg debug/pe, const IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION = 16
pkg debug/pe, const IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION ideal-int
pkg debug/pe, const IMAGE_SUBSYSTEM_WINDOWS_CE_GUI = 9
pkg debug/pe, const IMAGE_SUBSYSTEM_WINDOWS_CE_GUI ideal-int
pkg debug/pe, const IMAGE_SUBSYSTEM_WINDOWS_CUI = 3
pkg debug/pe, const IMAGE_SUBSYSTEM_WINDOWS_CUI ideal-int
pkg debug/pe, const IMAGE_SUBSYSTEM_WINDOWS_GUI = 2
pkg debug/pe, const IMAGE_SUBSYSTEM_WINDOWS_GUI ideal-int
pkg debug/pe, const IMAGE_SUBSYSTEM_XBOX = 14
pkg debug/pe, const IMAGE_SUBSYSTEM_XBOX ideal-int
pkg go/printer, const StdFormat = 16
pkg go/printer, const StdFormat Mode
pkg math/big, method (*Int) FillBytes([]uint8) []uint8
pkg net, method (*Resolver) LookupIP(context.Context, string, string) ([]IP, error)
pkg net/url, method (*URL) EscapedFragment() string
pkg net/url, method (*URL) Redacted() string
pkg net/url, type URL struct, RawFragment string
pkg os, method (*File) ReadFrom(io.Reader) (int64, error)
pkg os, var ErrDeadlineExceeded error
pkg regexp, method (*Regexp) SubexpIndex(string) int
pkg strconv, func FormatComplex(complex128, uint8, int, int) string
pkg strconv, func ParseComplex(string, int) (complex128, error)
pkg sync, method (*Map) LoadAndDelete(interface{}) (interface{}, bool)
pkg testing, method (*B) TempDir() string
pkg testing, method (*T) Deadline() (time.Time, bool)
pkg testing, method (*T) TempDir() string
pkg testing, type TB interface, TempDir() string
pkg time, method (*Ticker) Reset(Duration)

View file

@ -1,3 +0,0 @@
pkg testing, method (*T) Deadline() (time.Time, bool)
pkg time, method (*Ticker) Reset(Duration)
pkg sync, method (*Map) LoadAndDelete(interface{}) (interface{}, bool)

View file

@ -30,7 +30,7 @@ adds <a href="#test">caching of successful test results</a>,
runs <a href="#test-vet">vet automatically during tests</a>, runs <a href="#test-vet">vet automatically during tests</a>,
and and
permits <a href="#cgo">passing string values directly between Go and C using cgo</a>. permits <a href="#cgo">passing string values directly between Go and C using cgo</a>.
A new <a href="#cgo">compiler option whitelist</a> may cause A new <a href="#cgo">hard-coded set of safe compiler options</a> may cause
unexpected <a href="https://golang.org/s/invalidflag"><code>invalid unexpected <a href="https://golang.org/s/invalidflag"><code>invalid
flag</code></a> errors in code that built successfully with older flag</code></a> errors in code that built successfully with older
releases. releases.
@ -267,7 +267,7 @@ and the <a href="/cmd/test2json/">test2json documentation</a>.
<p> <p>
Options specified by cgo using <code>#cgo CFLAGS</code> and the like Options specified by cgo using <code>#cgo CFLAGS</code> and the like
are now checked against a whitelist of permitted options. are now checked against a list of permitted options.
This closes a security hole in which a downloaded package uses This closes a security hole in which a downloaded package uses
compiler options like compiler options like
<span style="white-space: nowrap"><code>-fplugin</code></span> <span style="white-space: nowrap"><code>-fplugin</code></span>

View file

@ -55,6 +55,13 @@ Do not send CLs removing the interior tags from such phrases.
on Windows. on Windows.
</p> </p>
<p><!-- CL 227003 -->
The <code>-race</code> and <code>-msan</code> flags now always
enable <code>-d=checkptr</code>, which checks uses
of <code>unsafe.Pointer</code>. This was previously the case on all
OSes except Windows.
</p>
<p><!-- CL 211139 --> <p><!-- CL 211139 -->
Go-built DLLs no longer cause the process to exit when it receives a Go-built DLLs no longer cause the process to exit when it receives a
signal (such as Ctrl-C at a terminal). signal (such as Ctrl-C at a terminal).
@ -211,10 +218,24 @@ Do not send CLs removing the interior tags from such phrases.
<h2 id="runtime">Runtime</h2> <h2 id="runtime">Runtime</h2>
<p><!-- CL 232862 --> <p><!-- CL 221779 -->
Go now retries system calls that return <code>EINTR</code>. This If <code>panic</code> is invoked with a value whose type is derived from any
became more common in Go 1.14 with the addition of asynchronous of: <code>bool</code>, <code>complex64</code>, <code>complex128</code>, <code>float32</code>, <code>float64</code>,
preemption, but is now handled transparently. <code>int</code>, <code>int8</code>, <code>int16</code>, <code>int32</code>, <code>int64</code>, <code>string</code>,
<code>uint</code>, <code>uint8</code>, <code>uint16</code>, <code>uint32</code>, <code>uint64</code>, <code>uintptr</code>,
then the value will be printed, instead of just its address.
Previously, this was only true for values of exactly these types.
</p>
<p><!-- CL 228900 -->
On a Unix system, if the <code>kill</code> command
or <code>kill</code> system call is used to send
a <code>SIGSEGV</code>, <code>SIGBUS</code>,
or <code>SIGFPE</code> signal to a Go program, and if the signal
is not being handled via
<a href="/pkg/os/signal/#Notify"><code>os/signal.Notify</code></a>,
the Go program will now reliably crash with a stack trace.
In earlier releases the behavior was unpredictable.
</p> </p>
<p><!-- CL 221182, CL 229998 --> <p><!-- CL 221182, CL 229998 -->
@ -222,8 +243,14 @@ Do not send CLs removing the interior tags from such phrases.
counts, and has lower worst-case latency. counts, and has lower worst-case latency.
</p> </p>
<p> <p><!-- CL 216401 -->
TODO Converting a small integer value into an interface value no longer
causes allocation.
</p>
<p><!-- CL 216818 -->
Non-blocking receives on closed channels now perform as well as
non-blocking receives on open channels.
</p> </p>
<h2 id="compiler">Compiler</h2> <h2 id="compiler">Compiler</h2>
@ -245,6 +272,15 @@ TODO
aggressively eliminating unused type metadata. aggressively eliminating unused type metadata.
</p> </p>
<p><!-- CL 219357, CL 231600 -->
The toolchain now mitigates
<a href="https://www.intel.com/content/www/us/en/support/articles/000055650/processors.html">Intel
CPU erratum SKX102</a> on <code>GOARCH=amd64</code> by aligning
functions to 32 byte boundaries and padding jump instructions. While
this padding increases binary sizes, this is more than made up for
by the binary size improvements mentioned above.
</p>
<p><!-- CL 222661 --> <p><!-- CL 222661 -->
Go 1.15 adds a <code>-spectre</code> flag to both the Go 1.15 adds a <code>-spectre</code> flag to both the
compiler and the assembler, to allow enabling Spectre mitigations. compiler and the assembler, to allow enabling Spectre mitigations.
@ -253,6 +289,19 @@ TODO
See the <a href="https://github.com/golang/go/wiki/Spectre">Spectre wiki page</a> for details. See the <a href="https://github.com/golang/go/wiki/Spectre">Spectre wiki page</a> for details.
</p> </p>
<p><!-- CL 228578 -->
The compiler now rejects <code>//go:</code> compiler directives that
have no meaning for the declaration they are applied to with a
"misplaced compiler directive" error. Such misapplied directives
were broken before, but were silently ignored by the compiler.
</p>
<p><!-- CL 206658, CL 205066 -->
The compiler's <code>-json</code> optimization logging now reports
large (>= 128 byte) copies and includes explanations of escape
analysis decisions.
</p>
<h2 id="linker">Linker</h2> <h2 id="linker">Linker</h2>
<p> <p>
@ -283,6 +332,14 @@ TODO
improvements expected in future releases. improvements expected in future releases.
</p> </p>
<h2 id="objdump">Objdump</h2>
<p><!-- CL 225459 -->
The <a href="/cmd/objdump/">objdump</a> tool now supports
disassembling in GNU assembler syntax with the <code>-gnu</code>
flag.
</p>
<h2 id="library">Core library</h2> <h2 id="library">Core library</h2>
<h3 id="time/tzdata">New embedded tzdata package</h3> <h3 id="time/tzdata">New embedded tzdata package</h3>
@ -299,10 +356,6 @@ TODO
Either approach increases the size of the program by about 800 KB. Either approach increases the size of the program by about 800 KB.
</p> </p>
<p>
TODO
</p>
<h3 id="cgo">Cgo</h3> <h3 id="cgo">Cgo</h3>
<p><!-- CL 235817 --> <p><!-- CL 235817 -->
@ -321,10 +374,6 @@ TODO
in mind. in mind.
</p> </p>
<p>
TODO
</p>
<dl id="debug/pe"><dt><a href="/pkg/debug/pe/">debug/pe</a></dt> <dl id="debug/pe"><dt><a href="/pkg/debug/pe/">debug/pe</a></dt>
<dd> <dd>
<p><!-- CL 222637 --> <p><!-- CL 222637 -->
@ -336,10 +385,53 @@ TODO
</dd> </dd>
</dl><!-- debug/pe --> </dl><!-- debug/pe -->
<dl id="crypto"><dt><a href="/pkg/crypto/">crypto</a></dt>
<dd>
<p><!-- CL 231417, CL 225460 -->
The <code>PrivateKey</code> and <code>PublicKey</code> types in the
<a href="/pkg/crypto/rsa"><code>crypto/rsa</code></a>,
<a href="/pkg/crypto/ecdsa"><code>crypto/ecdsa</code></a>, and
<a href="/pkg/crypto/ed25519"><code>crypto/ed25519</code></a> packages
now have an <code>Equal</code> method to compare keys for equivalence
or to make type-safe interfaces for public keys. The method signature
is compatible with
<a href="https://pkg.go.dev/github.com/google/go-cmp/cmp#Equal"><code>go-cmp</code>'s
definition of equality</a>.
</p>
<p><!-- CL 224937 -->
<a href="/pkg/crypto/#Hash"><code>Hash</code></a> now implements
<a href="/pkg/fmt/#Stringer"><code>fmt.Stringer</code></a>.
</p>
</dd>
</dl><!-- crypto -->
<dl id="crypto/ecdsa"><dt><a href="/pkg/crypto/ecdsa/">crypto/ecdsa</a></dt>
<dd>
<p><!-- CL 217940 -->
The new <a href="/pkg/crypto/ecdsa/#SignASN1"><code>SignASN1</code></a>
and <a href="/pkg/crypto/ecdsa/#VerifyASN1"><code>VerifyASN1</code></a>
functions allow generating and verifying ECDSA signatures in the standard
ASN.1 DER encoding.
</p>
</dd>
</dl><!-- crypto/ecdsa -->
<dl id="crypto/elliptic"><dt><a href="/pkg/crypto/elliptic/">crypto/elliptic</a></dt>
<dd>
<p><!-- CL 202819 -->
The new <a href="/pkg/crypto/elliptic/#MarshalCompressed"><code>MarshalCompressed</code></a>
and <a href="/pkg/crypto/elliptic/#UnmarshalCompressed"><code>UnmarshalCompressed</code></a>
functions allow encoding and decoding NIST elliptic curve points in compressed format.
</p>
</dd>
</dl><!-- crypto/elliptic -->
<dl id="crypto/rsa"><dt><a href="/pkg/crypto/rsa/">crypto/rsa</a></dt> <dl id="crypto/rsa"><dt><a href="/pkg/crypto/rsa/">crypto/rsa</a></dt>
<dd> <dd>
<p><!-- CL 226203 --> <p><!-- CL 226203 -->
VerifyPKCS1v15 now rejects invalid short signatures with missing leading zeroes. <a href="/pkg/crypto/rsa/#VerifyPKCS1v15"><code>VerifyPKCS1v15</code></a>
now rejects invalid short signatures with missing leading zeroes, according to RFC 8017.
</p> </p>
</dd> </dd>
</dl><!-- crypto/rsa --> </dl><!-- crypto/rsa -->
@ -353,21 +445,137 @@ TODO
<a href="/pkg/crypto/tls/#Dialer.DialContext"><code>DialContext</code></a> <a href="/pkg/crypto/tls/#Dialer.DialContext"><code>DialContext</code></a>
method permits using a context to both connect and handshake with a TLS server. method permits using a context to both connect and handshake with a TLS server.
</p> </p>
<p><!-- CL 229122 -->
The new
<a href="/pkg/crypto/tls/#Config.VerifyConnection"><code>VerifyConnection</code></a>
callback on the <a href="/pkg/crypto/tls/#Config"><code>Config</code></a> type
allows custom verification logic for every connection. It has access to the
<a href="/pkg/crypto/tls/#ConnectionState"><code>ConnectionState</code></a>
which includes peer certificates, SCTs, and stapled OCSP responses.
</p>
<p><!-- CL 230679 -->
Auto-generated session ticket keys are now automatically rotated every 24 hours,
with a lifetime of 7 days, to limit their impact on forward secrecy.
</p>
<p><!-- CL 231317 -->
Session ticket lifetimes in TLS 1.2 and earlier, where the session keys
are reused for resumed connections, are now limited to 7 days, also to
limit their impact on forward secrecy.
</p>
<p><!-- CL 231038 -->
The client-side downgrade protection checks specified in RFC 8446 are now
enforced. This has the potential to cause connection errors for clients
encountering middleboxes that behave like unauthorized downgrade attacks.
</p>
<p><!-- CL 208226 -->
<a href="/pkg/crypto/tls/#SignatureScheme"><code>SignatureScheme</code></a>,
<a href="/pkg/crypto/tls/#CurveID"><code>CurveID</code></a>, and
<a href="/pkg/crypto/tls/#ClientAuthType"><code>ClientAuthType</code></a>
now implement <a href="/pkg/fmt/#Stringer"><code>fmt.Stringer</code></a>.
</p>
<p><!-- CL 236737 -->
The <a href="/pkg/crypto/tls/#ConnectionState"><code>ConnectionState</code></a>
fields <code>OCSPResponse</code> and <code>SignedCertificateTimestamps</code>
are now repopulated on client-side resumed connections.
</p>
</dd> </dd>
</dl> </dl><!-- crypto/tls -->
<dl id="crypto/x509"><dt><a href="/pkg/crypto/x509/">crypto/x509</a></dt> <dl id="crypto/x509"><dt><a href="/pkg/crypto/x509/">crypto/x509</a></dt>
<dd> <dd>
<p><!-- CL 231378, CL 231380, CL 231381 -->
If either the name on the certificate or the name being verified (with
<a href="/pkg/crypto/x509/#VerifyOptions.DNSName"><code>VerifyOptions.DNSName</code></a>
or <a href="/pkg/crypto/x509/#Certificate.VerifyHostname"><code>VerifyHostname</code></a>)
are invalid, they will now be compared case-insensitively without further
processing (without honoring wildcards or stripping trailing dots).
Invalid names include those with any characters other than letters,
digits, hyphens and underscores, those with empty labels, and names on
certificates with trailing dots.
</p>
<p><!-- CL 231379 -->
The deprecated, legacy behavior of treating the <code>CommonName</code>
field as a hostname when no Subject Alternative Names are present is now
disabled by default. It can be temporarily re-enabled by adding the value
<code>x509ignoreCN=0</code> to the <code>GODEBUG</code> environment
variable. If the <code>CommonName</code> is an invalid hostname, it's
always ignored.
</p>
<p><!-- CL 217298 -->
The new <a href="/pkg/crypto/x509/#CreateRevocationList"><code>CreateRevocationList</code></a>
function and <a href="/pkg/crypto/x509/#RevocationList"><code>RevocationList</code></a> type
allow creating RFC 5280-compliant X.509 v2 Certificate Revocation Lists.
</p>
<p><!-- CL 227098 -->
<a href="/pkg/crypto/x509/#CreateCertificate"><code>CreateCertificate</code></a>
now automatically generates the <code>SubjectKeyId</code> if the template
is a CA and doesn't explicitly specify one.
</p>
<p><!-- CL 228777 -->
<a href="/pkg/crypto/x509/#CreateCertificate"><code>CreateCertificate</code></a>
now returns an error if the template specifies <code>MaxPathLen</code> but is not a CA.
</p>
<p><!-- CL 205237 --> <p><!-- CL 205237 -->
TODO: <a href="https://golang.org/cl/205237">https://golang.org/cl/205237</a>: load roots from colon separated SSL_CERT_DIR in loadSystemRoots On Unix systems other than macOS, the <code>SSL_CERT_DIR</code>
environment variable can now be a colon-separated list.
</p>
<p><!-- CL 227037 -->
On macOS, binaries are now always linked against
<code>Security.framework</code> to extract the system trust roots,
regardless of whether cgo is available. The resulting behavior should be
more consistent with the OS verifier.
</p> </p>
</dd> </dd>
</dl><!-- crypto/x509 --> </dl><!-- crypto/x509 -->
<dl id="crypto/x509/pkix"><dt><a href="/pkg/crypto/x509/pkix/">crypto/x509/pkix</a></dt>
<dd>
<p><!-- CL 229864 -->
<a href="/pkg/crypto/x509/pkix/#Name.String"><code>Name.String</code></a>
now prints non-standard attributes from
<a href="/pkg/crypto/x509/pkix/#Name.Names"><code>Names</code></a> if
<a href="/pkg/crypto/x509/pkix/#Name.ExtraNames"><code>ExtraNames</code></a> is empty.
</p>
</dd>
</dl><!-- crypto/x509/pkix -->
<dl id="encoding/json"><dt><a href="/pkg/encoding/json/">encoding/json</a></dt>
<dd>
<p><!-- CL 191783 -->
Decoding a JSON array into a slice no longer reuses any existing slice elements,
following the rules that the package documentation already stated.
</p>
<p><!-- CL 199837 -->
Introduce an internal limit to the maximum depth of nesting when decoding.
This reduces the possibility that a deeply nested input could use large quantities
of stack memory, or even cause a "goroutine stack exceeds limit" panic.
</p>
</dd>
</dl><!-- encoding/json -->
<dl id="encoding/xml"><dt><a href="/pkg/encoding/xml/">encoding/xml</a></dt> <dl id="encoding/xml"><dt><a href="/pkg/encoding/xml/">encoding/xml</a></dt>
<dd> <dd>
<p><!-- CL 203417 --> <p><!-- CL 203417 -->
TODO: <a href="https://golang.org/cl/203417">https://golang.org/cl/203417</a>: fix reserved namespace check to be case-insensitive The encoder has always taken care to avoid using namespace prefixes beginning with
<code>xml</code>,
which are reserved by the XML specification.
Now, following the specification more closely,
that check is case-insensitive, so that prefixes beginning with
<code>XML</code>, <code>XmL</code>,
and so on are also avoided.
</p> </p>
</dd> </dd>
</dl><!-- encoding/xml --> </dl><!-- encoding/xml -->
@ -390,7 +598,8 @@ TODO
<dl id="fmt"><dt><a href="/pkg/fmt/">fmt</a></dt> <dl id="fmt"><dt><a href="/pkg/fmt/">fmt</a></dt>
<dd> <dd>
<p><!-- CL 215001 --> <p><!-- CL 215001 -->
TODO: <a href="https://golang.org/cl/215001">https://golang.org/cl/215001</a>: do not remove trailing zeros for %g and %G with #(sharp) flag The printing verbs <code>%#g</code> and <code>%#G</code> now preserve
trailing zeros for floating-point values.
</p> </p>
</dd> </dd>
</dl><!-- fmt --> </dl><!-- fmt -->
@ -410,7 +619,8 @@ TODO
<dl id="math/big"><dt><a href="/pkg/math/big/">math/big</a></dt> <dl id="math/big"><dt><a href="/pkg/math/big/">math/big</a></dt>
<dd> <dd>
<p><!-- CL 230397 --> <p><!-- CL 230397 -->
TODO: <a href="https://golang.org/cl/230397">https://golang.org/cl/230397</a>: add (*Int).FillBytes The new <a href="/pkg/math/big/#Int.FillBytes"><code>Int.FillBytes</code></a>
method allows serializing to fixed-size pre-allocated byte slices.
</p> </p>
</dd> </dd>
</dl><!-- math/big --> </dl><!-- math/big -->
@ -441,8 +651,10 @@ TODO
<dl id="net/http"><dt><a href="/pkg/net/http/">net/http</a></dt> <dl id="net/http"><dt><a href="/pkg/net/http/">net/http</a></dt>
<dd> <dd>
<p><!-- CL 231418 --> <p><!-- CL 231418, CL 231419 -->
TODO: <a href="https://golang.org/cl/231418">https://golang.org/cl/231418</a>: only support &#34;chunked&#34; in inbound Transfer-Encoding headers Parsing is now stricter as a hardening measure against request smuggling attacks:
non-ASCII white space is no longer trimmed like SP and HTAB, and support for the
"<code>identity</code>" <code>Transfer-Encoding</code> was dropped.
</p> </p>
</dd> </dd>
</dl><!-- net/http --> </dl><!-- net/http -->
@ -457,7 +669,9 @@ TODO
</p> </p>
<p><!-- CL 224897 --> <p><!-- CL 224897 -->
TODO: <a href="https://golang.org/cl/224897">https://golang.org/cl/224897</a>: make Switching Protocol requests (e.g. Websockets) cancelable When a Switching Protocol (like WebSocket) request handled by
<a href="/pkg/net/http/httputil/#ReverseProxy"><code>ReverseProxy</code></a>
is canceled, the backend connection is now correctly closed.
</p> </p>
</dd> </dd>
</dl> </dl>
@ -506,6 +720,14 @@ TODO
which <code>Timeout</code> returns <code>true</code> although a which <code>Timeout</code> returns <code>true</code> although a
deadline has not been exceeded. deadline has not been exceeded.
</p> </p>
<p><!-- CL 232862 -->
Packages <code>os</code> and <code>net</code> now automatically
retry system calls that fail with <code>EINTR</code>. Previously
this led to spurious failures, which became more common in Go
1.14 with the addition of asynchronous preemption. Now this is
handled transparently.
</p>
</dd> </dd>
</dl> </dl>
@ -525,7 +747,7 @@ TODO
<dl id="reflect"><dt><a href="/pkg/reflect/">reflect</a></dt> <dl id="reflect"><dt><a href="/pkg/reflect/">reflect</a></dt>
<dd> <dd>
<p><!-- CL 228902 --> <p><!-- CL 228902 -->
Package reflect now disallows accessing methods of all Package <code>reflect</code> now disallows accessing methods of all
non-exported fields, whereas previously it allowed accessing non-exported fields, whereas previously it allowed accessing
those of non-exported, embedded fields. Code that relies on the those of non-exported, embedded fields. Code that relies on the
previous behavior should be updated to instead access the previous behavior should be updated to instead access the
@ -546,26 +768,6 @@ TODO
<dl id="pkg-runtime"><dt><a href="/pkg/runtime/">runtime</a></dt> <dl id="pkg-runtime"><dt><a href="/pkg/runtime/">runtime</a></dt>
<dd> <dd>
<p><!-- CL 221779 -->
If <code>panic</code> is invoked with a value whose type is derived from any
of: <code>bool</code>, <code>complex64</code>, <code>complex128</code>, <code>float32</code>, <code>float64</code>,
<code>int</code>, <code>int8</code>, <code>int16</code>, <code>int32</code>, <code>int64</code>, <code>string</code>,
<code>uint</code>, <code>uint8</code>, <code>uint16</code>, <code>uint32</code>, <code>uint64</code>, <code>uintptr</code>,
then the value will be printed, instead of just its address.
Previously, this was only true for values of exactly these types.
</p>
<p><!-- CL -->
On a Unix system, if the <code>kill</code> command
or <code>kill</code> system call is used to send
a <code>SIGSEGV</code>, <code>SIGBUS</code>,
or <code>SIGFPE</code> signal to a Go program, and if the signal
is not being handled via
<a href="/pkg/os/signal/#Notify"><code>os/signal.Notify</code></a>,
the Go program will now reliably crash with a stack trace.
In earlier releases the behavior was unpredictable.
</p>
<p><!-- CL 216557 --> <p><!-- CL 216557 -->
Several functions, including Several functions, including
<a href="/pkg/runtime/#ReadMemStats"><code>ReadMemStats</code></a> <a href="/pkg/runtime/#ReadMemStats"><code>ReadMemStats</code></a>
@ -573,16 +775,6 @@ TODO
<a href="/pkg/runtime/#GoroutineProfile"><code>GoroutineProfile</code></a>, <a href="/pkg/runtime/#GoroutineProfile"><code>GoroutineProfile</code></a>,
no longer block if a garbage collection is in progress. no longer block if a garbage collection is in progress.
</p> </p>
<p><!-- CL 216401 -->
Converting small integer values into an interface value no
longer causes allocation.
</p>
<p><!-- CL 216818 -->
Non-blocking receives on closed channels now perform as well as
non-blocking receives on open channels.
</p>
</dd> </dd>
</dl> </dl>

View file

@ -1,27 +1,27 @@
:: Copyright 2012 The Go Authors. All rights reserved. :: Copyright 2012 The Go Authors. All rights reserved.
:: Use of this source code is governed by a BSD-style :: Use of this source code is governed by a BSD-style
:: license that can be found in the LICENSE file. :: license that can be found in the LICENSE file.
@echo off @echo off
setlocal setlocal
if exist make.bat goto ok if exist make.bat goto ok
echo all.bat must be run from go\src echo all.bat must be run from go\src
:: cannot exit: would kill parent command interpreter :: cannot exit: would kill parent command interpreter
goto end goto end
:ok :ok
set OLDPATH=%PATH% set OLDPATH=%PATH%
call make.bat --no-banner --no-local call make.bat --no-banner --no-local
if %GOBUILDFAIL%==1 goto end if %GOBUILDFAIL%==1 goto end
call run.bat --no-rebuild --no-local call run.bat --no-rebuild --no-local
if %GOBUILDFAIL%==1 goto end if %GOBUILDFAIL%==1 goto end
:: we must restore %PATH% before running "dist banner" so that the latter :: we must restore %PATH% before running "dist banner" so that the latter
:: can get the original %PATH% and give suggestion to add %GOROOT%/bin :: can get the original %PATH% and give suggestion to add %GOROOT%/bin
:: to %PATH% if necessary. :: to %PATH% if necessary.
set PATH=%OLDPATH% set PATH=%OLDPATH%
"%GOTOOLDIR%/dist" banner "%GOTOOLDIR%/dist" banner
:end :end
if x%GOBUILDEXIT%==x1 exit %GOBUILDFAIL% if x%GOBUILDEXIT%==x1 exit %GOBUILDFAIL%

View file

@ -1,32 +1,32 @@
:: Copyright 2012 The Go Authors. All rights reserved. :: Copyright 2012 The Go Authors. All rights reserved.
:: Use of this source code is governed by a BSD-style :: Use of this source code is governed by a BSD-style
:: license that can be found in the LICENSE file. :: license that can be found in the LICENSE file.
@echo off @echo off
setlocal setlocal
set GOBUILDFAIL=0 set GOBUILDFAIL=0
go tool dist env -w -p >env.bat go tool dist env -w -p >env.bat
if errorlevel 1 goto fail if errorlevel 1 goto fail
call env.bat call env.bat
del env.bat del env.bat
echo. echo.
if exist %GOTOOLDIR%\dist.exe goto distok if exist %GOTOOLDIR%\dist.exe goto distok
echo cannot find %GOTOOLDIR%\dist; nothing to clean echo cannot find %GOTOOLDIR%\dist; nothing to clean
goto fail goto fail
:distok :distok
"%GOBIN%\go" clean -i std "%GOBIN%\go" clean -i std
"%GOBIN%\go" tool dist clean "%GOBIN%\go" tool dist clean
"%GOBIN%\go" clean -i cmd "%GOBIN%\go" clean -i cmd
goto end goto end
:fail :fail
set GOBUILDFAIL=1 set GOBUILDFAIL=1
:end :end
if x%GOBUILDEXIT%==x1 exit %GOBUILDFAIL% if x%GOBUILDEXIT%==x1 exit %GOBUILDFAIL%

View file

@ -73,19 +73,29 @@ func testAddr2Line(t *testing.T, exepath, addr string) {
if err != nil { if err != nil {
t.Fatalf("Stat failed: %v", err) t.Fatalf("Stat failed: %v", err)
} }
// Debug paths are stored slash-separated, so convert to system-native.
srcPath = filepath.FromSlash(srcPath)
fi2, err := os.Stat(srcPath) fi2, err := os.Stat(srcPath)
if gorootFinal := os.Getenv("GOROOT_FINAL"); gorootFinal != "" && strings.HasPrefix(srcPath, gorootFinal) {
if os.IsNotExist(err) || (err == nil && !os.SameFile(fi1, fi2)) {
// srcPath has had GOROOT_FINAL substituted for GOROOT, and it doesn't
// match the actual file. GOROOT probably hasn't been moved to its final
// location yet, so try the original location instead.
fi2, err = os.Stat(runtime.GOROOT() + strings.TrimPrefix(srcPath, gorootFinal))
}
}
if err != nil { if err != nil {
t.Fatalf("Stat failed: %v", err) t.Fatalf("Stat failed: %v", err)
} }
if !os.SameFile(fi1, fi2) { if !os.SameFile(fi1, fi2) {
t.Fatalf("addr2line_test.go and %s are not same file", srcPath) t.Fatalf("addr2line_test.go and %s are not same file", srcPath)
} }
if srcLineNo != "89" { if srcLineNo != "99" {
t.Fatalf("line number = %v; want 89", srcLineNo) t.Fatalf("line number = %v; want 99", srcLineNo)
} }
} }
// This is line 88. The test depends on that. // This is line 98. The test depends on that.
func TestAddr2Line(t *testing.T) { func TestAddr2Line(t *testing.T) {
testenv.MustHaveGoBuild(t) testenv.MustHaveGoBuild(t)

View file

@ -420,6 +420,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
UXTBW R2, R6 // 461c0053 UXTBW R2, R6 // 461c0053
UXTHW R7, R20 // f43c0053 UXTHW R7, R20 // f43c0053
VCNT V0.B8, V0.B8 // 0058200e VCNT V0.B8, V0.B8 // 0058200e
VCNT V0.B16, V0.B16 // 0058204e
WFE // 5f2003d5 WFE // 5f2003d5
WFI // 7f2003d5 WFI // 7f2003d5
YIELD // 3f2003d5 YIELD // 3f2003d5

View file

@ -990,7 +990,7 @@ produces a file named a.out, even if cmd/link does so by invoking the host
linker in external linking mode. linker in external linking mode.
By default, cmd/link will decide the linking mode as follows: if the only By default, cmd/link will decide the linking mode as follows: if the only
packages using cgo are those on a whitelist of standard library packages using cgo are those on a list of known standard library
packages (net, os/user, runtime/cgo), cmd/link will use internal linking packages (net, os/user, runtime/cgo), cmd/link will use internal linking
mode. Otherwise, there are non-standard cgo packages involved, and cmd/link mode. Otherwise, there are non-standard cgo packages involved, and cmd/link
will use external linking mode. The first rule means that a build of will use external linking mode. The first rule means that a build of

View file

@ -96,7 +96,7 @@ func TestFormats(t *testing.T) {
} }
importPath := filepath.Join("cmd/compile", path) importPath := filepath.Join("cmd/compile", path)
if blacklistedPackages[filepath.ToSlash(importPath)] { if ignoredPackages[filepath.ToSlash(importPath)] {
return filepath.SkipDir return filepath.SkipDir
} }
@ -344,8 +344,7 @@ func collectPkgFormats(t *testing.T, pkg *build.Package) {
for index, file := range files { for index, file := range files {
ast.Inspect(file, func(n ast.Node) bool { ast.Inspect(file, func(n ast.Node) bool {
if call, ok := n.(*ast.CallExpr); ok { if call, ok := n.(*ast.CallExpr); ok {
// ignore blacklisted functions if ignoredFunctions[nodeString(call.Fun)] {
if blacklistedFunctions[nodeString(call.Fun)] {
return true return true
} }
// look for an arguments that might be a format string // look for an arguments that might be a format string
@ -354,7 +353,7 @@ func collectPkgFormats(t *testing.T, pkg *build.Package) {
// make sure we have enough arguments // make sure we have enough arguments
n := numFormatArgs(s) n := numFormatArgs(s)
if i+1+n > len(call.Args) { if i+1+n > len(call.Args) {
t.Errorf("%s: not enough format args (blacklist %s?)", posString(call), nodeString(call.Fun)) t.Errorf("%s: not enough format args (ignore %s?)", posString(call), nodeString(call.Fun))
break // ignore this call break // ignore this call
} }
// assume last n arguments are to be formatted; // assume last n arguments are to be formatted;
@ -549,14 +548,14 @@ func formatReplace(in string, f func(i int, s string) string) string {
return string(append(buf, in[i0:]...)) return string(append(buf, in[i0:]...))
} }
// blacklistedPackages is the set of packages which can // ignoredPackages is the set of packages which can
// be ignored. // be ignored.
var blacklistedPackages = map[string]bool{} var ignoredPackages = map[string]bool{}
// blacklistedFunctions is the set of functions which may have // ignoredFunctions is the set of functions which may have
// format-like arguments but which don't do any formatting and // format-like arguments but which don't do any formatting and
// thus may be ignored. // thus may be ignored.
var blacklistedFunctions = map[string]bool{} var ignoredFunctions = map[string]bool{}
func init() { func init() {
// verify that knownFormats entries are correctly formatted // verify that knownFormats entries are correctly formatted

View file

@ -140,6 +140,7 @@ var knownFormats = map[string]string{
"float64 %.3f": "", "float64 %.3f": "",
"float64 %.6g": "", "float64 %.6g": "",
"float64 %g": "", "float64 %g": "",
"int %#x": "",
"int %-12d": "", "int %-12d": "",
"int %-6d": "", "int %-6d": "",
"int %-8o": "", "int %-8o": "",
@ -203,6 +204,7 @@ var knownFormats = map[string]string{
"uint64 %b": "", "uint64 %b": "",
"uint64 %d": "", "uint64 %d": "",
"uint64 %x": "", "uint64 %x": "",
"uint8 %#x": "",
"uint8 %d": "", "uint8 %d": "",
"uint8 %v": "", "uint8 %v": "",
"uint8 %x": "", "uint8 %x": "",

View file

@ -888,16 +888,30 @@ var condBits = map[ssa.Op]uint8{
var blockJump = map[ssa.BlockKind]struct { var blockJump = map[ssa.BlockKind]struct {
asm, invasm obj.As asm, invasm obj.As
}{ }{
ssa.BlockARMEQ: {arm.ABEQ, arm.ABNE}, ssa.BlockARMEQ: {arm.ABEQ, arm.ABNE},
ssa.BlockARMNE: {arm.ABNE, arm.ABEQ}, ssa.BlockARMNE: {arm.ABNE, arm.ABEQ},
ssa.BlockARMLT: {arm.ABLT, arm.ABGE}, ssa.BlockARMLT: {arm.ABLT, arm.ABGE},
ssa.BlockARMGE: {arm.ABGE, arm.ABLT}, ssa.BlockARMGE: {arm.ABGE, arm.ABLT},
ssa.BlockARMLE: {arm.ABLE, arm.ABGT}, ssa.BlockARMLE: {arm.ABLE, arm.ABGT},
ssa.BlockARMGT: {arm.ABGT, arm.ABLE}, ssa.BlockARMGT: {arm.ABGT, arm.ABLE},
ssa.BlockARMULT: {arm.ABLO, arm.ABHS}, ssa.BlockARMULT: {arm.ABLO, arm.ABHS},
ssa.BlockARMUGE: {arm.ABHS, arm.ABLO}, ssa.BlockARMUGE: {arm.ABHS, arm.ABLO},
ssa.BlockARMUGT: {arm.ABHI, arm.ABLS}, ssa.BlockARMUGT: {arm.ABHI, arm.ABLS},
ssa.BlockARMULE: {arm.ABLS, arm.ABHI}, ssa.BlockARMULE: {arm.ABLS, arm.ABHI},
ssa.BlockARMLTnoov: {arm.ABMI, arm.ABPL},
ssa.BlockARMGEnoov: {arm.ABPL, arm.ABMI},
}
// To model a 'LEnoov' ('<=' without overflow checking) branching
var leJumps = [2][2]gc.IndexJump{
{{Jump: arm.ABEQ, Index: 0}, {Jump: arm.ABPL, Index: 1}}, // next == b.Succs[0]
{{Jump: arm.ABMI, Index: 0}, {Jump: arm.ABEQ, Index: 0}}, // next == b.Succs[1]
}
// To model a 'GTnoov' ('>' without overflow checking) branching
var gtJumps = [2][2]gc.IndexJump{
{{Jump: arm.ABMI, Index: 1}, {Jump: arm.ABEQ, Index: 1}}, // next == b.Succs[0]
{{Jump: arm.ABEQ, Index: 1}, {Jump: arm.ABPL, Index: 0}}, // next == b.Succs[1]
} }
func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) { func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
@ -941,7 +955,8 @@ func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
ssa.BlockARMLT, ssa.BlockARMGE, ssa.BlockARMLT, ssa.BlockARMGE,
ssa.BlockARMLE, ssa.BlockARMGT, ssa.BlockARMLE, ssa.BlockARMGT,
ssa.BlockARMULT, ssa.BlockARMUGT, ssa.BlockARMULT, ssa.BlockARMUGT,
ssa.BlockARMULE, ssa.BlockARMUGE: ssa.BlockARMULE, ssa.BlockARMUGE,
ssa.BlockARMLTnoov, ssa.BlockARMGEnoov:
jmp := blockJump[b.Kind] jmp := blockJump[b.Kind]
switch next { switch next {
case b.Succs[0].Block(): case b.Succs[0].Block():
@ -958,6 +973,12 @@ func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
} }
} }
case ssa.BlockARMLEnoov:
s.CombJump(b, next, &leJumps)
case ssa.BlockARMGTnoov:
s.CombJump(b, next, &gtJumps)
default: default:
b.Fatalf("branch not implemented: %s", b.LongString()) b.Fatalf("branch not implemented: %s", b.LongString())
} }

View file

@ -141,13 +141,13 @@ func isSelfAssign(dst, src *Node) bool {
return samesafeexpr(dst.Left, src.Left) return samesafeexpr(dst.Left, src.Left)
} }
// mayAffectMemory reports whether n evaluation may affect program memory state. // mayAffectMemory reports whether evaluation of n may affect the program's
// If expression can't affect it, then it can be safely ignored by the escape analysis. // memory state. If the expression can't affect memory state, then it can be
// safely ignored by the escape analysis.
func mayAffectMemory(n *Node) bool { func mayAffectMemory(n *Node) bool {
// We may want to use "memory safe" black list instead of general // We may want to use a list of "memory safe" ops instead of generally
// "side-effect free", which can include all calls and other ops // "side-effect free", which would include all calls and other ops that can
// that can affect allocate or change global state. // allocate or change global state. For now, it's safer to start with the latter.
// It's safer to start from a whitelist for now.
// //
// We're ignoring things like division by zero, index out of range, // We're ignoring things like division by zero, index out of range,
// and nil pointer dereference here. // and nil pointer dereference here.

View file

@ -451,6 +451,7 @@ var passes = [...]pass{
{name: "lowered deadcode for cse", fn: deadcode}, // deadcode immediately before CSE avoids CSE making dead values live again {name: "lowered deadcode for cse", fn: deadcode}, // deadcode immediately before CSE avoids CSE making dead values live again
{name: "lowered cse", fn: cse}, {name: "lowered cse", fn: cse},
{name: "elim unread autos", fn: elimUnreadAutos}, {name: "elim unread autos", fn: elimUnreadAutos},
{name: "tighten tuple selectors", fn: tightenTupleSelectors, required: true},
{name: "lowered deadcode", fn: deadcode, required: true}, {name: "lowered deadcode", fn: deadcode, required: true},
{name: "checkLower", fn: checkLower, required: true}, {name: "checkLower", fn: checkLower, required: true},
{name: "late phielim", fn: phielim}, {name: "late phielim", fn: phielim},
@ -509,6 +510,8 @@ var passOrder = [...]constraint{
{"decompose builtin", "late opt"}, {"decompose builtin", "late opt"},
// decompose builtin is the last pass that may introduce new float ops, so run softfloat after it // decompose builtin is the last pass that may introduce new float ops, so run softfloat after it
{"decompose builtin", "softfloat"}, {"decompose builtin", "softfloat"},
// tuple selectors must be tightened to generators and de-duplicated before scheduling
{"tighten tuple selectors", "schedule"},
// remove critical edges before phi tighten, so that phi args get better placement // remove critical edges before phi tighten, so that phi args get better placement
{"critical", "phi tighten"}, {"critical", "phi tighten"},
// don't layout blocks until critical edges have been removed // don't layout blocks until critical edges have been removed

View file

@ -223,60 +223,6 @@ func cse(f *Func) {
} }
} }
// Fixup tuple selectors.
//
// If we have rewritten a tuple generator to a new one in a different
// block, copy its selectors to the new generator's block, so tuple
// generator and selectors stay together.
//
// Note: that there must be only one selector of each type per tuple
// generator. CSE may have left us with more than one so we de-duplicate
// them using a map. See issue 16741.
selectors := make(map[struct {
id ID
op Op
}]*Value)
for _, b := range f.Blocks {
for _, selector := range b.Values {
if selector.Op != OpSelect0 && selector.Op != OpSelect1 {
continue
}
// Get the tuple generator to use as a key for de-duplication.
tuple := selector.Args[0]
if !tuple.Type.IsTuple() {
f.Fatalf("arg of tuple selector %s is not a tuple: %s", selector.String(), tuple.LongString())
}
// If there is a pre-existing selector in the target block then
// use that. Do this even if the selector is already in the
// target block to avoid duplicate tuple selectors.
key := struct {
id ID
op Op
}{tuple.ID, selector.Op}
if t := selectors[key]; t != nil {
if selector != t {
selector.copyOf(t)
}
continue
}
// If the selector is in the wrong block copy it into the target
// block.
if selector.Block != tuple.Block {
t := selector.copyInto(tuple.Block)
selector.copyOf(t)
selectors[key] = t
continue
}
// The selector is in the target block. Add it to the map so it
// cannot be duplicated.
selectors[key] = selector
}
}
if f.pass.stats > 0 { if f.pass.stats > 0 {
f.LogStat("CSE REWRITES", rewrites) f.LogStat("CSE REWRITES", rewrites)
} }

View file

@ -704,6 +704,10 @@
(UGE (InvertFlags cmp) yes no) -> (ULE cmp yes no) (UGE (InvertFlags cmp) yes no) -> (ULE cmp yes no)
(EQ (InvertFlags cmp) yes no) -> (EQ cmp yes no) (EQ (InvertFlags cmp) yes no) -> (EQ cmp yes no)
(NE (InvertFlags cmp) yes no) -> (NE cmp yes no) (NE (InvertFlags cmp) yes no) -> (NE cmp yes no)
(LTnoov (InvertFlags cmp) yes no) => (GTnoov cmp yes no)
(GEnoov (InvertFlags cmp) yes no) => (LEnoov cmp yes no)
(LEnoov (InvertFlags cmp) yes no) => (GEnoov cmp yes no)
(GTnoov (InvertFlags cmp) yes no) => (LTnoov cmp yes no)
// absorb flag constants into boolean values // absorb flag constants into boolean values
(Equal (FlagEQ)) -> (MOVWconst [1]) (Equal (FlagEQ)) -> (MOVWconst [1])
@ -1417,42 +1421,42 @@
(NE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 -> (NE (TEQshiftLLreg x y z) yes no) (NE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 -> (NE (TEQshiftLLreg x y z) yes no)
(NE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 -> (NE (TEQshiftRLreg x y z) yes no) (NE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 -> (NE (TEQshiftRLreg x y z) yes no)
(NE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 -> (NE (TEQshiftRAreg x y z) yes no) (NE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 -> (NE (TEQshiftRAreg x y z) yes no)
(LT (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (LT (CMP x y) yes no) (LT (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (LTnoov (CMP x y) yes no)
(LT (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (LT (CMP a (MUL <x.Type> x y)) yes no) (LT (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (LTnoov (CMP a (MUL <x.Type> x y)) yes no)
(LT (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (LT (CMPconst [c] x) yes no) (LT (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (LTnoov (CMPconst [c] x) yes no)
(LT (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 -> (LT (CMPshiftLL x y [c]) yes no) (LT (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 -> (LTnoov (CMPshiftLL x y [c]) yes no)
(LT (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 -> (LT (CMPshiftRL x y [c]) yes no) (LT (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 -> (LTnoov (CMPshiftRL x y [c]) yes no)
(LT (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 -> (LT (CMPshiftRA x y [c]) yes no) (LT (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 -> (LTnoov (CMPshiftRA x y [c]) yes no)
(LT (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 -> (LT (CMPshiftLLreg x y z) yes no) (LT (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 -> (LTnoov (CMPshiftLLreg x y z) yes no)
(LT (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 -> (LT (CMPshiftRLreg x y z) yes no) (LT (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 -> (LTnoov (CMPshiftRLreg x y z) yes no)
(LT (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 -> (LT (CMPshiftRAreg x y z) yes no) (LT (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 -> (LTnoov (CMPshiftRAreg x y z) yes no)
(LE (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (LE (CMP x y) yes no) (LE (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (LEnoov (CMP x y) yes no)
(LE (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (LE (CMP a (MUL <x.Type> x y)) yes no) (LE (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (LEnoov (CMP a (MUL <x.Type> x y)) yes no)
(LE (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (LE (CMPconst [c] x) yes no) (LE (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (LEnoov (CMPconst [c] x) yes no)
(LE (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 -> (LE (CMPshiftLL x y [c]) yes no) (LE (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 -> (LEnoov (CMPshiftLL x y [c]) yes no)
(LE (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 -> (LE (CMPshiftRL x y [c]) yes no) (LE (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 -> (LEnoov (CMPshiftRL x y [c]) yes no)
(LE (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 -> (LE (CMPshiftRA x y [c]) yes no) (LE (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 -> (LEnoov (CMPshiftRA x y [c]) yes no)
(LE (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 -> (LE (CMPshiftLLreg x y z) yes no) (LE (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 -> (LEnoov (CMPshiftLLreg x y z) yes no)
(LE (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 -> (LE (CMPshiftRLreg x y z) yes no) (LE (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 -> (LEnoov (CMPshiftRLreg x y z) yes no)
(LE (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 -> (LE (CMPshiftRAreg x y z) yes no) (LE (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 -> (LEnoov (CMPshiftRAreg x y z) yes no)
(LT (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 -> (LT (CMN x y) yes no) (LT (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 -> (LTnoov (CMN x y) yes no)
(LT (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (LT (CMN a (MUL <x.Type> x y)) yes no) (LT (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (LTnoov (CMN a (MUL <x.Type> x y)) yes no)
(LT (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 -> (LT (CMNconst [c] x) yes no) (LT (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 -> (LTnoov (CMNconst [c] x) yes no)
(LT (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 -> (LT (CMNshiftLL x y [c]) yes no) (LT (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 -> (LTnoov (CMNshiftLL x y [c]) yes no)
(LT (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 -> (LT (CMNshiftRL x y [c]) yes no) (LT (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 -> (LTnoov (CMNshiftRL x y [c]) yes no)
(LT (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 -> (LT (CMNshiftRA x y [c]) yes no) (LT (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 -> (LTnoov (CMNshiftRA x y [c]) yes no)
(LT (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (LT (CMNshiftLLreg x y z) yes no) (LT (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (LTnoov (CMNshiftLLreg x y z) yes no)
(LT (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (LT (CMNshiftRLreg x y z) yes no) (LT (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (LTnoov (CMNshiftRLreg x y z) yes no)
(LT (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (LT (CMNshiftRAreg x y z) yes no) (LT (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (LTnoov (CMNshiftRAreg x y z) yes no)
(LE (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 -> (LE (CMN x y) yes no) (LE (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 -> (LEnoov (CMN x y) yes no)
(LE (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (LE (CMN a (MUL <x.Type> x y)) yes no) (LE (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (LEnoov (CMN a (MUL <x.Type> x y)) yes no)
(LE (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 -> (LE (CMNconst [c] x) yes no) (LE (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 -> (LEnoov (CMNconst [c] x) yes no)
(LE (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 -> (LE (CMNshiftLL x y [c]) yes no) (LE (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 -> (LEnoov (CMNshiftLL x y [c]) yes no)
(LE (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 -> (LE (CMNshiftRL x y [c]) yes no) (LE (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 -> (LEnoov (CMNshiftRL x y [c]) yes no)
(LE (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 -> (LE (CMNshiftRA x y [c]) yes no) (LE (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 -> (LEnoov (CMNshiftRA x y [c]) yes no)
(LE (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (LE (CMNshiftLLreg x y z) yes no) (LE (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (LEnoov (CMNshiftLLreg x y z) yes no)
(LE (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (LE (CMNshiftRLreg x y z) yes no) (LE (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (LEnoov (CMNshiftRLreg x y z) yes no)
(LE (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (LE (CMNshiftRAreg x y z) yes no) (LE (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (LEnoov (CMNshiftRAreg x y z) yes no)
(LT (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 -> (LT (TST x y) yes no) (LT (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 -> (LT (TST x y) yes no)
(LT (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 -> (LT (TSTconst [c] x) yes no) (LT (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 -> (LT (TSTconst [c] x) yes no)
(LT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 -> (LT (TSTshiftLL x y [c]) yes no) (LT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 -> (LT (TSTshiftLL x y [c]) yes no)
@ -1485,43 +1489,43 @@
(LE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 -> (LE (TEQshiftLLreg x y z) yes no) (LE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 -> (LE (TEQshiftLLreg x y z) yes no)
(LE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 -> (LE (TEQshiftRLreg x y z) yes no) (LE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 -> (LE (TEQshiftRLreg x y z) yes no)
(LE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 -> (LE (TEQshiftRAreg x y z) yes no) (LE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 -> (LE (TEQshiftRAreg x y z) yes no)
(GT (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (GT (CMP x y) yes no) (GT (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (GTnoov (CMP x y) yes no)
(GT (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (GT (CMP a (MUL <x.Type> x y)) yes no) (GT (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (GTnoov (CMP a (MUL <x.Type> x y)) yes no)
(GT (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (GT (CMPconst [c] x) yes no) (GT (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (GTnoov (CMPconst [c] x) yes no)
(GT (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 -> (GT (CMPshiftLL x y [c]) yes no) (GT (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 -> (GTnoov (CMPshiftLL x y [c]) yes no)
(GT (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 -> (GT (CMPshiftRL x y [c]) yes no) (GT (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 -> (GTnoov (CMPshiftRL x y [c]) yes no)
(GT (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 -> (GT (CMPshiftRA x y [c]) yes no) (GT (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 -> (GTnoov (CMPshiftRA x y [c]) yes no)
(GT (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 -> (GT (CMPshiftLLreg x y z) yes no) (GT (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 -> (GTnoov (CMPshiftLLreg x y z) yes no)
(GT (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 -> (GT (CMPshiftRLreg x y z) yes no) (GT (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 -> (GTnoov (CMPshiftRLreg x y z) yes no)
(GT (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 -> (GT (CMPshiftRAreg x y z) yes no) (GT (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 -> (GTnoov (CMPshiftRAreg x y z) yes no)
(GE (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (GE (CMP x y) yes no) (GE (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (GEnoov (CMP x y) yes no)
(GE (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (GE (CMP a (MUL <x.Type> x y)) yes no) (GE (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (GEnoov (CMP a (MUL <x.Type> x y)) yes no)
(GE (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (GE (CMPconst [c] x) yes no) (GE (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (GEnoov (CMPconst [c] x) yes no)
(GE (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 -> (GE (CMPshiftLL x y [c]) yes no) (GE (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 -> (GEnoov (CMPshiftLL x y [c]) yes no)
(GE (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 -> (GE (CMPshiftRL x y [c]) yes no) (GE (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 -> (GEnoov (CMPshiftRL x y [c]) yes no)
(GE (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 -> (GE (CMPshiftRA x y [c]) yes no) (GE (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 -> (GEnoov (CMPshiftRA x y [c]) yes no)
(GE (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 -> (GE (CMPshiftLLreg x y z) yes no) (GE (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 -> (GEnoov (CMPshiftLLreg x y z) yes no)
(GE (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 -> (GE (CMPshiftRLreg x y z) yes no) (GE (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 -> (GEnoov (CMPshiftRLreg x y z) yes no)
(GE (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 -> (GE (CMPshiftRAreg x y z) yes no) (GE (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 -> (GEnoov (CMPshiftRAreg x y z) yes no)
(GT (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 -> (GT (CMN x y) yes no) (GT (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 -> (GTnoov (CMN x y) yes no)
(GT (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 -> (GT (CMNconst [c] x) yes no) (GT (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 -> (GTnoov (CMNconst [c] x) yes no)
(GT (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 -> (GT (CMNshiftLL x y [c]) yes no) (GT (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 -> (GTnoov (CMNshiftLL x y [c]) yes no)
(GT (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 -> (GT (CMNshiftRL x y [c]) yes no) (GT (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 -> (GTnoov (CMNshiftRL x y [c]) yes no)
(GT (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 -> (GT (CMNshiftRA x y [c]) yes no) (GT (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 -> (GTnoov (CMNshiftRA x y [c]) yes no)
(GT (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (GT (CMNshiftLLreg x y z) yes no) (GT (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (GTnoov (CMNshiftLLreg x y z) yes no)
(GT (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (GT (CMNshiftRLreg x y z) yes no) (GT (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (GTnoov (CMNshiftRLreg x y z) yes no)
(GT (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (GT (CMNshiftRAreg x y z) yes no) (GT (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (GTnoov (CMNshiftRAreg x y z) yes no)
(GE (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 -> (GE (CMN x y) yes no) (GE (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 -> (GEnoov (CMN x y) yes no)
(GE (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (GE (CMN a (MUL <x.Type> x y)) yes no) (GE (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (GEnoov (CMN a (MUL <x.Type> x y)) yes no)
(GE (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 -> (GE (CMNconst [c] x) yes no) (GE (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 -> (GEnoov (CMNconst [c] x) yes no)
(GE (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 -> (GE (CMNshiftLL x y [c]) yes no) (GE (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 -> (GEnoov (CMNshiftLL x y [c]) yes no)
(GE (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 -> (GE (CMNshiftRL x y [c]) yes no) (GE (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 -> (GEnoov (CMNshiftRL x y [c]) yes no)
(GE (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 -> (GE (CMNshiftRA x y [c]) yes no) (GE (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 -> (GEnoov (CMNshiftRA x y [c]) yes no)
(GE (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (GE (CMNshiftLLreg x y z) yes no) (GE (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (GEnoov (CMNshiftLLreg x y z) yes no)
(GE (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (GE (CMNshiftRLreg x y z) yes no) (GE (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (GEnoov (CMNshiftRLreg x y z) yes no)
(GE (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (GE (CMNshiftRAreg x y z) yes no) (GE (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (GEnoov (CMNshiftRAreg x y z) yes no)
(GT (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 -> (GT (TST x y) yes no) (GT (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 -> (GT (TST x y) yes no)
(GT (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (GT (CMN a (MUL <x.Type> x y)) yes no) (GT (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (GTnoov (CMN a (MUL <x.Type> x y)) yes no)
(GT (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 -> (GT (TSTconst [c] x) yes no) (GT (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 -> (GT (TSTconst [c] x) yes no)
(GT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 -> (GT (TSTshiftLL x y [c]) yes no) (GT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 -> (GT (TSTshiftLL x y [c]) yes no)
(GT (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 -> (GT (TSTshiftRL x y [c]) yes no) (GT (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 -> (GT (TSTshiftRL x y [c]) yes no)

View file

@ -584,6 +584,10 @@ func init() {
{name: "ULE", controls: 1}, {name: "ULE", controls: 1},
{name: "UGT", controls: 1}, {name: "UGT", controls: 1},
{name: "UGE", controls: 1}, {name: "UGE", controls: 1},
{name: "LTnoov", controls: 1}, // 'LT' but without honoring overflow
{name: "LEnoov", controls: 1}, // 'LE' but without honoring overflow
{name: "GTnoov", controls: 1}, // 'GT' but without honoring overflow
{name: "GEnoov", controls: 1}, // 'GE' but without honoring overflow
} }
archs = append(archs, arch{ archs = append(archs, arch{

View file

@ -61,6 +61,10 @@ const (
BlockARMULE BlockARMULE
BlockARMUGT BlockARMUGT
BlockARMUGE BlockARMUGE
BlockARMLTnoov
BlockARMLEnoov
BlockARMGTnoov
BlockARMGEnoov
BlockARM64EQ BlockARM64EQ
BlockARM64NE BlockARM64NE
@ -185,16 +189,20 @@ var blockString = [...]string{
BlockAMD64ORD: "ORD", BlockAMD64ORD: "ORD",
BlockAMD64NAN: "NAN", BlockAMD64NAN: "NAN",
BlockARMEQ: "EQ", BlockARMEQ: "EQ",
BlockARMNE: "NE", BlockARMNE: "NE",
BlockARMLT: "LT", BlockARMLT: "LT",
BlockARMLE: "LE", BlockARMLE: "LE",
BlockARMGT: "GT", BlockARMGT: "GT",
BlockARMGE: "GE", BlockARMGE: "GE",
BlockARMULT: "ULT", BlockARMULT: "ULT",
BlockARMULE: "ULE", BlockARMULE: "ULE",
BlockARMUGT: "UGT", BlockARMUGT: "UGT",
BlockARMUGE: "UGE", BlockARMUGE: "UGE",
BlockARMLTnoov: "LTnoov",
BlockARMLEnoov: "LEnoov",
BlockARMGTnoov: "GTnoov",
BlockARMGEnoov: "GEnoov",
BlockARM64EQ: "EQ", BlockARM64EQ: "EQ",
BlockARM64NE: "NE", BlockARM64NE: "NE",

File diff suppressed because it is too large Load diff

View file

@ -7,24 +7,26 @@ package ssa
import ( import (
"math" "math"
"math/rand" "math/rand"
"runtime"
"testing" "testing"
) )
var ( var (
x64 int64 = math.MaxInt64 - 2 x64 int64 = math.MaxInt64 - 2
x64b int64 = math.MaxInt64 - 2 x64b int64 = math.MaxInt64 - 2
x64c int64 = math.MaxInt64 - 2 x64c int64 = math.MaxInt64 - 2
y64 int64 = math.MinInt64 + 1 y64 int64 = math.MinInt64 + 1
x32 int32 = math.MaxInt32 - 2 x32 int32 = math.MaxInt32 - 2
x32b int32 = math.MaxInt32 - 2 x32b int32 = math.MaxInt32 - 2
y32 int32 = math.MinInt32 + 1 x32c int32 = math.MaxInt32 - 2
one64 int64 = 1 y32 int32 = math.MinInt32 + 1
one32 int32 = 1 one64 int64 = 1
v64 int64 = 11 // ensure it's not 2**n +/- 1 one32 int32 = 1
v64_n int64 = -11 v64 int64 = 11 // ensure it's not 2**n +/- 1
v32 int32 = 11 v64_n int64 = -11
v32_n int32 = -11 v32 int32 = 11
v32_n int32 = -11
uv32 uint32 = 19
uz uint8 = 1 // for lowering to SLL/SRL/SRA
) )
var crTests = []struct { var crTests = []struct {
@ -39,6 +41,8 @@ var crTests = []struct {
{"MAddVar32", testMAddVar32}, {"MAddVar32", testMAddVar32},
{"MSubVar64", testMSubVar64}, {"MSubVar64", testMSubVar64},
{"MSubVar32", testMSubVar32}, {"MSubVar32", testMSubVar32},
{"AddShift32", testAddShift32},
{"SubShift32", testSubShift32},
} }
var crBenches = []struct { var crBenches = []struct {
@ -58,9 +62,6 @@ var crBenches = []struct {
// and machine code sequences are covered. // and machine code sequences are covered.
// It's for arm64 initially, please see https://github.com/golang/go/issues/38740 // It's for arm64 initially, please see https://github.com/golang/go/issues/38740
func TestCondRewrite(t *testing.T) { func TestCondRewrite(t *testing.T) {
if runtime.GOARCH == "arm" {
t.Skip("fix on arm expected!")
}
for _, test := range crTests { for _, test := range crTests {
t.Run(test.name, test.tf) t.Run(test.name, test.tf)
} }
@ -408,6 +409,66 @@ func testMSubVar32(t *testing.T) {
} }
} }
// 32-bit ADDshift, pick up 1~2 scenarios randomly for each condition
func testAddShift32(t *testing.T) {
if x32+v32<<1 < 0 {
} else {
t.Errorf("'%#x + %#x<<%#x < 0' failed", x32, v32, 1)
}
if x32+v32>>1 <= 0 {
} else {
t.Errorf("'%#x + %#x>>%#x <= 0' failed", x32, v32, 1)
}
if x32+int32(uv32>>1) > 0 {
t.Errorf("'%#x + int32(%#x>>%#x) > 0' failed", x32, uv32, 1)
}
if x32+v32<<uz >= 0 {
t.Errorf("'%#x + %#x<<%#x >= 0' failed", x32, v32, uz)
}
if x32+v32>>uz > 0 {
t.Errorf("'%#x + %#x>>%#x > 0' failed", x32, v32, uz)
}
if x32+int32(uv32>>uz) < 0 {
} else {
t.Errorf("'%#x + int32(%#x>>%#x) < 0' failed", x32, uv32, uz)
}
}
// 32-bit SUBshift, pick up 1~2 scenarios randomly for each condition
func testSubShift32(t *testing.T) {
if y32-v32<<1 > 0 {
} else {
t.Errorf("'%#x - %#x<<%#x > 0' failed", y32, v32, 1)
}
if y32-v32>>1 < 0 {
t.Errorf("'%#x - %#x>>%#x < 0' failed", y32, v32, 1)
}
if y32-int32(uv32>>1) >= 0 {
} else {
t.Errorf("'%#x - int32(%#x>>%#x) >= 0' failed", y32, uv32, 1)
}
if y32-v32<<uz < 0 {
t.Errorf("'%#x - %#x<<%#x < 0' failed", y32, v32, uz)
}
if y32-v32>>uz >= 0 {
} else {
t.Errorf("'%#x - %#x>>%#x >= 0' failed", y32, v32, uz)
}
if y32-int32(uv32>>uz) <= 0 {
t.Errorf("'%#x - int32(%#x>>%#x) <= 0' failed", y32, uv32, uz)
}
}
var rnd = rand.New(rand.NewSource(0)) var rnd = rand.New(rand.NewSource(0))
var sink int64 var sink int64

View file

@ -0,0 +1,59 @@
// Copyright 2020 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 ssa
// tightenTupleSelectors ensures that tuple selectors (Select0 and
// Select1 ops) are in the same block as their tuple generator. The
// function also ensures that there are no duplicate tuple selectors.
// These properties are expected by the scheduler but may not have
// been maintained by the optimization pipeline up to this point.
//
// See issues 16741 and 39472.
func tightenTupleSelectors(f *Func) {
selectors := make(map[struct {
id ID
op Op
}]*Value)
for _, b := range f.Blocks {
for _, selector := range b.Values {
if selector.Op != OpSelect0 && selector.Op != OpSelect1 {
continue
}
// Get the tuple generator to use as a key for de-duplication.
tuple := selector.Args[0]
if !tuple.Type.IsTuple() {
f.Fatalf("arg of tuple selector %s is not a tuple: %s", selector.String(), tuple.LongString())
}
// If there is a pre-existing selector in the target block then
// use that. Do this even if the selector is already in the
// target block to avoid duplicate tuple selectors.
key := struct {
id ID
op Op
}{tuple.ID, selector.Op}
if t := selectors[key]; t != nil {
if selector != t {
selector.copyOf(t)
}
continue
}
// If the selector is in the wrong block copy it into the target
// block.
if selector.Block != tuple.Block {
t := selector.copyInto(tuple.Block)
selector.copyOf(t)
selectors[key] = t
continue
}
// The selector is in the target block. Add it to the map so it
// cannot be duplicated.
selectors[key] = selector
}
}
}

View file

@ -178,15 +178,6 @@ func (t *tester) run() {
return return
} }
// We must unset GOROOT_FINAL before tests, because runtime/debug requires
// correct access to source code, so if we have GOROOT_FINAL in effect,
// at least runtime/debug test will fail.
// If GOROOT_FINAL was set before, then now all the commands will appear stale.
// Nothing we can do about that other than not checking them below.
// (We call checkNotStale but only with "std" not "cmd".)
os.Setenv("GOROOT_FINAL_OLD", os.Getenv("GOROOT_FINAL")) // for cmd/link test
os.Unsetenv("GOROOT_FINAL")
for _, name := range t.runNames { for _, name := range t.runNames {
if !t.isRegisteredTestName(name) { if !t.isRegisteredTestName(name) {
fatalf("unknown test %q", name) fatalf("unknown test %q", name)

View file

@ -124,7 +124,6 @@ func TestMain(m *testing.M) {
fmt.Printf("SKIP\n") fmt.Printf("SKIP\n")
return return
} }
os.Unsetenv("GOROOT_FINAL")
flag.Parse() flag.Parse()
@ -180,6 +179,11 @@ func TestMain(m *testing.M) {
} }
testGOROOT = goEnv("GOROOT") testGOROOT = goEnv("GOROOT")
os.Setenv("TESTGO_GOROOT", testGOROOT) os.Setenv("TESTGO_GOROOT", testGOROOT)
// Ensure that GOROOT is set explicitly.
// Otherwise, if the toolchain was built with GOROOT_FINAL set but has not
// yet been moved to its final location, programs that invoke runtime.GOROOT
// may accidentally use the wrong path.
os.Setenv("GOROOT", testGOROOT)
// The whole GOROOT/pkg tree was installed using the GOHOSTOS/GOHOSTARCH // The whole GOROOT/pkg tree was installed using the GOHOSTOS/GOHOSTARCH
// toolchain (installed in GOROOT/pkg/tool/GOHOSTOS_GOHOSTARCH). // toolchain (installed in GOROOT/pkg/tool/GOHOSTOS_GOHOSTARCH).
@ -216,8 +220,10 @@ func TestMain(m *testing.M) {
} }
testCC = strings.TrimSpace(string(out)) testCC = strings.TrimSpace(string(out))
if out, err := exec.Command(testGo, "env", "CGO_ENABLED").Output(); err != nil { cmd := exec.Command(testGo, "env", "CGO_ENABLED")
fmt.Fprintf(os.Stderr, "running testgo failed: %v\n", err) cmd.Stderr = new(strings.Builder)
if out, err := cmd.Output(); err != nil {
fmt.Fprintf(os.Stderr, "running testgo failed: %v\n%s", err, cmd.Stderr)
canRun = false canRun = false
} else { } else {
canCgo, err = strconv.ParseBool(strings.TrimSpace(string(out))) canCgo, err = strconv.ParseBool(strings.TrimSpace(string(out)))

View file

@ -13,6 +13,7 @@ package web
import ( import (
"crypto/tls" "crypto/tls"
"errors"
"fmt" "fmt"
"mime" "mime"
"net/http" "net/http"
@ -47,6 +48,13 @@ var securityPreservingHTTPClient = &http.Client{
lastHop := via[len(via)-1].URL lastHop := via[len(via)-1].URL
return fmt.Errorf("redirected from secure URL %s to insecure URL %s", lastHop, req.URL) return fmt.Errorf("redirected from secure URL %s to insecure URL %s", lastHop, req.URL)
} }
// Go's http.DefaultClient allows 10 redirects before returning an error.
// The securityPreservingHTTPClient also uses this default policy to avoid
// Go command hangs.
if len(via) >= 10 {
return errors.New("stopped after 10 redirects")
}
return nil return nil
}, },
} }

View file

@ -168,7 +168,7 @@ func gcBackendConcurrency(gcflags []string) int {
CheckFlags: CheckFlags:
for _, flag := range gcflags { for _, flag := range gcflags {
// Concurrent compilation is presumed incompatible with any gcflags, // Concurrent compilation is presumed incompatible with any gcflags,
// except for a small whitelist of commonly used flags. // except for known commonly used flags.
// If the user knows better, they can manually add their own -c to the gcflags. // If the user knows better, they can manually add their own -c to the gcflags.
switch flag { switch flag {
case "-N", "-l", "-S", "-B", "-C", "-I": case "-N", "-l", "-S", "-B", "-C", "-I":

View file

@ -174,6 +174,25 @@ func proxyHandler(w http.ResponseWriter, r *http.Request) {
return return
} }
// Request for $GOPROXY/redirect/<count>/... goes to redirects.
if strings.HasPrefix(path, "redirect/") {
path = path[len("redirect/"):]
if j := strings.Index(path, "/"); j >= 0 {
count, err := strconv.Atoi(path[:j])
if err != nil {
return
}
// The last redirect.
if count <= 1 {
http.Redirect(w, r, fmt.Sprintf("/mod/%s", path[j+1:]), 302)
return
}
http.Redirect(w, r, fmt.Sprintf("/mod/redirect/%d/%s", count-1, path[j+1:]), 302)
return
}
}
// Request for $GOPROXY/sumdb/<name>/supported // Request for $GOPROXY/sumdb/<name>/supported
// is checking whether it's OK to access sumdb via the proxy. // is checking whether it's OK to access sumdb via the proxy.
if path == "sumdb/"+testSumDBName+"/supported" { if path == "sumdb/"+testSumDBName+"/supported" {

View file

@ -130,6 +130,7 @@ func (ts *testScript) setup() {
"GOPROXY=" + proxyURL, "GOPROXY=" + proxyURL,
"GOPRIVATE=", "GOPRIVATE=",
"GOROOT=" + testGOROOT, "GOROOT=" + testGOROOT,
"GOROOT_FINAL=" + os.Getenv("GOROOT_FINAL"), // causes spurious rebuilds and breaks the "stale" built-in if not propagated
"TESTGO_GOROOT=" + testGOROOT, "TESTGO_GOROOT=" + testGOROOT,
"GOSUMDB=" + testSumDBVerifierKey, "GOSUMDB=" + testSumDBVerifierKey,
"GONOPROXY=", "GONOPROXY=",

View file

@ -34,6 +34,7 @@ Scripts also have access to these other environment variables:
GOPATH=$WORK/gopath GOPATH=$WORK/gopath
GOPROXY=<local module proxy serving from cmd/go/testdata/mod> GOPROXY=<local module proxy serving from cmd/go/testdata/mod>
GOROOT=<actual GOROOT> GOROOT=<actual GOROOT>
GOROOT_FINAL=<actual GOROOT_FINAL>
TESTGO_GOROOT=<GOROOT used to build cmd/go, for use in tests that may change GOROOT> TESTGO_GOROOT=<GOROOT used to build cmd/go, for use in tests that may change GOROOT>
HOME=/no-home HOME=/no-home
PATH=<actual PATH> PATH=<actual PATH>

View file

@ -1,5 +1,9 @@
[short] skip [short] skip
# If GOROOT_FINAL is set, 'go build -trimpath' bakes that into the resulting
# binary instead of GOROOT. Explicitly unset it here.
env GOROOT_FINAL=
# Set up two identical directories that can be used as GOPATH. # Set up two identical directories that can be used as GOPATH.
env GO111MODULE=on env GO111MODULE=on
mkdir $WORK/a/src/paths $WORK/b/src/paths mkdir $WORK/a/src/paths $WORK/b/src/paths

View file

@ -2,6 +2,13 @@
mkdir $WORK/new/bin mkdir $WORK/new/bin
# In this test, we are specifically checking the logic for deriving
# the value of GOROOT from runtime.GOROOT.
# GOROOT_FINAL changes the default behavior of runtime.GOROOT,
# and will thus cause the test to fail if it is set when our
# new cmd/go is built.
env GOROOT_FINAL=
go build -o $WORK/new/bin/go$GOEXE cmd/go & go build -o $WORK/new/bin/go$GOEXE cmd/go &
go build -o $WORK/bin/check$GOEXE check.go & go build -o $WORK/bin/check$GOEXE check.go &
wait wait

View file

@ -20,7 +20,6 @@ cd $WORK/gopkgdir/x
! go list . ! go list .
stderr 'cannot find main module' stderr 'cannot find main module'
! stderr 'Gopkg.lock' ! stderr 'Gopkg.lock'
! stderr 'go mod init'
-- $WORK/test/Gopkg.lock -- -- $WORK/test/Gopkg.lock --
-- $WORK/test/x/x.go -- -- $WORK/test/x/x.go --

View file

@ -0,0 +1,10 @@
env GO111MODULE=on
env GOPROXYBASE=$GOPROXY
env GOPROXY=$GOPROXYBASE/redirect/11
env GOSUMDB=off
! go get -d rsc.io/quote@v1.2.0
stderr 'stopped after 10 redirects'
env GOPROXY=$GOPROXYBASE/redirect/9
go get -d rsc.io/quote@v1.2.0

View file

@ -36,7 +36,7 @@ func findGorootModules(t *testing.T) []gorootModule {
if err != nil { if err != nil {
return err return err
} }
if info.Name() == "vendor" || info.Name() == "testdata" { if info.IsDir() && (info.Name() == "vendor" || info.Name() == "testdata") {
return filepath.SkipDir return filepath.SkipDir
} }
if path == filepath.Join(runtime.GOROOT(), "pkg") { if path == filepath.Join(runtime.GOROOT(), "pkg") {

View file

@ -460,7 +460,6 @@ var optab = []Optab{
{AFCVTZSD, C_FREG, C_NONE, C_NONE, C_REG, 29, 4, 0, 0, 0}, {AFCVTZSD, C_FREG, C_NONE, C_NONE, C_REG, 29, 4, 0, 0, 0},
{ASCVTFD, C_REG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0}, {ASCVTFD, C_REG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0},
{AFCVTSD, C_FREG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0}, {AFCVTSD, C_FREG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0},
{AVCNT, C_ARNG, C_NONE, C_NONE, C_ARNG, 29, 4, 0, 0, 0},
{AVMOV, C_ELEM, C_NONE, C_NONE, C_REG, 73, 4, 0, 0, 0}, {AVMOV, C_ELEM, C_NONE, C_NONE, C_REG, 73, 4, 0, 0, 0},
{AVMOV, C_ELEM, C_NONE, C_NONE, C_ELEM, 92, 4, 0, 0, 0}, {AVMOV, C_ELEM, C_NONE, C_NONE, C_ELEM, 92, 4, 0, 0, 0},
{AVMOV, C_ELEM, C_NONE, C_NONE, C_VREG, 80, 4, 0, 0, 0}, {AVMOV, C_ELEM, C_NONE, C_NONE, C_VREG, 80, 4, 0, 0, 0},
@ -2773,6 +2772,7 @@ func buildop(ctxt *obj.Link) {
oprangeset(AVSRI, t) oprangeset(AVSRI, t)
case AVREV32: case AVREV32:
oprangeset(AVCNT, t)
oprangeset(AVRBIT, t) oprangeset(AVRBIT, t)
oprangeset(AVREV64, t) oprangeset(AVREV64, t)
oprangeset(AVREV16, t) oprangeset(AVREV16, t)
@ -4523,7 +4523,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
c.ctxt.Diag("invalid arrangement: %v\n", p) c.ctxt.Diag("invalid arrangement: %v\n", p)
} }
if (p.As == AVMOV || p.As == AVRBIT) && (af != ARNG_16B && af != ARNG_8B) { if (p.As == AVMOV || p.As == AVRBIT || p.As == AVCNT) && (af != ARNG_16B && af != ARNG_8B) {
c.ctxt.Diag("invalid arrangement: %v", p) c.ctxt.Diag("invalid arrangement: %v", p)
} }

View file

@ -134,7 +134,7 @@ func init() {
} }
func Framepointer_enabled(goos, goarch string) bool { func Framepointer_enabled(goos, goarch string) bool {
return framepointer_enabled != 0 && (goarch == "amd64" || goarch == "arm64" && goos == "linux") return framepointer_enabled != 0 && (goarch == "amd64" || goarch == "arm64" && (goos == "linux" || goos == "darwin"))
} }
func addexp(s string) { func addexp(s string) {

View file

@ -33,8 +33,8 @@ func testDWARF(t *testing.T, buildmode string, expectDWARF bool, env ...string)
t.Fatalf("go list: %v\n%s", err, out) t.Fatalf("go list: %v\n%s", err, out)
} }
if string(out) != "false\n" { if string(out) != "false\n" {
if os.Getenv("GOROOT_FINAL_OLD") != "" { if strings.HasPrefix(testenv.Builder(), "darwin-") {
t.Skip("cmd/link is stale, but $GOROOT_FINAL_OLD is set") t.Skipf("cmd/link is spuriously stale on Darwin builders - see #33598")
} }
t.Fatalf("cmd/link is stale - run go install cmd/link") t.Fatalf("cmd/link is stale - run go install cmd/link")
} }

View file

@ -616,15 +616,15 @@ func (l *Loader) checkdup(name string, r *oReader, li uint32, dup Sym) {
} }
fmt.Fprintf(os.Stderr, "cmd/link: while reading object for '%v': duplicate symbol '%s', previous def at '%v', with mismatched payload: %s\n", r.unit.Lib, name, rdup.unit.Lib, reason) fmt.Fprintf(os.Stderr, "cmd/link: while reading object for '%v': duplicate symbol '%s', previous def at '%v', with mismatched payload: %s\n", r.unit.Lib, name, rdup.unit.Lib, reason)
// For the moment, whitelist DWARF subprogram DIEs for // For the moment, allow DWARF subprogram DIEs for
// auto-generated wrapper functions. What seems to happen // auto-generated wrapper functions. What seems to happen
// here is that we get different line numbers on formal // here is that we get different line numbers on formal
// params; I am guessing that the pos is being inherited // params; I am guessing that the pos is being inherited
// from the spot where the wrapper is needed. // from the spot where the wrapper is needed.
whitelist := strings.HasPrefix(name, "go.info.go.interface") || allowed := strings.HasPrefix(name, "go.info.go.interface") ||
strings.HasPrefix(name, "go.info.go.builtin") || strings.HasPrefix(name, "go.info.go.builtin") ||
strings.HasPrefix(name, "go.debuglines") strings.HasPrefix(name, "go.debuglines")
if !whitelist { if !allowed {
l.strictDupMsgs++ l.strictDupMsgs++
} }
} }

View file

@ -138,7 +138,11 @@ func testDisasm(t *testing.T, printCode bool, printGnuAsm bool, flags ...string)
args = append(args, flags...) args = append(args, flags...)
args = append(args, "fmthello.go") args = append(args, "fmthello.go")
cmd := exec.Command(testenv.GoToolPath(t), args...) cmd := exec.Command(testenv.GoToolPath(t), args...)
cmd.Dir = "testdata" // "Bad line" bug #36683 is sensitive to being run in the source directory // "Bad line" bug #36683 is sensitive to being run in the source directory.
cmd.Dir = "testdata"
// Ensure that the source file location embedded in the binary matches our
// actual current GOROOT, instead of GOROOT_FINAL if set.
cmd.Env = append(os.Environ(), "GOROOT_FINAL=")
t.Logf("Running %v", cmd.Args) t.Logf("Running %v", cmd.Args)
out, err := cmd.CombinedOutput() out, err := cmd.CombinedOutput()
if err != nil { if err != nil {

View file

@ -278,6 +278,8 @@ type ClientSessionState struct {
serverCertificates []*x509.Certificate // Certificate chain presented by the server serverCertificates []*x509.Certificate // Certificate chain presented by the server
verifiedChains [][]*x509.Certificate // Certificate chains we built for verification verifiedChains [][]*x509.Certificate // Certificate chains we built for verification
receivedAt time.Time // When the session ticket was received from the server receivedAt time.Time // When the session ticket was received from the server
ocspResponse []byte // Stapled OCSP response presented by the server
scts [][]byte // SCTs presented by the server
// TLS 1.3 fields. // TLS 1.3 fields.
nonce []byte // Ticket nonce sent by the server, to derive PSK nonce []byte // Ticket nonce sent by the server, to derive PSK

View file

@ -728,10 +728,17 @@ func (hs *clientHandshakeState) processServerHello() (bool, error) {
return false, errors.New("tls: server resumed a session with a different cipher suite") return false, errors.New("tls: server resumed a session with a different cipher suite")
} }
// Restore masterSecret and peerCerts from previous state // Restore masterSecret, peerCerts, and ocspResponse from previous state
hs.masterSecret = hs.session.masterSecret hs.masterSecret = hs.session.masterSecret
c.peerCertificates = hs.session.serverCertificates c.peerCertificates = hs.session.serverCertificates
c.verifiedChains = hs.session.verifiedChains c.verifiedChains = hs.session.verifiedChains
c.ocspResponse = hs.session.ocspResponse
// Let the ServerHello SCTs override the session SCTs from the original
// connection, if any are provided
if len(c.scts) == 0 && len(hs.session.scts) != 0 {
c.scts = hs.session.scts
}
return true, nil return true, nil
} }
@ -788,6 +795,8 @@ func (hs *clientHandshakeState) readSessionTicket() error {
serverCertificates: c.peerCertificates, serverCertificates: c.peerCertificates,
verifiedChains: c.verifiedChains, verifiedChains: c.verifiedChains,
receivedAt: c.config.time(), receivedAt: c.config.time(),
ocspResponse: c.ocspResponse,
scts: c.scts,
} }
return nil return nil

View file

@ -19,6 +19,7 @@ import (
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"reflect"
"strconv" "strconv"
"strings" "strings"
"testing" "testing"
@ -2430,3 +2431,83 @@ func TestDowngradeCanary(t *testing.T) {
t.Errorf("client unexpectedly reacted to a canary in TLS 1.0") t.Errorf("client unexpectedly reacted to a canary in TLS 1.0")
} }
} }
func TestResumptionKeepsOCSPAndSCT(t *testing.T) {
t.Run("TLSv12", func(t *testing.T) { testResumptionKeepsOCSPAndSCT(t, VersionTLS12) })
t.Run("TLSv13", func(t *testing.T) { testResumptionKeepsOCSPAndSCT(t, VersionTLS13) })
}
func testResumptionKeepsOCSPAndSCT(t *testing.T, ver uint16) {
issuer, err := x509.ParseCertificate(testRSACertificateIssuer)
if err != nil {
t.Fatalf("failed to parse test issuer")
}
roots := x509.NewCertPool()
roots.AddCert(issuer)
clientConfig := &Config{
MaxVersion: ver,
ClientSessionCache: NewLRUClientSessionCache(32),
ServerName: "example.golang",
RootCAs: roots,
}
serverConfig := testConfig.Clone()
serverConfig.MaxVersion = ver
serverConfig.Certificates[0].OCSPStaple = []byte{1, 2, 3}
serverConfig.Certificates[0].SignedCertificateTimestamps = [][]byte{{4, 5, 6}}
_, ccs, err := testHandshake(t, clientConfig, serverConfig)
if err != nil {
t.Fatalf("handshake failed: %s", err)
}
// after a new session we expect to see OCSPResponse and
// SignedCertificateTimestamps populated as usual
if !bytes.Equal(ccs.OCSPResponse, serverConfig.Certificates[0].OCSPStaple) {
t.Errorf("client ConnectionState contained unexpected OCSPResponse: wanted %v, got %v",
serverConfig.Certificates[0].OCSPStaple, ccs.OCSPResponse)
}
if !reflect.DeepEqual(ccs.SignedCertificateTimestamps, serverConfig.Certificates[0].SignedCertificateTimestamps) {
t.Errorf("client ConnectionState contained unexpected SignedCertificateTimestamps: wanted %v, got %v",
serverConfig.Certificates[0].SignedCertificateTimestamps, ccs.SignedCertificateTimestamps)
}
// if the server doesn't send any SCTs, repopulate the old SCTs
oldSCTs := serverConfig.Certificates[0].SignedCertificateTimestamps
serverConfig.Certificates[0].SignedCertificateTimestamps = nil
_, ccs, err = testHandshake(t, clientConfig, serverConfig)
if err != nil {
t.Fatalf("handshake failed: %s", err)
}
if !ccs.DidResume {
t.Fatalf("expected session to be resumed")
}
// after a resumed session we also expect to see OCSPResponse
// and SignedCertificateTimestamps populated
if !bytes.Equal(ccs.OCSPResponse, serverConfig.Certificates[0].OCSPStaple) {
t.Errorf("client ConnectionState contained unexpected OCSPResponse after resumption: wanted %v, got %v",
serverConfig.Certificates[0].OCSPStaple, ccs.OCSPResponse)
}
if !reflect.DeepEqual(ccs.SignedCertificateTimestamps, oldSCTs) {
t.Errorf("client ConnectionState contained unexpected SignedCertificateTimestamps after resumption: wanted %v, got %v",
oldSCTs, ccs.SignedCertificateTimestamps)
}
// Only test overriding the SCTs for TLS 1.2, since in 1.3
// the server won't send the message containing them
if ver == VersionTLS13 {
return
}
// if the server changes the SCTs it sends, they should override the saved SCTs
serverConfig.Certificates[0].SignedCertificateTimestamps = [][]byte{{7, 8, 9}}
_, ccs, err = testHandshake(t, clientConfig, serverConfig)
if err != nil {
t.Fatalf("handshake failed: %s", err)
}
if !ccs.DidResume {
t.Fatalf("expected session to be resumed")
}
if !reflect.DeepEqual(ccs.SignedCertificateTimestamps, serverConfig.Certificates[0].SignedCertificateTimestamps) {
t.Errorf("client ConnectionState contained unexpected SignedCertificateTimestamps after resumption: wanted %v, got %v",
serverConfig.Certificates[0].SignedCertificateTimestamps, ccs.SignedCertificateTimestamps)
}
}

View file

@ -334,6 +334,8 @@ func (hs *clientHandshakeStateTLS13) processServerHello() error {
c.didResume = true c.didResume = true
c.peerCertificates = hs.session.serverCertificates c.peerCertificates = hs.session.serverCertificates
c.verifiedChains = hs.session.verifiedChains c.verifiedChains = hs.session.verifiedChains
c.ocspResponse = hs.session.ocspResponse
c.scts = hs.session.scts
return nil return nil
} }
@ -666,6 +668,8 @@ func (c *Conn) handleNewSessionTicket(msg *newSessionTicketMsgTLS13) error {
nonce: msg.nonce, nonce: msg.nonce,
useBy: c.config.time().Add(lifetime), useBy: c.config.time().Add(lifetime),
ageAdd: msg.ageAdd, ageAdd: msg.ageAdd,
ocspResponse: c.ocspResponse,
scts: c.scts,
} }
cacheKey := clientSessionCacheKey(c.conn.RemoteAddr(), c.config) cacheKey := clientSessionCacheKey(c.conn.RemoteAddr(), c.config)

View file

@ -2129,16 +2129,13 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv
authorityKeyId = parent.SubjectKeyId authorityKeyId = parent.SubjectKeyId
} }
encodedPublicKey := asn1.BitString{BitLength: len(publicKeyBytes) * 8, Bytes: publicKeyBytes}
pki := publicKeyInfo{nil, publicKeyAlgorithm, encodedPublicKey}
subjectKeyId := template.SubjectKeyId subjectKeyId := template.SubjectKeyId
if len(subjectKeyId) == 0 && template.IsCA { if len(subjectKeyId) == 0 && template.IsCA {
// SubjectKeyId generated using method 1 in RFC 5280, Section 4.2.1.2 // SubjectKeyId generated using method 1 in RFC 5280, Section 4.2.1.2:
b, err := asn1.Marshal(pki) // (1) The keyIdentifier is composed of the 160-bit SHA-1 hash of the
if err != nil { // value of the BIT STRING subjectPublicKey (excluding the tag,
return nil, err // length, and number of unused bits).
} h := sha1.Sum(publicKeyBytes)
h := sha1.Sum(b)
subjectKeyId = h[:] subjectKeyId = h[:]
} }
@ -2147,6 +2144,7 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv
return return
} }
encodedPublicKey := asn1.BitString{BitLength: len(publicKeyBytes) * 8, Bytes: publicKeyBytes}
c := tbsCertificate{ c := tbsCertificate{
Version: 2, Version: 2,
SerialNumber: template.SerialNumber, SerialNumber: template.SerialNumber,
@ -2154,7 +2152,7 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv
Issuer: asn1.RawValue{FullBytes: asn1Issuer}, Issuer: asn1.RawValue{FullBytes: asn1Issuer},
Validity: validity{template.NotBefore.UTC(), template.NotAfter.UTC()}, Validity: validity{template.NotBefore.UTC(), template.NotAfter.UTC()},
Subject: asn1.RawValue{FullBytes: asn1Subject}, Subject: asn1.RawValue{FullBytes: asn1Subject},
PublicKey: pki, PublicKey: publicKeyInfo{nil, publicKeyAlgorithm, encodedPublicKey},
Extensions: extensions, Extensions: extensions,
} }

View file

@ -20,6 +20,7 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"sync" "sync"
_ "unsafe" // for go:linkname
) )
// An Importer provides the context for importing packages from source code. // An Importer provides the context for importing packages from source code.
@ -133,7 +134,7 @@ func (p *Importer) ImportFrom(path, srcDir string, mode types.ImportMode) (*type
// build.Context's VFS. // build.Context's VFS.
conf.FakeImportC = true conf.FakeImportC = true
} else { } else {
conf.UsesCgo = true setUsesCgo(&conf)
file, err := p.cgo(bp) file, err := p.cgo(bp)
if err != nil { if err != nil {
return nil, err return nil, err
@ -260,3 +261,6 @@ func (p *Importer) joinPath(elem ...string) string {
} }
return filepath.Join(elem...) return filepath.Join(elem...)
} }
//go:linkname setUsesCgo go/types.srcimporter_setUsesCgo
func setUsesCgo(conf *types.Config)

View file

@ -105,14 +105,14 @@ type Config struct {
// Do not use casually! // Do not use casually!
FakeImportC bool FakeImportC bool
// If UsesCgo is set, the type checker expects the // If go115UsesCgo is set, the type checker expects the
// _cgo_gotypes.go file generated by running cmd/cgo to be // _cgo_gotypes.go file generated by running cmd/cgo to be
// provided as a package source file. Qualified identifiers // provided as a package source file. Qualified identifiers
// referring to package C will be resolved to cgo-provided // referring to package C will be resolved to cgo-provided
// declarations within _cgo_gotypes.go. // declarations within _cgo_gotypes.go.
// //
// It is an error to set both FakeImportC and UsesCgo. // It is an error to set both FakeImportC and go115UsesCgo.
UsesCgo bool go115UsesCgo bool
// If Error != nil, it is called with each error found // If Error != nil, it is called with each error found
// during type checking; err has dynamic type Error. // during type checking; err has dynamic type Error.
@ -140,6 +140,10 @@ type Config struct {
DisableUnusedImportCheck bool DisableUnusedImportCheck bool
} }
func srcimporter_setUsesCgo(conf *Config) {
conf.go115UsesCgo = true
}
// Info holds result type information for a type-checked package. // Info holds result type information for a type-checked package.
// Only the information for which a map is provided is collected. // Only the information for which a map is provided is collected.
// If the package has type errors, the collected information may // If the package has type errors, the collected information may

View file

@ -248,10 +248,10 @@ func (check *Checker) handleBailout(err *error) {
// Files checks the provided files as part of the checker's package. // Files checks the provided files as part of the checker's package.
func (check *Checker) Files(files []*ast.File) error { return check.checkFiles(files) } func (check *Checker) Files(files []*ast.File) error { return check.checkFiles(files) }
var errBadCgo = errors.New("cannot use FakeImportC and UsesCgo together") var errBadCgo = errors.New("cannot use FakeImportC and go115UsesCgo together")
func (check *Checker) checkFiles(files []*ast.File) (err error) { func (check *Checker) checkFiles(files []*ast.File) (err error) {
if check.conf.FakeImportC && check.conf.UsesCgo { if check.conf.FakeImportC && check.conf.go115UsesCgo {
return errBadCgo return errBadCgo
} }

View file

@ -141,10 +141,10 @@ func (check *Checker) importPackage(pos token.Pos, path, dir string) *Package {
} }
// no package yet => import it // no package yet => import it
if path == "C" && (check.conf.FakeImportC || check.conf.UsesCgo) { if path == "C" && (check.conf.FakeImportC || check.conf.go115UsesCgo) {
imp = NewPackage("C", "C") imp = NewPackage("C", "C")
imp.fake = true // package scope is not populated imp.fake = true // package scope is not populated
imp.cgo = check.conf.UsesCgo imp.cgo = check.conf.go115UsesCgo
} else { } else {
// ordinary import // ordinary import
var err error var err error

View file

@ -240,8 +240,7 @@ func htmlNameFilter(args ...interface{}) string {
} }
s = strings.ToLower(s) s = strings.ToLower(s)
if t := attrType(s); t != contentTypePlain { if t := attrType(s); t != contentTypePlain {
// TODO: Split attr and element name part filters so we can whitelist // TODO: Split attr and element name part filters so we can recognize known attributes.
// attributes.
return filterFailsafe return filterFailsafe
} }
for _, r := range s { for _, r := range s {

View file

@ -479,7 +479,7 @@ func DupCloseOnExec(fd int) (int, string, error) {
return dupCloseOnExecOld(fd) return dupCloseOnExecOld(fd)
} }
// dupCloseOnExecUnixOld is the traditional way to dup an fd and // dupCloseOnExecOld is the traditional way to dup an fd and
// set its O_CLOEXEC bit, using two system calls. // set its O_CLOEXEC bit, using two system calls.
func dupCloseOnExecOld(fd int) (int, string, error) { func dupCloseOnExecOld(fd int) (int, string, error) {
syscall.ForkLock.RLock() syscall.ForkLock.RLock()

View file

@ -1,153 +1,152 @@
:: Copyright 2012 The Go Authors. All rights reserved. :: Copyright 2012 The Go Authors. All rights reserved.
:: Use of this source code is governed by a BSD-style :: Use of this source code is governed by a BSD-style
:: license that can be found in the LICENSE file. :: license that can be found in the LICENSE file.
:: Environment variables that control make.bat: :: Environment variables that control make.bat:
:: ::
:: GOROOT_FINAL: The expected final Go root, baked into binaries. :: GOROOT_FINAL: The expected final Go root, baked into binaries.
:: The default is the location of the Go tree during the build. :: The default is the location of the Go tree during the build.
:: ::
:: GOHOSTARCH: The architecture for host tools (compilers and :: GOHOSTARCH: The architecture for host tools (compilers and
:: binaries). Binaries of this type must be executable on the current :: binaries). Binaries of this type must be executable on the current
:: system, so the only common reason to set this is to set :: system, so the only common reason to set this is to set
:: GOHOSTARCH=386 on an amd64 machine. :: GOHOSTARCH=386 on an amd64 machine.
:: ::
:: GOARCH: The target architecture for installed packages and tools. :: GOARCH: The target architecture for installed packages and tools.
:: ::
:: GOOS: The target operating system for installed packages and tools. :: GOOS: The target operating system for installed packages and tools.
:: ::
:: GO_GCFLAGS: Additional go tool compile arguments to use when :: GO_GCFLAGS: Additional go tool compile arguments to use when
:: building the packages and commands. :: building the packages and commands.
:: ::
:: GO_LDFLAGS: Additional go tool link arguments to use when :: GO_LDFLAGS: Additional go tool link arguments to use when
:: building the commands. :: building the commands.
:: ::
:: CGO_ENABLED: Controls cgo usage during the build. Set it to 1 :: CGO_ENABLED: Controls cgo usage during the build. Set it to 1
:: to include all cgo related files, .c and .go file with "cgo" :: to include all cgo related files, .c and .go file with "cgo"
:: build directive, in the build. Set it to 0 to ignore them. :: build directive, in the build. Set it to 0 to ignore them.
:: ::
:: CC: Command line to run to compile C code for GOHOSTARCH. :: CC: Command line to run to compile C code for GOHOSTARCH.
:: Default is "gcc". :: Default is "gcc".
:: ::
:: CC_FOR_TARGET: Command line to run compile C code for GOARCH. :: CC_FOR_TARGET: Command line to run compile C code for GOARCH.
:: This is used by cgo. Default is CC. :: This is used by cgo. Default is CC.
:: ::
:: FC: Command line to run to compile Fortran code. :: FC: Command line to run to compile Fortran code.
:: This is used by cgo. Default is "gfortran". :: This is used by cgo. Default is "gfortran".
@echo off @echo off
:: Keep environment variables within this script :: Keep environment variables within this script
:: unless invoked with --no-local. :: unless invoked with --no-local.
if x%1==x--no-local goto nolocal if x%1==x--no-local goto nolocal
if x%2==x--no-local goto nolocal if x%2==x--no-local goto nolocal
if x%3==x--no-local goto nolocal if x%3==x--no-local goto nolocal
if x%4==x--no-local goto nolocal if x%4==x--no-local goto nolocal
setlocal setlocal
:nolocal :nolocal
set GOENV=off set GOENV=off
set GOBUILDFAIL=0 set GOBUILDFAIL=0
set GOFLAGS= set GOFLAGS=
set GO111MODULE= set GO111MODULE=
if exist make.bat goto ok if exist make.bat goto ok
echo Must run make.bat from Go src directory. echo Must run make.bat from Go src directory.
goto fail goto fail
:ok :ok
:: Clean old generated file that will cause problems in the build. :: Clean old generated file that will cause problems in the build.
del /F ".\pkg\runtime\runtime_defs.go" 2>NUL del /F ".\pkg\runtime\runtime_defs.go" 2>NUL
:: Set GOROOT for build. :: Set GOROOT for build.
cd .. cd ..
set GOROOT_TEMP=%CD% set GOROOT_TEMP=%CD%
set GOROOT= set GOROOT=
cd src cd src
set vflag= set vflag=
if x%1==x-v set vflag=-v if x%1==x-v set vflag=-v
if x%2==x-v set vflag=-v if x%2==x-v set vflag=-v
if x%3==x-v set vflag=-v if x%3==x-v set vflag=-v
if x%4==x-v set vflag=-v if x%4==x-v set vflag=-v
if not exist ..\bin\tool mkdir ..\bin\tool if not exist ..\bin\tool mkdir ..\bin\tool
:: Calculating GOROOT_BOOTSTRAP :: Calculating GOROOT_BOOTSTRAP
if not "x%GOROOT_BOOTSTRAP%"=="x" goto bootstrapset if not "x%GOROOT_BOOTSTRAP%"=="x" goto bootstrapset
for /f "tokens=*" %%g in ('where go 2^>nul') do ( for /f "tokens=*" %%g in ('where go 2^>nul') do (
if "x%GOROOT_BOOTSTRAP%"=="x" ( if "x%GOROOT_BOOTSTRAP%"=="x" (
for /f "tokens=*" %%i in ('%%g env GOROOT 2^>nul') do ( for /f "tokens=*" %%i in ('%%g env GOROOT 2^>nul') do (
if /I not %%i==%GOROOT_TEMP% ( if /I not %%i==%GOROOT_TEMP% (
set GOROOT_BOOTSTRAP=%%i set GOROOT_BOOTSTRAP=%%i
) )
) )
) )
) )
if "x%GOROOT_BOOTSTRAP%"=="x" set GOROOT_BOOTSTRAP=%HOMEDRIVE%%HOMEPATH%\Go1.4 if "x%GOROOT_BOOTSTRAP%"=="x" set GOROOT_BOOTSTRAP=%HOMEDRIVE%%HOMEPATH%\Go1.4
:bootstrapset :bootstrapset
if not exist "%GOROOT_BOOTSTRAP%\bin\go.exe" goto bootstrapfail if not exist "%GOROOT_BOOTSTRAP%\bin\go.exe" goto bootstrapfail
set GOROOT=%GOROOT_TEMP% set GOROOT=%GOROOT_TEMP%
set GOROOT_TEMP= set GOROOT_TEMP=
echo Building Go cmd/dist using %GOROOT_BOOTSTRAP% echo Building Go cmd/dist using %GOROOT_BOOTSTRAP%
if x%vflag==x-v echo cmd/dist if x%vflag==x-v echo cmd/dist
setlocal setlocal
set GOROOT=%GOROOT_BOOTSTRAP% set GOROOT=%GOROOT_BOOTSTRAP%
set GOOS= set GOOS=
set GOARCH= set GOARCH=
set GOBIN= set GOBIN=
set GO111MODULE=off set GO111MODULE=off
"%GOROOT_BOOTSTRAP%\bin\go.exe" build -o cmd\dist\dist.exe .\cmd\dist "%GOROOT_BOOTSTRAP%\bin\go.exe" build -o cmd\dist\dist.exe .\cmd\dist
endlocal endlocal
if errorlevel 1 goto fail if errorlevel 1 goto fail
.\cmd\dist\dist.exe env -w -p >env.bat .\cmd\dist\dist.exe env -w -p >env.bat
if errorlevel 1 goto fail if errorlevel 1 goto fail
call env.bat call env.bat
del env.bat del env.bat
if x%vflag==x-v echo. if x%vflag==x-v echo.
if x%1==x--dist-tool goto copydist if x%1==x--dist-tool goto copydist
if x%2==x--dist-tool goto copydist if x%2==x--dist-tool goto copydist
if x%3==x--dist-tool goto copydist if x%3==x--dist-tool goto copydist
if x%4==x--dist-tool goto copydist if x%4==x--dist-tool goto copydist
set buildall=-a set buildall=-a
if x%1==x--no-clean set buildall= if x%1==x--no-clean set buildall=
if x%2==x--no-clean set buildall= if x%2==x--no-clean set buildall=
if x%3==x--no-clean set buildall= if x%3==x--no-clean set buildall=
if x%4==x--no-clean set buildall= if x%4==x--no-clean set buildall=
if x%1==x--no-banner set buildall=%buildall% --no-banner if x%1==x--no-banner set buildall=%buildall% --no-banner
if x%2==x--no-banner set buildall=%buildall% --no-banner if x%2==x--no-banner set buildall=%buildall% --no-banner
if x%3==x--no-banner set buildall=%buildall% --no-banner if x%3==x--no-banner set buildall=%buildall% --no-banner
if x%4==x--no-banner set buildall=%buildall% --no-banner if x%4==x--no-banner set buildall=%buildall% --no-banner
:: Run dist bootstrap to complete make.bash. :: Run dist bootstrap to complete make.bash.
:: Bootstrap installs a proper cmd/dist, built with the new toolchain. :: Bootstrap installs a proper cmd/dist, built with the new toolchain.
:: Throw ours, built with Go 1.4, away after bootstrap. :: Throw ours, built with Go 1.4, away after bootstrap.
.\cmd\dist\dist.exe bootstrap %vflag% %buildall% .\cmd\dist\dist.exe bootstrap %vflag% %buildall%
if errorlevel 1 goto fail if errorlevel 1 goto fail
del .\cmd\dist\dist.exe del .\cmd\dist\dist.exe
goto end goto end
:: DO NOT ADD ANY NEW CODE HERE. :: DO NOT ADD ANY NEW CODE HERE.
:: The bootstrap+del above are the final step of make.bat. :: The bootstrap+del above are the final step of make.bat.
:: If something must be added, add it to cmd/dist's cmdbootstrap, :: If something must be added, add it to cmd/dist's cmdbootstrap,
:: to avoid needing three copies in three different shell languages :: to avoid needing three copies in three different shell languages
:: (make.bash, make.bat, make.rc). :: (make.bash, make.bat, make.rc).
:copydist :copydist
mkdir "%GOTOOLDIR%" 2>NUL mkdir "%GOTOOLDIR%" 2>NUL
copy cmd\dist\dist.exe "%GOTOOLDIR%\" copy cmd\dist\dist.exe "%GOTOOLDIR%\"
goto end goto end
:bootstrapfail :bootstrapfail
echo ERROR: Cannot find %GOROOT_BOOTSTRAP%\bin\go.exe echo ERROR: Cannot find %GOROOT_BOOTSTRAP%\bin\go.exe
echo Set GOROOT_BOOTSTRAP to a working Go tree ^>= Go 1.4. echo Set GOROOT_BOOTSTRAP to a working Go tree ^>= Go 1.4.
:fail :fail
set GOBUILDFAIL=1 set GOBUILDFAIL=1
if x%GOBUILDEXIT%==x1 exit %GOBUILDFAIL% if x%GOBUILDEXIT%==x1 exit %GOBUILDFAIL%
:end :end

View file

@ -503,7 +503,7 @@ func valueOrDefault(value, def string) string {
// NOTE: This is not intended to reflect the actual Go version being used. // NOTE: This is not intended to reflect the actual Go version being used.
// It was changed at the time of Go 1.1 release because the former User-Agent // It was changed at the time of Go 1.1 release because the former User-Agent
// had ended up on a blacklist for some intrusion detection systems. // had ended up blocked by some intrusion detection systems.
// See https://codereview.appspot.com/7532043. // See https://codereview.appspot.com/7532043.
const defaultUserAgent = "Go-http-client/1.1" const defaultUserAgent = "Go-http-client/1.1"

View file

@ -1698,9 +1698,9 @@ func (c *conn) closeWriteAndWait() {
time.Sleep(rstAvoidanceDelay) time.Sleep(rstAvoidanceDelay)
} }
// validNextProto reports whether the proto is not a blacklisted ALPN // validNextProto reports whether the proto is a valid ALPN protocol name.
// protocol name. Empty and built-in protocol types are blacklisted // Everything is valid except the empty string and built-in protocol types,
// and can't be overridden with alternate implementations. // so that those can't be overridden with alternate implementations.
func validNextProto(proto string) bool { func validNextProto(proto string) bool {
switch proto { switch proto {
case "", "http/1.1", "http/1.0": case "", "http/1.1", "http/1.0":

View file

@ -202,10 +202,8 @@ func openFileNolog(name string, flag int, perm FileMode) (*File, error) {
break break
} }
// On OS X, sigaction(2) doesn't guarantee that SA_RESTART will cause // We have to check EINTR here, per issues 11180 and 39237.
// open(2) to be restarted for regular files. This is easy to reproduce on if e == syscall.EINTR {
// fuse file systems (see https://golang.org/issue/11180).
if runtime.GOOS == "darwin" && e == syscall.EINTR {
continue continue
} }

View file

@ -9,7 +9,6 @@ package os
import ( import (
"internal/syscall/unix" "internal/syscall/unix"
"io" "io"
"runtime"
"syscall" "syscall"
) )
@ -178,7 +177,7 @@ func openFdAt(dirfd int, name string) (*File, error) {
} }
// See comment in openFileNolog. // See comment in openFileNolog.
if runtime.GOOS == "darwin" && e == syscall.EINTR { if e == syscall.EINTR {
continue continue
} }

View file

@ -40,8 +40,8 @@ func (e *PtyError) Error() string {
func (e *PtyError) Unwrap() error { return e.Errno } func (e *PtyError) Unwrap() error { return e.Errno }
// Open returns a master pty and the name of the linked slave tty. // Open returns a control pty and the name of the linked process tty.
func Open() (master *os.File, slave string, err error) { func Open() (pty *os.File, processTTY string, err error) {
m, err := C.posix_openpt(C.O_RDWR) m, err := C.posix_openpt(C.O_RDWR)
if err != nil { if err != nil {
return nil, "", ptyError("posix_openpt", err) return nil, "", ptyError("posix_openpt", err)
@ -54,6 +54,6 @@ func Open() (master *os.File, slave string, err error) {
C.close(m) C.close(m)
return nil, "", ptyError("unlockpt", err) return nil, "", ptyError("unlockpt", err)
} }
slave = C.GoString(C.ptsname(m)) processTTY = C.GoString(C.ptsname(m))
return os.NewFile(uintptr(m), "pty-master"), slave, nil return os.NewFile(uintptr(m), "pty"), processTTY, nil
} }

View file

@ -19,7 +19,7 @@ import (
"io" "io"
"os" "os"
"os/exec" "os/exec"
"os/signal/internal/pty" ptypkg "os/signal/internal/pty"
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
@ -71,20 +71,20 @@ func TestTerminalSignal(t *testing.T) {
// The test only fails when using a "slow device," in this // The test only fails when using a "slow device," in this
// case a pseudo-terminal. // case a pseudo-terminal.
master, sname, err := pty.Open() pty, procTTYName, err := ptypkg.Open()
if err != nil { if err != nil {
ptyErr := err.(*pty.PtyError) ptyErr := err.(*ptypkg.PtyError)
if ptyErr.FuncName == "posix_openpt" && ptyErr.Errno == syscall.EACCES { if ptyErr.FuncName == "posix_openpt" && ptyErr.Errno == syscall.EACCES {
t.Skip("posix_openpt failed with EACCES, assuming chroot and skipping") t.Skip("posix_openpt failed with EACCES, assuming chroot and skipping")
} }
t.Fatal(err) t.Fatal(err)
} }
defer master.Close() defer pty.Close()
slave, err := os.OpenFile(sname, os.O_RDWR, 0) procTTY, err := os.OpenFile(procTTYName, os.O_RDWR, 0)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
defer slave.Close() defer procTTY.Close()
// Start an interactive shell. // Start an interactive shell.
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
@ -92,9 +92,9 @@ func TestTerminalSignal(t *testing.T) {
cmd := exec.CommandContext(ctx, bash, "--norc", "--noprofile", "-i") cmd := exec.CommandContext(ctx, bash, "--norc", "--noprofile", "-i")
// Clear HISTFILE so that we don't read or clobber the user's bash history. // Clear HISTFILE so that we don't read or clobber the user's bash history.
cmd.Env = append(os.Environ(), "HISTFILE=") cmd.Env = append(os.Environ(), "HISTFILE=")
cmd.Stdin = slave cmd.Stdin = procTTY
cmd.Stdout = slave cmd.Stdout = procTTY
cmd.Stderr = slave cmd.Stderr = procTTY
cmd.SysProcAttr = &syscall.SysProcAttr{ cmd.SysProcAttr = &syscall.SysProcAttr{
Setsid: true, Setsid: true,
Setctty: true, Setctty: true,
@ -105,21 +105,21 @@ func TestTerminalSignal(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if err := slave.Close(); err != nil { if err := procTTY.Close(); err != nil {
t.Errorf("closing slave: %v", err) t.Errorf("closing procTTY: %v", err)
} }
progReady := make(chan bool) progReady := make(chan bool)
sawPrompt := make(chan bool, 10) sawPrompt := make(chan bool, 10)
const prompt = "prompt> " const prompt = "prompt> "
// Read data from master in the background. // Read data from pty in the background.
var wg sync.WaitGroup var wg sync.WaitGroup
wg.Add(1) wg.Add(1)
defer wg.Wait() defer wg.Wait()
go func() { go func() {
defer wg.Done() defer wg.Done()
input := bufio.NewReader(master) input := bufio.NewReader(pty)
var line, handled []byte var line, handled []byte
for { for {
b, err := input.ReadByte() b, err := input.ReadByte()
@ -130,11 +130,11 @@ func TestTerminalSignal(t *testing.T) {
if perr, ok := err.(*os.PathError); ok { if perr, ok := err.(*os.PathError); ok {
err = perr.Err err = perr.Err
} }
// EOF means master is closed. // EOF means pty is closed.
// EIO means child process is done. // EIO means child process is done.
// "file already closed" means deferred close of master has happened. // "file already closed" means deferred close of pty has happened.
if err != io.EOF && err != syscall.EIO && !strings.Contains(err.Error(), "file already closed") { if err != io.EOF && err != syscall.EIO && !strings.Contains(err.Error(), "file already closed") {
t.Logf("error reading from master: %v", err) t.Logf("error reading from pty: %v", err)
} }
return return
} }
@ -161,7 +161,7 @@ func TestTerminalSignal(t *testing.T) {
}() }()
// Set the bash prompt so that we can see it. // Set the bash prompt so that we can see it.
if _, err := master.Write([]byte("PS1='" + prompt + "'\n")); err != nil { if _, err := pty.Write([]byte("PS1='" + prompt + "'\n")); err != nil {
t.Fatalf("setting prompt: %v", err) t.Fatalf("setting prompt: %v", err)
} }
select { select {
@ -172,7 +172,7 @@ func TestTerminalSignal(t *testing.T) {
// Start a small program that reads from stdin // Start a small program that reads from stdin
// (namely the code at the top of this function). // (namely the code at the top of this function).
if _, err := master.Write([]byte("GO_TEST_TERMINAL_SIGNALS=1 " + os.Args[0] + " -test.run=TestTerminalSignal\n")); err != nil { if _, err := pty.Write([]byte("GO_TEST_TERMINAL_SIGNALS=1 " + os.Args[0] + " -test.run=TestTerminalSignal\n")); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -190,7 +190,7 @@ func TestTerminalSignal(t *testing.T) {
time.Sleep(pause) time.Sleep(pause)
// Send a ^Z to stop the program. // Send a ^Z to stop the program.
if _, err := master.Write([]byte{26}); err != nil { if _, err := pty.Write([]byte{26}); err != nil {
t.Fatalf("writing ^Z to pty: %v", err) t.Fatalf("writing ^Z to pty: %v", err)
} }
@ -202,7 +202,7 @@ func TestTerminalSignal(t *testing.T) {
} }
// Restart the stopped program. // Restart the stopped program.
if _, err := master.Write([]byte("fg\n")); err != nil { if _, err := pty.Write([]byte("fg\n")); err != nil {
t.Fatalf("writing %q to pty: %v", "fg", err) t.Fatalf("writing %q to pty: %v", "fg", err)
} }
@ -217,7 +217,7 @@ func TestTerminalSignal(t *testing.T) {
// Write some data for the program to read, // Write some data for the program to read,
// which should cause it to exit. // which should cause it to exit.
if _, err := master.Write([]byte{'\n'}); err != nil { if _, err := pty.Write([]byte{'\n'}); err != nil {
t.Fatalf("writing %q to pty: %v", "\n", err) t.Fatalf("writing %q to pty: %v", "\n", err)
} }
@ -229,7 +229,7 @@ func TestTerminalSignal(t *testing.T) {
} }
// Exit the shell with the program's exit status. // Exit the shell with the program's exit status.
if _, err := master.Write([]byte("exit $?\n")); err != nil { if _, err := pty.Write([]byte("exit $?\n")); err != nil {
t.Fatalf("writing %q to pty: %v", "exit", err) t.Fatalf("writing %q to pty: %v", "exit", err)
} }

View file

@ -1,51 +1,51 @@
:: Copyright 2013 The Go Authors. All rights reserved. :: Copyright 2013 The Go Authors. All rights reserved.
:: Use of this source code is governed by a BSD-style :: Use of this source code is governed by a BSD-style
:: license that can be found in the LICENSE file. :: license that can be found in the LICENSE file.
:: race.bash tests the standard library under the race detector. :: race.bash tests the standard library under the race detector.
:: https://golang.org/doc/articles/race_detector.html :: https://golang.org/doc/articles/race_detector.html
@echo off @echo off
setlocal setlocal
if exist make.bat goto ok if exist make.bat goto ok
echo race.bat must be run from go\src echo race.bat must be run from go\src
:: cannot exit: would kill parent command interpreter :: cannot exit: would kill parent command interpreter
goto end goto end
:ok :ok
set GOROOT=%CD%\.. set GOROOT=%CD%\..
call make.bat --dist-tool >NUL call make.bat --dist-tool >NUL
if errorlevel 1 goto fail if errorlevel 1 goto fail
.\cmd\dist\dist.exe env -w -p >env.bat .\cmd\dist\dist.exe env -w -p >env.bat
if errorlevel 1 goto fail if errorlevel 1 goto fail
call env.bat call env.bat
del env.bat del env.bat
if %GOHOSTARCH% == amd64 goto continue if %GOHOSTARCH% == amd64 goto continue
echo Race detector is only supported on windows/amd64. echo Race detector is only supported on windows/amd64.
goto fail goto fail
:continue :continue
call make.bat --no-banner --no-local call make.bat --no-banner --no-local
if %GOBUILDFAIL%==1 goto end if %GOBUILDFAIL%==1 goto end
echo # go install -race std echo # go install -race std
go install -race std go install -race std
if errorlevel 1 goto fail if errorlevel 1 goto fail
go tool dist test -race go tool dist test -race
if errorlevel 1 goto fail if errorlevel 1 goto fail
goto succ goto succ
:fail :fail
set GOBUILDFAIL=1 set GOBUILDFAIL=1
echo Fail. echo Fail.
goto end goto end
:succ :succ
echo All tests passed. echo All tests passed.
:end :end
if x%GOBUILDEXIT%==x1 exit %GOBUILDFAIL% if x%GOBUILDEXIT%==x1 exit %GOBUILDFAIL%

View file

@ -1,59 +1,54 @@
:: Copyright 2012 The Go Authors. All rights reserved. :: Copyright 2012 The Go Authors. All rights reserved.
:: Use of this source code is governed by a BSD-style :: Use of this source code is governed by a BSD-style
:: license that can be found in the LICENSE file. :: license that can be found in the LICENSE file.
@echo off @echo off
if exist ..\bin\go.exe goto ok if exist ..\bin\go.exe goto ok
echo Must run run.bat from Go src directory after installing cmd/go. echo Must run run.bat from Go src directory after installing cmd/go.
goto fail goto fail
:ok :ok
:: Keep environment variables within this script :: Keep environment variables within this script
:: unless invoked with --no-local. :: unless invoked with --no-local.
if x%1==x--no-local goto nolocal if x%1==x--no-local goto nolocal
if x%2==x--no-local goto nolocal if x%2==x--no-local goto nolocal
setlocal setlocal
:nolocal :nolocal
set GOBUILDFAIL=0 set GOBUILDFAIL=0
:: we disallow local import for non-local packages, if %GOROOT% happens :: we disallow local import for non-local packages, if %GOROOT% happens
:: to be under %GOPATH%, then some tests below will fail :: to be under %GOPATH%, then some tests below will fail
set GOPATH= set GOPATH=
:: Issue 14340: ignore GOBIN during all.bat. :: Issue 14340: ignore GOBIN during all.bat.
set GOBIN= set GOBIN=
set GOFLAGS= set GOFLAGS=
set GO111MODULE= set GO111MODULE=
rem TODO avoid rebuild if possible rem TODO avoid rebuild if possible
if x%1==x--no-rebuild goto norebuild if x%1==x--no-rebuild goto norebuild
echo ##### Building packages and commands. echo ##### Building packages and commands.
..\bin\go install -a -v std cmd ..\bin\go install -a -v std cmd
if errorlevel 1 goto fail if errorlevel 1 goto fail
echo. echo.
:norebuild :norebuild
:: we must unset GOROOT_FINAL before tests, because runtime/debug requires :: get CGO_ENABLED
:: correct access to source code, so if we have GOROOT_FINAL in effect, ..\bin\go env > env.bat
:: at least runtime/debug test will fail. if errorlevel 1 goto fail
set GOROOT_FINAL= call env.bat
del env.bat
:: get CGO_ENABLED echo.
..\bin\go env > env.bat
if errorlevel 1 goto fail ..\bin\go tool dist test
call env.bat if errorlevel 1 goto fail
del env.bat echo.
echo.
goto end
..\bin\go tool dist test
if errorlevel 1 goto fail :fail
echo. set GOBUILDFAIL=1
goto end :end
:fail
set GOBUILDFAIL=1
:end

View file

@ -18,12 +18,12 @@ var _cgo_sigaction unsafe.Pointer
//go:nosplit //go:nosplit
//go:nowritebarrierrec //go:nowritebarrierrec
func sigaction(sig uint32, new, old *sigactiont) { func sigaction(sig uint32, new, old *sigactiont) {
// The runtime package is explicitly blacklisted from sanitizer // racewalk.go avoids adding sanitizing instrumentation to package runtime,
// instrumentation in racewalk.go, but we might be calling into instrumented C // but we might be calling into instrumented C functions here,
// functions here — so we need the pointer parameters to be properly marked. // so we need the pointer parameters to be properly marked.
// //
// Mark the input as having been written before the call and the output as // Mark the input as having been written before the call
// read after. // and the output as read after.
if msanenabled && new != nil { if msanenabled && new != nil {
msanwrite(unsafe.Pointer(new), unsafe.Sizeof(*new)) msanwrite(unsafe.Pointer(new), unsafe.Sizeof(*new))
} }

View file

@ -61,7 +61,7 @@ func debugCallCheck(pc uintptr) string {
"debugCall16384", "debugCall16384",
"debugCall32768", "debugCall32768",
"debugCall65536": "debugCall65536":
// These functions are whitelisted so that the debugger can initiate multiple function calls. // These functions are allowed so that the debugger can initiate multiple function calls.
// See: https://golang.org/cl/161137/ // See: https://golang.org/cl/161137/
return return
} }

View file

@ -976,6 +976,7 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
throw("malloc called with no P") throw("malloc called with no P")
} }
} }
var span *mspan
var x unsafe.Pointer var x unsafe.Pointer
noscan := typ == nil || typ.ptrdata == 0 noscan := typ == nil || typ.ptrdata == 0
if size <= maxSmallSize { if size <= maxSmallSize {
@ -1028,10 +1029,10 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
return x return x
} }
// Allocate a new maxTinySize block. // Allocate a new maxTinySize block.
span := c.alloc[tinySpanClass] span = c.alloc[tinySpanClass]
v := nextFreeFast(span) v := nextFreeFast(span)
if v == 0 { if v == 0 {
v, _, shouldhelpgc = c.nextFree(tinySpanClass) v, span, shouldhelpgc = c.nextFree(tinySpanClass)
} }
x = unsafe.Pointer(v) x = unsafe.Pointer(v)
(*[2]uint64)(x)[0] = 0 (*[2]uint64)(x)[0] = 0
@ -1052,7 +1053,7 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
} }
size = uintptr(class_to_size[sizeclass]) size = uintptr(class_to_size[sizeclass])
spc := makeSpanClass(sizeclass, noscan) spc := makeSpanClass(sizeclass, noscan)
span := c.alloc[spc] span = c.alloc[spc]
v := nextFreeFast(span) v := nextFreeFast(span)
if v == 0 { if v == 0 {
v, span, shouldhelpgc = c.nextFree(spc) v, span, shouldhelpgc = c.nextFree(spc)
@ -1063,15 +1064,14 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
} }
} }
} else { } else {
var s *mspan
shouldhelpgc = true shouldhelpgc = true
systemstack(func() { systemstack(func() {
s = largeAlloc(size, needzero, noscan) span = largeAlloc(size, needzero, noscan)
}) })
s.freeindex = 1 span.freeindex = 1
s.allocCount = 1 span.allocCount = 1
x = unsafe.Pointer(s.base()) x = unsafe.Pointer(span.base())
size = s.elemsize size = span.elemsize
} }
var scanSize uintptr var scanSize uintptr
@ -1112,7 +1112,7 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
// This may be racing with GC so do it atomically if there can be // This may be racing with GC so do it atomically if there can be
// a race marking the bit. // a race marking the bit.
if gcphase != _GCoff { if gcphase != _GCoff {
gcmarknewobject(uintptr(x), size, scanSize) gcmarknewobject(span, uintptr(x), size, scanSize)
} }
if raceenabled { if raceenabled {

View file

@ -1627,11 +1627,21 @@ func gcDumpObject(label string, obj, off uintptr) {
// //
//go:nowritebarrier //go:nowritebarrier
//go:nosplit //go:nosplit
func gcmarknewobject(obj, size, scanSize uintptr) { func gcmarknewobject(span *mspan, obj, size, scanSize uintptr) {
if useCheckmark { // The world should be stopped so this should not happen. if useCheckmark { // The world should be stopped so this should not happen.
throw("gcmarknewobject called while doing checkmark") throw("gcmarknewobject called while doing checkmark")
} }
markBitsForAddr(obj).setMarked()
// Mark object.
objIndex := span.objIndex(obj)
span.markBitsForIndex(objIndex).setMarked()
// Mark span.
arena, pageIdx, pageMask := pageIndexOf(span.base())
if arena.pageMarks[pageIdx]&pageMask == 0 {
atomic.Or8(&arena.pageMarks[pageIdx], pageMask)
}
gcw := &getg().m.p.ptr().gcw gcw := &getg().m.p.ptr().gcw
gcw.bytesMarked += uint64(size) gcw.bytesMarked += uint64(size)
gcw.scanWork += int64(scanSize) gcw.scanWork += int64(scanSize)

View file

@ -529,7 +529,7 @@ func updatememstats() {
// Calculate memory allocator stats. // Calculate memory allocator stats.
// During program execution we only count number of frees and amount of freed memory. // During program execution we only count number of frees and amount of freed memory.
// Current number of alive object in the heap and amount of alive heap memory // Current number of alive objects in the heap and amount of alive heap memory
// are calculated by scanning all spans. // are calculated by scanning all spans.
// Total number of mallocs is calculated as number of frees plus number of alive objects. // Total number of mallocs is calculated as number of frees plus number of alive objects.
// Similarly, total amount of allocated memory is calculated as amount of freed memory // Similarly, total amount of allocated memory is calculated as amount of freed memory

View file

@ -296,6 +296,13 @@ func wbBufFlush1(_p_ *p) {
continue continue
} }
mbits.setMarked() mbits.setMarked()
// Mark span.
arena, pageIdx, pageMask := pageIndexOf(span.base())
if arena.pageMarks[pageIdx]&pageMask == 0 {
atomic.Or8(&arena.pageMarks[pageIdx], pageMask)
}
if span.spanclass.noscan() { if span.spanclass.noscan() {
gcw.bytesMarked += uint64(span.elemsize) gcw.bytesMarked += uint64(span.elemsize)
continue continue

View file

@ -563,8 +563,8 @@ func moduledataverify1(datap *moduledata) {
// given program counter address, or else nil. // given program counter address, or else nil.
// //
// If pc represents multiple functions because of inlining, it returns // If pc represents multiple functions because of inlining, it returns
// the a *Func describing the innermost function, but with an entry // the *Func describing the innermost function, but with an entry of
// of the outermost function. // the outermost function.
func FuncForPC(pc uintptr) *Func { func FuncForPC(pc uintptr) *Func {
f := findfunc(pc) f := findfunc(pc)
if !f.valid() { if !f.valid() {

View file

@ -253,6 +253,8 @@ func CmpLogicalToZero(a, b, c uint32, d, e uint64) uint64 {
// 'comparing to zero' expressions // 'comparing to zero' expressions
// var + const // var + const
// 'x-const' might be canonicalized to 'x+(-const)', so we check both
// CMN and CMP for subtraction expressions to make the pattern robust.
func CmpToZero_ex1(a int64, e int32) int { func CmpToZero_ex1(a int64, e int32) int {
// arm64:`CMN`,-`ADD`,`(BMI|BPL)` // arm64:`CMN`,-`ADD`,`(BMI|BPL)`
if a+3 < 0 { if a+3 < 0 {
@ -269,37 +271,41 @@ func CmpToZero_ex1(a int64, e int32) int {
return 2 return 2
} }
// arm64:`CMP`,-`SUB`,`(BMI|BPL)` // arm64:`CMP|CMN`,-`(ADD|SUB)`,`(BMI|BPL)`
if a-7 < 0 { if a-7 < 0 {
return 3 return 3
} }
// arm64:`CMP`,-`SUB`,`(BMI|BPL)` // arm64:`CMP|CMN`,-`(ADD|SUB)`,`(BMI|BPL)`
if a-11 >= 0 { if a-11 >= 0 {
return 4 return 4
} }
// arm64:`CMP`,-`SUB`,`BEQ`,`(BMI|BPL)` // arm64:`CMP|CMN`,-`(ADD|SUB)`,`BEQ`,`(BMI|BPL)`
if a-19 > 0 { if a-19 > 0 {
return 4 return 4
} }
// arm64:`CMNW`,-`ADDW`,`(BMI|BPL)` // arm64:`CMNW`,-`ADDW`,`(BMI|BPL)`
// arm:`CMN`,-`ADD`,`(BMI|BPL)`
if e+3 < 0 { if e+3 < 0 {
return 5 return 5
} }
// arm64:`CMNW`,-`ADDW`,`(BMI|BPL)` // arm64:`CMNW`,-`ADDW`,`(BMI|BPL)`
// arm:`CMN`,-`ADD`,`(BMI|BPL)`
if e+13 >= 0 { if e+13 >= 0 {
return 6 return 6
} }
// arm64:`CMPW`,-`SUBW`,`(BMI|BPL)` // arm64:`CMPW|CMNW`,`(BMI|BPL)`
// arm:`CMP|CMN`, -`(ADD|SUB)`, `(BMI|BPL)`
if e-7 < 0 { if e-7 < 0 {
return 7 return 7
} }
// arm64:`CMPW`,-`SUBW`,`(BMI|BPL)` // arm64:`CMPW|CMNW`,`(BMI|BPL)`
// arm:`CMP|CMN`, -`(ADD|SUB)`, `(BMI|BPL)`
if e-11 >= 0 { if e-11 >= 0 {
return 8 return 8
} }
@ -326,11 +332,13 @@ func CmpToZero_ex2(a, b, c int64, e, f, g int32) int {
} }
// arm64:`CMNW`,-`ADDW`,`(BMI|BPL)` // arm64:`CMNW`,-`ADDW`,`(BMI|BPL)`
// arm:`CMN`,-`ADD`,`(BMI|BPL)`
if e+f < 0 { if e+f < 0 {
return 5 return 5
} }
// arm64:`CMNW`,-`ADDW`,`(BMI|BPL)` // arm64:`CMNW`,-`ADDW`,`(BMI|BPL)`
// arm:`CMN`,-`ADD`,`(BMI|BPL)`
if f+g >= 0 { if f+g >= 0 {
return 6 return 6
} }
@ -350,11 +358,13 @@ func CmpToZero_ex3(a, b, c, d int64, e, f, g, h int32) int {
} }
// arm64:`CMNW`,-`MADDW`,`MULW`,`BEQ`,`(BMI|BPL)` // arm64:`CMNW`,-`MADDW`,`MULW`,`BEQ`,`(BMI|BPL)`
// arm:`CMN`,-`MULA`,`MUL`,`BEQ`,`(BMI|BPL)`
if e+f*g > 0 { if e+f*g > 0 {
return 5 return 5
} }
// arm64:`CMNW`,-`MADDW`,`MULW`,`BEQ`,`(BMI|BPL)` // arm64:`CMNW`,-`MADDW`,`MULW`,`BEQ`,`(BMI|BPL)`
// arm:`CMN`,-`MULA`,`MUL`,`BEQ`,`(BMI|BPL)`
if f+g*h <= 0 { if f+g*h <= 0 {
return 6 return 6
} }
@ -384,3 +394,16 @@ func CmpToZero_ex4(a, b, c, d int64, e, f, g, h int32) int {
} }
return 0 return 0
} }
func CmpToZero_ex5(e, f int32, u uint32) int {
// arm:`CMN`,-`ADD`,`BEQ`,`(BMI|BPL)`
if e+f<<1 > 0 {
return 1
}
// arm:`CMP`,-`SUB`,`(BMI|BPL)`
if f-int32(u>>2) >= 0 {
return 2
}
return 0
}

View file

@ -0,0 +1,12 @@
// compile -N
// Copyright 2020 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 p
func f(x float64) bool {
x += 1
return (x != 0) == (x != 0)
}

View file

@ -4,8 +4,8 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// Check that batch files are maintained as CRLF files (consistent behaviour // Check that batch files are maintained as CRLF files (consistent
// on all operating systems). See https://github.com/golang/go/issues/37791 // behavior on all operating systems). See golang.org/issue/37791.
package main package main
@ -13,18 +13,56 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log"
"os" "os"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strings"
) )
func main() { func main() {
batches, _ := filepath.Glob(runtime.GOROOT() + "/src/*.bat") // Ensure that the GOROOT/src/all.bat file exists and has strict CRLF line endings.
for _, bat := range batches { enforceBatchStrictCRLF(filepath.Join(runtime.GOROOT(), "src", "all.bat"))
body, _ := ioutil.ReadFile(bat)
if !bytes.Contains(body, []byte("\r\n")) { // Walk the entire Go repository source tree (without GOROOT/pkg),
fmt.Printf("Windows batch file %s does not contain CRLF line termination.\nTry running git checkout src/*.bat to fix this.\n", bat) // skipping directories that start with "." and named "testdata",
os.Exit(1) // and ensure all .bat files found have exact CRLF line endings.
err := filepath.Walk(runtime.GOROOT(), func(path string, fi os.FileInfo, err error) error {
if err != nil {
return err
} }
if fi.IsDir() && (strings.HasPrefix(fi.Name(), ".") || fi.Name() == "testdata") {
return filepath.SkipDir
}
if path == filepath.Join(runtime.GOROOT(), "pkg") {
// GOROOT/pkg is known to contain generated artifacts, not source code.
// Skip it to avoid false positives. (Also see golang.org/issue/37929.)
return filepath.SkipDir
}
if filepath.Ext(fi.Name()) == ".bat" {
enforceBatchStrictCRLF(path)
}
return nil
})
if err != nil {
log.Fatalln(err)
}
}
func enforceBatchStrictCRLF(path string) {
b, err := ioutil.ReadFile(path)
if err != nil {
log.Fatalln(err)
}
cr, lf := bytes.Count(b, []byte{13}), bytes.Count(b, []byte{10})
crlf := bytes.Count(b, []byte{13, 10})
if cr != crlf || lf != crlf {
if rel, err := filepath.Rel(runtime.GOROOT(), path); err == nil {
// Make the test failure more readable by showing a path relative to GOROOT.
path = rel
}
fmt.Printf("Windows batch file %s does not use strict CRLF line termination.\n", path)
fmt.Printf("Please convert it to CRLF before checking it in due to golang.org/issue/37791.\n")
os.Exit(1)
} }
} }