mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.link] all: merge branch 'master' into dev.link
Change-Id: I446db56b20ef2189e23e225a91a17736c1d11e4c
This commit is contained in:
commit
3187b05b87
71 changed files with 1541 additions and 832 deletions
20
.gitattributes
vendored
20
.gitattributes
vendored
|
|
@ -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
|
|
||||||
|
|
|
||||||
1
AUTHORS
1
AUTHORS
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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
132
api/go1.15.txt
Normal 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)
|
||||||
|
|
@ -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)
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
300
doc/go1.15.html
300
doc/go1.15.html
|
|
@ -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 "chunked" 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>
|
||||||
|
|
||||||
|
|
|
||||||
54
src/all.bat
54
src/all.bat
|
|
@ -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%
|
||||||
|
|
|
||||||
|
|
@ -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%
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
1
src/cmd/asm/internal/asm/testdata/arm64enc.s
vendored
1
src/cmd/asm/internal/asm/testdata/arm64enc.s
vendored
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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": "",
|
||||||
|
|
|
||||||
|
|
@ -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, >Jumps)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
b.Fatalf("branch not implemented: %s", b.LongString())
|
b.Fatalf("branch not implemented: %s", b.LongString())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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{
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
59
src/cmd/compile/internal/ssa/tuple.go
Normal file
59
src/cmd/compile/internal/ssa/tuple.go
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
9
src/cmd/dist/test.go
vendored
9
src/cmd/dist/test.go
vendored
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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)))
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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":
|
||||||
|
|
|
||||||
|
|
@ -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" {
|
||||||
|
|
|
||||||
|
|
@ -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=",
|
||||||
|
|
|
||||||
1
src/cmd/go/testdata/script/README
vendored
1
src/cmd/go/testdata/script/README
vendored
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 --
|
||||||
|
|
|
||||||
10
src/cmd/go/testdata/script/mod_get_too_many_redirects.txt
vendored
Normal file
10
src/cmd/go/testdata/script/mod_get_too_many_redirects.txt
vendored
Normal 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
|
||||||
|
|
@ -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") {
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
305
src/make.bat
305
src/make.bat
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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":
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
102
src/race.bat
102
src/race.bat
|
|
@ -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%
|
||||||
|
|
|
||||||
113
src/run.bat
113
src/run.bat
|
|
@ -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
|
|
||||||
|
|
|
||||||
|
|
@ -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))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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() {
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
||||||
12
test/fixedbugs/issue39472.go
Normal file
12
test/fixedbugs/issue39472.go
Normal 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)
|
||||||
|
}
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue