Compare commits

...

20 Commits

Author SHA1 Message Date
Andrew Bonventre
a563954b79 [release-branch.go1.9] go1.9.3
Change-Id: I9347a78c86dcc13cd5f6f000e788934cb1bda491
Reviewed-on: https://go-review.googlesource.com/89015
Run-TryBot: Andrew Bonventre <andybons@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Andrew Bonventre <andybons@golang.org>
2018-01-22 21:38:28 +00:00
Stanislav Afanasev
6ac64a0692 [release-branch.go1.9] doc/contrib.html: fix outdated link
Change-Id: I6d94a14a781a2fbeb90db35ae3490ce2ac5f8ed1
Reviewed-on: https://go-review.googlesource.com/83315
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
(cherry picked from commit 2fb9fe48c6)
Reviewed-on: https://go-review.googlesource.com/89036
Reviewed-by: Andrew Bonventre <andybons@golang.org>
2018-01-22 21:15:00 +00:00
Andrew Bonventre
f94c408f4b [release-branch.go1.9] doc: update 1.9.3 release date
Change-Id: I689ccfb8452a170629425dc97da503b28766c6f9
Reviewed-on: https://go-review.googlesource.com/89035
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
(cherry picked from commit 7abbaddea4819515e1dad817cc1090e18f655b60)
Reviewed-on: https://go-review.googlesource.com/89055
Reviewed-by: Andrew Bonventre <andybons@golang.org>
2018-01-22 21:12:25 +00:00
Andrew Bonventre
6452bf4a05 [release-branch.go1.9] doc: change anchor URLs from golang.org/dl/ to /dl/
When running locally, it will redirect properly to golang.org/dl/
(see https://github.com/golang/tools/blob/master/cmd/godoc/dl.go).

This is to support domains in prod other than golang.org.

Change-Id: I6d3051fcd7e06a86442324a64d781d8ad95c624f
Reviewed-on: https://go-review.googlesource.com/88679
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-on: https://go-review.googlesource.com/88715
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Andrew Bonventre <andybons@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2018-01-22 20:25:15 +00:00
Andrew Bonventre
5380990b84 [release-branch.go1.9] net/http: update bundled http2
Updates http2 to x/net/http2 git rev 44b7c21 for

  http2: Discard data reads on HEAD requests
  https://golang.org/cl/88655

Fixes golang/go#22376

Change-Id: I931d9065d7309bc6d3f978bfe8cc6a9f940ce9e9
Reviewed-on: https://go-review.googlesource.com/88676
Run-TryBot: Andrew Bonventre <andybons@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2018-01-22 20:25:14 +00:00
Keith Randall
edd3537817 [release-branch.go1.9] cmd/compile: fix mapassign_fast* routines for pointer keys
The signature of the mapassign_fast* routines need to distinguish
the pointerness of their key argument.  If the affected routines
suspend part way through, the object pointed to by the key might
get garbage collected because the key is typed as a uint{32,64}.

This is not a problem for mapaccess or mapdelete because the key
in those situations do not live beyond the call involved.  If the
object referenced by the key is garbage collected prematurely, the
code still works fine.  Even if that object is subsequently reallocated,
it can't be written to the map in time to affect the lookup/delete.

Fixes #22781

Change-Id: I0bbbc5e9883d5ce702faf4e655348be1191ee439
Reviewed-on: https://go-review.googlesource.com/79018
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
Reviewed-by: Martin Möhrmann <moehrmann@google.com>
Reviewed-on: https://go-review.googlesource.com/88635
Run-TryBot: Andrew Bonventre <andybons@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
2018-01-22 20:25:13 +00:00
Brad Fitzpatrick
0a72be280e [release-branch.go1.9] net/url: reject invalid userinfo values when parsing URLs
Fixes #23392

Change-Id: I5822b082b14d886b9c3b5ad7beebb2c01a77851b
Reviewed-on: https://go-review.googlesource.com/87038
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-on: https://go-review.googlesource.com/88535
Run-TryBot: Andrew Bonventre <andybons@golang.org>
2018-01-22 20:25:12 +00:00
Ian Lance Taylor
e36f34fa55 [release-branch.go1.9] runtime: call amd64 VDSO entry points on large stack
NOTE: This elides changes to src/runtime/sys_linux_386.s since that
requires another change (golang.org/cl/69390) which we don’t want
to backport.

If the Linux kernel was built with CONFIG_OPTIMIZE_INLINING=n and was
built with hardening options turned on, GCC will insert a stack probe
in the VDSO function that requires a full page of stack space.
The stack probe can corrupt memory if another thread is using it.
Avoid sporadic crashes by calling the VDSO on the g0 or gsignal stack.

While we're at it, align the stack as C code expects. We've been
getting away with a misaligned stack, but it's possible that the VDSO
code will change in the future to break that assumption.

Benchmarks show a 11% hit on time.Now, but it's only 6ns.

name                      old time/op  new time/op  delta
AfterFunc-12              1.66ms ± 0%  1.66ms ± 1%     ~     (p=0.905 n=9+10)
After-12                  1.90ms ± 6%  1.86ms ± 0%   -2.05%  (p=0.012 n=10+8)
Stop-12                    113µs ± 3%   115µs ± 2%   +1.60%  (p=0.017 n=9+10)
SimultaneousAfterFunc-12   145µs ± 1%   144µs ± 0%   -0.68%  (p=0.002 n=10+8)
StartStop-12              39.5µs ± 3%  40.4µs ± 5%   +2.19%  (p=0.023 n=10+10)
Reset-12                  10.2µs ± 0%  10.4µs ± 0%   +2.45%  (p=0.000 n=10+9)
Sleep-12                   190µs ± 1%   190µs ± 1%     ~     (p=0.971 n=10+10)
Ticker-12                 4.68ms ± 2%  4.64ms ± 2%   -0.83%  (p=0.043 n=9+10)
Now-12                    48.4ns ±11%  54.0ns ±11%  +11.42%  (p=0.017 n=10+10)
NowUnixNano-12            48.5ns ±13%  56.9ns ± 8%  +17.30%  (p=0.000 n=10+10)
Format-12                  489ns ±11%   504ns ± 6%     ~     (p=0.289 n=10+10)
FormatNow-12               436ns ±23%   480ns ±13%  +10.25%  (p=0.026 n=9+10)
MarshalJSON-12             656ns ±14%   587ns ±24%     ~     (p=0.063 n=10+10)
MarshalText-12             647ns ± 7%   638ns ± 9%     ~     (p=0.516 n=10+10)
Parse-12                   348ns ± 8%   328ns ± 9%   -5.66%  (p=0.030 n=10+10)
ParseDuration-12           136ns ± 9%   140ns ±11%     ~     (p=0.425 n=10+10)
Hour-12                   14.8ns ± 6%  15.6ns ±11%     ~     (p=0.085 n=10+10)
Second-12                 14.0ns ± 6%  14.3ns ±12%     ~     (p=0.443 n=10+10)
Year-12                   32.4ns ±11%  33.4ns ± 6%     ~     (p=0.492 n=10+10)
Day-12                    41.5ns ± 9%  42.3ns ±12%     ~     (p=0.239 n=10+10)

Fixes #20427

Change-Id: Ia395cbb863215f4499b8e7ef95f4b99f51090911
Reviewed-on: https://go-review.googlesource.com/76990
Reviewed-by: Austin Clements <austin@google.com>
Reviewed-on: https://go-review.googlesource.com/88495
Run-TryBot: Andrew Bonventre <andybons@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2018-01-22 20:25:11 +00:00
Austin Clements
75c7c40d29 [release-branch.go1.9] runtime: use MAP_ANON in sigstack check
MAP_ANON is the deprecated but more portable spelling of
MAP_ANONYMOUS. Use MAP_ANON to un-break the Darwin 10.10 builder.

Updates #22930.

Change-Id: Iedd6232b94390b3b2a7423c45cdcb25c1a5b3323
Reviewed-on: https://go-review.googlesource.com/88316
Run-TryBot: Andrew Bonventre <andybons@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2018-01-22 20:25:10 +00:00
Austin Clements
f4870b7758 [release-branch.go1.9] runtime: restore the Go-allocated signal stack in unminit
Currently, when we minit on a thread that already has an alternate
signal stack (e.g., because the M was an extram being used for a cgo
callback, or to handle a signal on a C thread, or because the
platform's libc always allocates a signal stack like on Android), we
simply drop the Go-allocated gsignal stack on the floor.

This is a problem for Ms on the extram list because those Ms may later
be reused for a different thread that may not have its own alternate
signal stack. On tip, this manifests as a crash in sigaltstack because
we clear the gsignal stack bounds in unminit and later try to use
those cleared bounds when we re-minit that M. On 1.9 and earlier, we
didn't clear the bounds, so this manifests as running more than one
signal handler on the same signal stack, which could lead to arbitrary
memory corruption.

This CL fixes this problem by saving the Go-allocated gsignal stack in
a new field in the m struct when overwriting it with a system-provided
signal stack, and then restoring the original gsignal stack in
unminit.

This CL is designed to be easy to back-port to 1.9. It won't quite
cherry-pick cleanly, but it should be sufficient to simply ignore the
change in mexit (which didn't exist in 1.9).

Now that we always have a place to stash the original signal stack in
the m struct, there are some simplifications we can make to the signal
stack handling. We'll do those in a later CL.

Fixes #22930.

Change-Id: I55c5a6dd9d97532f131146afdef0b216e1433054
Reviewed-on: https://go-review.googlesource.com/88315
Run-TryBot: Andrew Bonventre <andybons@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2018-01-22 20:25:09 +00:00
Keith Randall
2308c9c95e [release-branch.go1.9] cmd/compile: fix decomposition of 1-element arrays
The offending rule could move the load to a different block,
which is always a bad idea.

Fixes #22683

Change-Id: I973c88389b2359f734924d9f45c3fb38e166691d
Reviewed-on: https://go-review.googlesource.com/77331
Run-TryBot: Andrew Bonventre <andybons@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: David Chase <drchase@google.com>
2018-01-22 20:25:08 +00:00
Andrew Bonventre
f8a22093e2 [release-branch.go1.9] doc: document Go 1.9.3
Change-Id: Ic7a5d3118754b34ab0652fcef889259a03baebc3
Reviewed-on: https://go-review.googlesource.com/88536
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-on: https://go-review.googlesource.com/88678
Run-TryBot: Andrew Bonventre <andybons@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Andrew Bonventre <andybons@golang.org>
2018-01-22 20:25:07 +00:00
Keith Randall
a94581d021 [release-branch.go1.9] cmd/compile: fix large load/store offsets on 386
Pointer arithemetic is done mod 2^32 on 386, so we can just
drop the high bits of any large constant offsets.

The bounds check will make sure wraparounds are never observed.

Fixes #21655

Change-Id: I68ae5bbea9f02c73968ea2b21ca017e5ecb89223
Reviewed-on: https://go-review.googlesource.com/82675
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-on: https://go-review.googlesource.com/88324
Run-TryBot: Andrew Bonventre <andybons@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
2018-01-22 20:25:06 +00:00
kirk
f548fb287b [release-branch.go1.9] database/sql: fix transaction leak
When the user context which passed in (*DB)BeginTx is canceled or
timeout, the current implementation could cause db transaction leak
in some extreme scenario.

Goroutine 1:
        Call (*DB) BeginTx begins a transaction with a userContext.
        In (*DB)BeginTx, a new goroutine (*Tx)awaitDone
        which monitor context and rollback tx if needed will be created

Goroutine 2(awaitDone):
        block on tx.ctx.Done()

Goroutine 1:
        Execute some insert or update sqls on the database

Goroutine 1:
        Commit the transaction, (*Tx)Commit set
        the atomic variable tx.done to 1

Goroutine 3(maybe global timer):
        Cancel userContext which be passed in Tx

Goroutine 1:
        (*Tx)Commit checks tx.ctx.Done().
        Due to the context has been canceled, it will return
        context.Canceled or context.DeadlineExceeded error immediately
        and abort the real COMMIT operation of transaction

Goroutine 2:
        Release with tx.ctx.Done() signal, execute (*Tx)rollback.
        However the atomic variable tx.done is 1 currently,
        it will return ErrTxDone error immediately and
        abort the real ROLLBACK operation of transaction

Fixes #22976

Change-Id: I3bc23adf25db823861d91e33d3cca6189fb1171d
Reviewed-on: https://go-review.googlesource.com/81736
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Daniel Theophanes <kardianos@gmail.com>
Reviewed-on: https://go-review.googlesource.com/88323
Run-TryBot: Andrew Bonventre <andybons@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2018-01-22 20:25:05 +00:00
Alberto Donizetti
0b25e97d03 [release-branch.go1.9] math/big: protect against aliasing in nat.divLarge
In nat.divLarge (having signature (z nat).divLarge(u, uIn, v nat)),
we check whether z aliases uIn or v, but aliasing is currently not
checked for the u parameter.

Unfortunately, z and u aliasing each other can in some cases cause
errors in the computation.

The q return parameter (which will hold the result's quotient), is
unconditionally initialized as

    q = z.make(m + 1)

When cap(z) ≥ m+1, z.make() will reuse z's backing array, causing q
and z to share the same backing array. If then z aliases u, setting q
during the quotient computation will then corrupt u, which at that
point already holds computation state.

To fix this, we add an alias(z, u) check at the beginning of the
function, taking care of aliasing the same way we already do for uIn
and v.

Fixes #22830

Change-Id: I3ab81120d5af6db7772a062bb1dfc011de91f7ad
Reviewed-on: https://go-review.googlesource.com/78995
Run-TryBot: Alberto Donizetti <alb.donizetti@gmail.com>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
Reviewed-on: https://go-review.googlesource.com/88322
Run-TryBot: Andrew Bonventre <andybons@golang.org>
2018-01-22 20:25:04 +00:00
Austin Clements
3618ac2ca5 [release-branch.go1.9] runtime: fix gctrace STW CPU time and CPU fraction
The CPU time reported in the gctrace for STW phases is simply
work.stwprocs times the wall-clock duration of these phases. However,
work.stwprocs is set to gcprocs(), which is wrong for multiple
reasons:

1. gcprocs is intended to limit the number of Ms used for mark
   termination based on how well the garbage collector actually
   scales, but the gctrace wants to report how much CPU time is being
   stolen from the application. During STW, that's *all* of the CPU,
   regardless of how many the garbage collector can actually use.

2. gcprocs assumes it's being called during STW, so it limits its
   result to sched.nmidle+1. However, we're not calling it during STW,
   so sched.nmidle is typically quite small, even if GOMAXPROCS is
   quite large.

Fix this by setting work.stwprocs to min(ncpu, GOMAXPROCS). This also
fixes the overall GC CPU fraction, which is based on the computed CPU
times.

Fixes #22725.

Change-Id: I64b5ce87e28dbec6870aa068ce7aecdd28c058d1
Reviewed-on: https://go-review.googlesource.com/77710
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rick Hudson <rlh@golang.org>
Reviewed-on: https://go-review.googlesource.com/88321
Run-TryBot: Andrew Bonventre <andybons@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
2018-01-22 20:25:02 +00:00
Keith Randall
1cca09a8ed [release-branch.go1.9] cmd/compile: fix runtime.KeepAlive
KeepAlive needs to introduce a use of the spill of the
value it is keeping alive.  Without that, we don't guarantee
that the spill dominates the KeepAlive.

This bug was probably introduced with the code to move spills
down to the dominator of the restores, instead of always spilling
just after the value itself (CL 34822).

Fixes #22458.

Change-Id: I94955a21960448ffdacc4df775fe1213967b1d4c
Reviewed-on: https://go-review.googlesource.com/74210
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-on: https://go-review.googlesource.com/88318
Run-TryBot: Andrew Bonventre <andybons@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
2018-01-22 20:25:01 +00:00
Keith Randall
5c08eef870 [release-branch.go1.9] cmd/compile: make sure not to use SP as an index register
...because that's an illegal addressing mode.

I double-checked handling of this code, and 387 is the only
place where this check is missing.

Fixes #22429

Change-Id: I2284fe729ea86251c6af2f04076ddf7a5e66367c
Reviewed-on: https://go-review.googlesource.com/73551
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-on: https://go-review.googlesource.com/88317
Run-TryBot: Andrew Bonventre <andybons@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
2018-01-22 20:24:55 +00:00
Andrew Bonventre
aae9998d41 doc: hide content blocked by GFW when served in CN
Change-Id: Ia3d0fa0517d96f0672d3c5ce7e7b7bb8bd0ce093
Reviewed-on: https://go-review.googlesource.com/60070
Reviewed-by: Chris Broadfoot <cbro@golang.org>
(cherry picked from commit 98603e7af6)
Reviewed-on: https://go-review.googlesource.com/88735
Reviewed-by: Andrew Bonventre <andybons@golang.org>
2018-01-20 05:07:43 +00:00
Russ Cox
5476967b1a [release-branch.go1.9] doc: document Go 1.8.5
Change-Id: I9241e6acb65c337b961eed9cdeaf4c041b6326a3
Reviewed-on: https://go-review.googlesource.com/73390
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: Chris Broadfoot <cbro@golang.org>
Reviewed-on: https://go-review.googlesource.com/73590
2017-10-25 23:37:37 +00:00
39 changed files with 827 additions and 205 deletions

View File

@@ -1 +1 @@
go1.9.2
go1.9.3

View File

@@ -117,6 +117,6 @@ guidelines</a> for information on design, testing, and our code review process.
<p>
Check <a href="//golang.org/issue">the tracker</a> for
open issues that interest you. Those labeled
<a href="https://github.com/golang/go/issues?q=is%3Aopen+is%3Aissue+label%3Ahelpwanted">helpwanted</a>
<a href="https://github.com/golang/go/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22">help wanted</a>
are particularly in need of outside help.
</p>

View File

@@ -49,6 +49,14 @@ See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.9.2">Go
1.9.2 milestone</a> on our issue tracker for details.
</p>
<p>
go1.9.3 (released 2018/01/22) includes fixes to the compiler, runtime,
and the <code>database/sql</code>, <code>math/big</code>, <code>net/http</code>,
and <code>net/url</code> packages.
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.9.3">Go
1.9.3 milestone</a> on our issue tracker for details.
</p>
<h2 id="go1.8">go1.8 (released 2017/02/16)</h2>
<p>
@@ -89,6 +97,16 @@ See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.8.4">Go
1.8.4 milestone</a> on our issue tracker for details.
</p>
<p>
go1.8.5 (released 2017/10/25) includes fixes to the compiler, linker, runtime,
documentation, <code>go</code> command,
and the <code>crypto/x509</code> and <code>net/smtp</code> packages.
It includes a fix to a bug introduced in Go 1.8.4 that broke <code>go</code> <code>get</code>
of non-Git repositories under certain conditions.
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.8.5">Go
1.8.5 milestone</a> on our issue tracker for details.
</p>
<h2 id="go1.7">go1.7 (released 2016/08/15)</h2>
<p>
@@ -262,7 +280,7 @@ See the <a href="https://github.com/golang/go/commits/go1.3.2">change history</a
</p>
<p>
go1.3.3 (released 2014/09/30) includes further bug fixes to cgo, the runtime package, and the nacl port.
go1.3.3 (released 2014/09/30) includes further bug fixes to cgo, the runtime package, and the nacl port.
See the <a href="https://github.com/golang/go/commits/go1.3.3">change history</a> for details.
</p>
@@ -326,7 +344,7 @@ about the future of Go 1.
</p>
<p>
The go1 release corresponds to
The go1 release corresponds to
<code><a href="weekly.html#2012-03-27">weekly.2012-03-27</a></code>.
</p>
@@ -342,7 +360,7 @@ It also includes several minor code and documentation fixes.
<p>
go1.0.2 (released 2012/06/13) was issued to fix two bugs in the implementation
of maps using struct or array keys:
of maps using struct or array keys:
<a href="//golang.org/issue/3695">issue 3695</a> and
<a href="//golang.org/issue/3573">issue 3573</a>.
It also includes many minor code and documentation fixes.

View File

@@ -1,6 +1,7 @@
<!--{
"Title": "Documentation",
"Path": "/doc/"
"Path": "/doc/",
"Template": true
}-->
<p>
@@ -33,14 +34,20 @@ libraries.
<img class="gopher" src="/doc/gopher/doc.png"/>
<h3 id="go_tour"><a href="//tour.golang.org/">A Tour of Go</a></h3>
<h3 id="go_tour">
{{if $.GoogleCN}}
A Tour of Go
{{else}}
<a href="//tour.golang.org/">A Tour of Go</a>
{{end}}
</h3>
<p>
An interactive introduction to Go in three sections.
The first section covers basic syntax and data structures; the second discusses
methods and interfaces; and the third introduces Go's concurrency primitives.
Each section concludes with a few exercises so you can practice what you've
learned. You can <a href="//tour.golang.org/">take the tour online</a> or
install it locally with:
learned. You can {{if not $.GoogleCN}}<a href="//tour.golang.org/">take the tour
online</a> or{{end}} install it locally with:
</p>
<p>
<pre>
@@ -51,10 +58,13 @@ This will place the <code>gotour</code> binary in your workspace's <code>bin</co
<h3 id="code"><a href="code.html">How to write Go code</a></h3>
<p>
Also available as a
<a href="//www.youtube.com/watch?v=XCsL89YtqCs">screencast</a>, this doc
explains how to use the <a href="/cmd/go/">go command</a> to fetch, build, and
install packages, commands, and run tests.
{{if not $.GoogleCN}}
Also available as a <a href="//www.youtube.com/watch?v=XCsL89YtqCs">screencast</a>, this
{{else}}
This
{{end}}
doc explains how to use the <a href="/cmd/go/">go command</a>
to fetch, build, and install packages, commands, and run tests.
</p>
<h3 id="editors"><a href="editors.html">Editor plugins and IDEs</a></h3>
@@ -115,9 +125,11 @@ same variable in a different goroutine.
<h2 id="articles">Articles</h2>
{{if not $.GoogleCN}}
<h3 id="blog"><a href="//blog.golang.org/">The Go Blog</a></h3>
<p>The official blog of the Go project, featuring news and in-depth articles by
the Go team and guests.</p>
{{end}}
<h4>Codewalks</h4>
<p>
@@ -130,6 +142,7 @@ Guided tours of Go programs.
<li><a href="/doc/articles/wiki/">Writing Web Applications</a> - building a simple web application.</li>
</ul>
{{if not $.GoogleCN}}
<h4>Language</h4>
<ul>
<li><a href="/blog/json-rpc-tale-of-interfaces">JSON-RPC: a tale of interfaces</a></li>
@@ -150,17 +163,20 @@ Guided tours of Go programs.
<li><a href="/blog/go-image-package">The Go image package</a> - the fundamentals of the <a href="/pkg/image/">image</a> package.</li>
<li><a href="/blog/go-imagedraw-package">The Go image/draw package</a> - the fundamentals of the <a href="/pkg/image/draw/">image/draw</a> package.</li>
</ul>
{{end}}
<h4>Tools</h4>
<ul>
<li><a href="/doc/articles/go_command.html">About the Go command</a> - why we wrote it, what it is, what it's not, and how to use it.</li>
<li><a href="/blog/c-go-cgo">C? Go? Cgo!</a> - linking against C code with <a href="/cmd/cgo/">cgo</a>.</li>
<li><a href="/doc/gdb">Debugging Go Code with GDB</a></li>
<li><a href="/doc/articles/race_detector.html">Data Race Detector</a> - a manual for the data race detector.</li>
<li><a href="/doc/asm">A Quick Guide to Go's Assembler</a> - an introduction to the assembler used by Go.</li>
{{if not $.GoogleCN}}
<li><a href="/blog/c-go-cgo">C? Go? Cgo!</a> - linking against C code with <a href="/cmd/cgo/">cgo</a>.</li>
<li><a href="/blog/godoc-documenting-go-code">Godoc: documenting Go code</a> - writing good documentation for <a href="/cmd/godoc/">godoc</a>.</li>
<li><a href="/blog/profiling-go-programs">Profiling Go Programs</a></li>
<li><a href="/doc/articles/race_detector.html">Data Race Detector</a> - a manual for the data race detector.</li>
<li><a href="/blog/race-detector">Introducing the Go Race Detector</a> - an introduction to the race detector.</li>
<li><a href="/doc/asm">A Quick Guide to Go's Assembler</a> - an introduction to the assembler used by Go.</li>
{{end}}
</ul>
<h4 id="articles_more">More</h4>
@@ -169,7 +185,7 @@ See the <a href="/wiki/Articles">Articles page</a> at the
<a href="/wiki">Wiki</a> for more Go articles.
</p>
{{if not $.GoogleCN}}
<h2 id="talks">Talks</h2>
<img class="gopher" src="/doc/gopher/talks.png"/>
@@ -200,7 +216,7 @@ This talk expands on the <i>Go Concurrency Patterns</i> talk to dive deeper into
<p>
See the <a href="/talks">Go Talks site</a> and <a href="/wiki/GoTalks">wiki page</a> for more Go talks.
</p>
{{end}}
<h2 id="nonenglish">Non-English Documentation</h2>

View File

@@ -775,7 +775,7 @@ to turn a string into an error. It replaces the old <code>os.NewError</code>.
</p>
{{code "/doc/progs/go1.go" `/ErrSyntax/`}}
<p>
<em>Updating</em>:
Running <code>go</code> <code>fix</code> will update almost all code affected by the change.
@@ -1827,7 +1827,7 @@ for full details.
<tr><td>Uitob(x, b)</td> <td>FormatUint(uint64(x), b)</td></tr>
<tr><td>Uitob64(x, b)</td> <td>FormatUint(x, b)</td></tr>
</table>
<p>
<em>Updating</em>:
Running <code>go</code> <code>fix</code> will update almost all code affected by the change.
@@ -1841,7 +1841,7 @@ a cast that must be added by hand; the <code>go</code> <code>fix</code> tool wil
<h3 id="templates">The template packages</h3>
<p>
The <code>template</code> and <code>exp/template/html</code> packages have moved to
The <code>template</code> and <code>exp/template/html</code> packages have moved to
<a href="/pkg/text/template/"><code>text/template</code></a> and
<a href="/pkg/html/template/"><code>html/template</code></a>.
More significant, the interface to these packages has been simplified.
@@ -2035,4 +2035,4 @@ They are available for many combinations of architecture and operating system
Installation details are described on the
<a href="/doc/install">Getting Started</a> page, while
the distributions themselves are listed on the
<a href="https://golang.org/dl/">downloads page</a>.
<a href="/dl/">downloads page</a>.

View File

@@ -1,6 +1,7 @@
<!--{
"Title": "Help",
"Path": "/help/"
"Path": "/help/",
"Template": true
}-->
<div id="manual-nav"></div>
@@ -9,6 +10,7 @@
<img class="gopher" src="/doc/gopher/help.png"/>
{{if not $.GoogleCN}}
<h3 id="mailinglist"><a href="https://groups.google.com/group/golang-nuts">Go Nuts Mailing List</a></h3>
<p>
Get help from Go users, and share your work on the official mailing list.
@@ -31,10 +33,12 @@ forum for Go programmers.
<h3 id="irc"><a href="irc:irc.freenode.net/go-nuts">Go IRC Channel</a></h3>
<p>Get live support at <b>#go-nuts</b> on <b>irc.freenode.net</b>, the official
Go IRC channel.</p>
{{end}}
<h3 id="faq"><a href="/doc/faq">Frequently Asked Questions (FAQ)</a></h3>
<p>Answers to common questions about Go.</p>
{{if not $.GoogleCN}}
<h2 id="inform">Stay informed</h2>
<h3 id="announce"><a href="https://groups.google.com/group/golang-announce">Go Announcements Mailing List</a></h3>
@@ -64,6 +68,7 @@ for Go news and discussion.
The <a href="https://changelog.com/gotime">Go Time podcast</a> is a panel of Go experts and special guests
discussing the Go programming language, the community, and everything in between.
</p>
{{end}}
<h2 id="community">Community resources</h2>
@@ -73,11 +78,13 @@ Each month in places around the world, groups of Go programmers ("gophers")
meet to talk about Go. Find a chapter near you.
</p>
{{if not $.GoogleCN}}
<h3 id="playground"><a href="/play">Go Playground</a></h3>
<p>A place to write, run, and share Go code.</p>
<h3 id="wiki"><a href="/wiki">Go Wiki</a></h3>
<p>A wiki maintained by the Go community.</p>
{{end}}
<h3 id="conduct"><a href="/conduct">Code of Conduct</a></h3>
<p>

View File

@@ -8,14 +8,14 @@
<h2 id="download">Download the Go distribution</h2>
<p>
<a href="https://golang.org/dl/" id="start" class="download">
<a href="/dl/" id="start" class="download">
<span class="big">Download Go</span>
<span class="desc">Click here to visit the downloads page</span>
</a>
</p>
<p>
<a href="https://golang.org/dl/" target="_blank">Official binary
<a href="/dl/" target="_blank">Official binary
distributions</a> are available for the FreeBSD (release 8-STABLE and above),
Linux, Mac OS X (10.8 and above), and Windows operating systems and
the 32-bit (<code>386</code>) and 64-bit (<code>amd64</code>) x86 processor
@@ -33,7 +33,7 @@ system and architecture, try
<h2 id="requirements">System requirements</h2>
<p>
Go <a href="https://golang.org/dl/">binary distributions</a> are available for these supported operating systems and architectures.
Go <a href="/dl/">binary distributions</a> are available for these supported operating systems and architectures.
Please ensure your system meets these requirements before proceeding.
If your OS or architecture is not on the list, you may be able to
<a href="/doc/install/source">install from source</a> or
@@ -77,7 +77,7 @@ first <a href="#uninstall">remove the existing version</a>.
<h3 id="tarball">Linux, Mac OS X, and FreeBSD tarballs</h3>
<p>
<a href="https://golang.org/dl/">Download the archive</a>
<a href="/dl/">Download the archive</a>
and extract it into <code>/usr/local</code>, creating a Go tree in
<code>/usr/local/go</code>. For example:
</p>
@@ -138,7 +138,7 @@ location.
<h3 id="osx">Mac OS X package installer</h3>
<p>
<a href="https://golang.org/dl/">Download the package file</a>,
<a href="/dl/">Download the package file</a>,
open it, and follow the prompts to install the Go tools.
The package installs the Go distribution to <code>/usr/local/go</code>.
</p>
@@ -167,7 +167,7 @@ MSI installer that configures your installation automatically.
<h4 id="windows_msi">MSI installer</h4>
<p>
Open the <a href="https://golang.org/dl/">MSI file</a>
Open the <a href="/dl/">MSI file</a>
and follow the prompts to install the Go tools.
By default, the installer puts the Go distribution in <code>c:\Go</code>.
</p>
@@ -185,7 +185,7 @@ command prompts for the change to take effect.
<h4 id="windows_zip">Zip archive</h4>
<p>
<a href="https://golang.org/dl/">Download the zip file</a> and extract it into the directory of your choice (we suggest <code>c:\Go</code>).
<a href="/dl/">Download the zip file</a> and extract it into the directory of your choice (we suggest <code>c:\Go</code>).
</p>
<p>

View File

@@ -58,7 +58,7 @@ simple, reliable, and efficient software.
<div id="gopher"></div>
<a href="https://golang.org/dl/" id="start">
<a href="/dl/" id="start">
<span class="big">Download Go</span>
<span class="desc">
Binary distributions available for<br>

View File

@@ -86,7 +86,9 @@ var runtimeDecls = [...]struct {
{"mapaccess2_fat", funcTag, 67},
{"mapassign", funcTag, 62},
{"mapassign_fast32", funcTag, 63},
{"mapassign_fast32ptr", funcTag, 63},
{"mapassign_fast64", funcTag, 63},
{"mapassign_fast64ptr", funcTag, 63},
{"mapassign_faststr", funcTag, 63},
{"mapiterinit", funcTag, 68},
{"mapdelete", funcTag, 68},

View File

@@ -106,7 +106,9 @@ func mapaccess2_faststr(mapType *byte, hmap map[any]any, key any) (val *any, pre
func mapaccess2_fat(mapType *byte, hmap map[any]any, key *any, zero *byte) (val *any, pres bool)
func mapassign(mapType *byte, hmap map[any]any, key *any) (val *any)
func mapassign_fast32(mapType *byte, hmap map[any]any, key any) (val *any)
func mapassign_fast32ptr(mapType *byte, hmap map[any]any, key any) (val *any)
func mapassign_fast64(mapType *byte, hmap map[any]any, key any) (val *any)
func mapassign_fast64ptr(mapType *byte, hmap map[any]any, key any) (val *any)
func mapassign_faststr(mapType *byte, hmap map[any]any, key any) (val *any)
func mapiterinit(mapType *byte, hmap map[any]any, hiter *any)
func mapdelete(mapType *byte, hmap map[any]any, key *any)

View File

@@ -2785,21 +2785,23 @@ func mapfndel(name string, t *types.Type) *Node {
const (
mapslow = iota
mapfast32
mapfast32ptr
mapfast64
mapfast64ptr
mapfaststr
nmapfast
)
type mapnames [nmapfast]string
func mkmapnames(base string) mapnames {
return mapnames{base, base + "_fast32", base + "_fast64", base + "_faststr"}
func mkmapnames(base string, ptr string) mapnames {
return mapnames{base, base + "_fast32", base + "_fast32" + ptr, base + "_fast64", base + "_fast64" + ptr, base + "_faststr"}
}
var mapaccess1 mapnames = mkmapnames("mapaccess1")
var mapaccess2 mapnames = mkmapnames("mapaccess2")
var mapassign mapnames = mkmapnames("mapassign")
var mapdelete mapnames = mkmapnames("mapdelete")
var mapaccess1 mapnames = mkmapnames("mapaccess1", "")
var mapaccess2 mapnames = mkmapnames("mapaccess2", "")
var mapassign mapnames = mkmapnames("mapassign", "ptr")
var mapdelete mapnames = mkmapnames("mapdelete", "")
func mapfast(t *types.Type) int {
// Check ../../runtime/hashmap.go:maxValueSize before changing.
@@ -2808,9 +2810,22 @@ func mapfast(t *types.Type) int {
}
switch algtype(t.Key()) {
case AMEM32:
return mapfast32
if !t.Key().HasPointer() {
return mapfast32
}
if Widthptr == 4 {
return mapfast32ptr
}
Fatalf("small pointer %v", t.Key())
case AMEM64:
return mapfast64
if !t.Key().HasPointer() {
return mapfast64
}
if Widthptr == 8 {
return mapfast64ptr
}
// Two-word object, at least one of which is a pointer.
// Use the slow path.
case ASTRING:
return mapfaststr
}

View File

@@ -798,45 +798,45 @@
(MOVLstoreconstidx1 [c] {sym} ptr (SHLLconst [2] idx) mem) -> (MOVLstoreconstidx4 [c] {sym} ptr idx mem)
// combine ADDL into indexed loads and stores
(MOVBloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVBloadidx1 [c+d] {sym} ptr idx mem)
(MOVWloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVWloadidx1 [c+d] {sym} ptr idx mem)
(MOVWloadidx2 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVWloadidx2 [c+d] {sym} ptr idx mem)
(MOVLloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVLloadidx1 [c+d] {sym} ptr idx mem)
(MOVLloadidx4 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVLloadidx4 [c+d] {sym} ptr idx mem)
(MOVSSloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVSSloadidx1 [c+d] {sym} ptr idx mem)
(MOVSSloadidx4 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVSSloadidx4 [c+d] {sym} ptr idx mem)
(MOVSDloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVSDloadidx1 [c+d] {sym} ptr idx mem)
(MOVSDloadidx8 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVSDloadidx8 [c+d] {sym} ptr idx mem)
(MOVBloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVBloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
(MOVWloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVWloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
(MOVWloadidx2 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVWloadidx2 [int64(int32(c+d))] {sym} ptr idx mem)
(MOVLloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVLloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
(MOVLloadidx4 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVLloadidx4 [int64(int32(c+d))] {sym} ptr idx mem)
(MOVSSloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVSSloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
(MOVSSloadidx4 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVSSloadidx4 [int64(int32(c+d))] {sym} ptr idx mem)
(MOVSDloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVSDloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
(MOVSDloadidx8 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVSDloadidx8 [int64(int32(c+d))] {sym} ptr idx mem)
(MOVBstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVBstoreidx1 [c+d] {sym} ptr idx val mem)
(MOVWstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVWstoreidx1 [c+d] {sym} ptr idx val mem)
(MOVWstoreidx2 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVWstoreidx2 [c+d] {sym} ptr idx val mem)
(MOVLstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVLstoreidx1 [c+d] {sym} ptr idx val mem)
(MOVLstoreidx4 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVLstoreidx4 [c+d] {sym} ptr idx val mem)
(MOVSSstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVSSstoreidx1 [c+d] {sym} ptr idx val mem)
(MOVSSstoreidx4 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVSSstoreidx4 [c+d] {sym} ptr idx val mem)
(MOVSDstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVSDstoreidx1 [c+d] {sym} ptr idx val mem)
(MOVSDstoreidx8 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVSDstoreidx8 [c+d] {sym} ptr idx val mem)
(MOVBstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVBstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
(MOVWstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVWstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
(MOVWstoreidx2 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVWstoreidx2 [int64(int32(c+d))] {sym} ptr idx val mem)
(MOVLstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVLstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
(MOVLstoreidx4 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVLstoreidx4 [int64(int32(c+d))] {sym} ptr idx val mem)
(MOVSSstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVSSstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
(MOVSSstoreidx4 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVSSstoreidx4 [int64(int32(c+d))] {sym} ptr idx val mem)
(MOVSDstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVSDstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
(MOVSDstoreidx8 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVSDstoreidx8 [int64(int32(c+d))] {sym} ptr idx val mem)
(MOVBloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVBloadidx1 [c+d] {sym} ptr idx mem)
(MOVWloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVWloadidx1 [c+d] {sym} ptr idx mem)
(MOVWloadidx2 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVWloadidx2 [c+2*d] {sym} ptr idx mem)
(MOVLloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVLloadidx1 [c+d] {sym} ptr idx mem)
(MOVLloadidx4 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVLloadidx4 [c+4*d] {sym} ptr idx mem)
(MOVSSloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVSSloadidx1 [c+d] {sym} ptr idx mem)
(MOVSSloadidx4 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVSSloadidx4 [c+4*d] {sym} ptr idx mem)
(MOVSDloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVSDloadidx1 [c+d] {sym} ptr idx mem)
(MOVSDloadidx8 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVSDloadidx8 [c+8*d] {sym} ptr idx mem)
(MOVBloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVBloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
(MOVWloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVWloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
(MOVWloadidx2 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVWloadidx2 [int64(int32(c+2*d))] {sym} ptr idx mem)
(MOVLloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVLloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
(MOVLloadidx4 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVLloadidx4 [int64(int32(c+4*d))] {sym} ptr idx mem)
(MOVSSloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVSSloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
(MOVSSloadidx4 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVSSloadidx4 [int64(int32(c+4*d))] {sym} ptr idx mem)
(MOVSDloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVSDloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
(MOVSDloadidx8 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVSDloadidx8 [int64(int32(c+8*d))] {sym} ptr idx mem)
(MOVBstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVBstoreidx1 [c+d] {sym} ptr idx val mem)
(MOVWstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVWstoreidx1 [c+d] {sym} ptr idx val mem)
(MOVWstoreidx2 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVWstoreidx2 [c+2*d] {sym} ptr idx val mem)
(MOVLstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVLstoreidx1 [c+d] {sym} ptr idx val mem)
(MOVLstoreidx4 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVLstoreidx4 [c+4*d] {sym} ptr idx val mem)
(MOVSSstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVSSstoreidx1 [c+d] {sym} ptr idx val mem)
(MOVSSstoreidx4 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVSSstoreidx4 [c+4*d] {sym} ptr idx val mem)
(MOVSDstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVSDstoreidx1 [c+d] {sym} ptr idx val mem)
(MOVSDstoreidx8 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVSDstoreidx8 [c+8*d] {sym} ptr idx val mem)
(MOVBstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVBstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
(MOVWstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVWstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
(MOVWstoreidx2 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVWstoreidx2 [int64(int32(c+2*d))] {sym} ptr idx val mem)
(MOVLstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVLstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
(MOVLstoreidx4 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVLstoreidx4 [int64(int32(c+4*d))] {sym} ptr idx val mem)
(MOVSSstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVSSstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
(MOVSSstoreidx4 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVSSstoreidx4 [int64(int32(c+4*d))] {sym} ptr idx val mem)
(MOVSDstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVSDstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
(MOVSDstoreidx8 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVSDstoreidx8 [int64(int32(c+8*d))] {sym} ptr idx val mem)
(MOVBstoreconstidx1 [x] {sym} (ADDLconst [c] ptr) idx mem) ->
(MOVBstoreconstidx1 [ValAndOff(x).add(c)] {sym} ptr idx mem)

View File

@@ -819,7 +819,7 @@
(Store _ (ArrayMake0) mem) -> mem
(Store dst (ArrayMake1 e) mem) -> (Store {e.Type} dst e mem)
(ArraySelect [0] (Load ptr mem)) -> (Load ptr mem)
(ArraySelect [0] x:(Load ptr mem)) -> @x.Block (Load <v.Type> ptr mem)
// Putting [1]{*byte} and similar into direct interfaces.
(IMake typ (ArrayMake1 val)) -> (IMake typ val)

View File

@@ -1103,12 +1103,15 @@ func (s *regAllocState) regalloc(f *Func) {
if v.Op == OpKeepAlive {
// Make sure the argument to v is still live here.
s.advanceUses(v)
vi := &s.values[v.Args[0].ID]
if vi.spill != nil {
a := v.Args[0]
vi := &s.values[a.ID]
if vi.regs == 0 && !vi.rematerializeable {
// Use the spill location.
v.SetArg(0, vi.spill)
// This forces later liveness analysis to make the
// value live at this point.
v.SetArg(0, s.makeSpill(a, b))
} else {
// No need to keep unspilled values live.
// In-register and rematerializeable values are already live.
// These are typically rematerializeable constants like nil,
// or values of a variable that were modified since the last call.
v.Op = OpCopy

View File

@@ -3148,7 +3148,7 @@ func rewriteValue386_Op386MOVBload_0(v *Value) bool {
func rewriteValue386_Op386MOVBloadidx1_0(v *Value) bool {
// match: (MOVBloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem)
// cond:
// result: (MOVBloadidx1 [c+d] {sym} ptr idx mem)
// result: (MOVBloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -3162,7 +3162,7 @@ func rewriteValue386_Op386MOVBloadidx1_0(v *Value) bool {
idx := v.Args[1]
mem := v.Args[2]
v.reset(Op386MOVBloadidx1)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -3171,7 +3171,7 @@ func rewriteValue386_Op386MOVBloadidx1_0(v *Value) bool {
}
// match: (MOVBloadidx1 [c] {sym} idx (ADDLconst [d] ptr) mem)
// cond:
// result: (MOVBloadidx1 [c+d] {sym} ptr idx mem)
// result: (MOVBloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -3185,7 +3185,7 @@ func rewriteValue386_Op386MOVBloadidx1_0(v *Value) bool {
ptr := v_1.Args[0]
mem := v.Args[2]
v.reset(Op386MOVBloadidx1)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -3194,7 +3194,7 @@ func rewriteValue386_Op386MOVBloadidx1_0(v *Value) bool {
}
// match: (MOVBloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem)
// cond:
// result: (MOVBloadidx1 [c+d] {sym} ptr idx mem)
// result: (MOVBloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -3208,7 +3208,7 @@ func rewriteValue386_Op386MOVBloadidx1_0(v *Value) bool {
idx := v_1.Args[0]
mem := v.Args[2]
v.reset(Op386MOVBloadidx1)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -3217,7 +3217,7 @@ func rewriteValue386_Op386MOVBloadidx1_0(v *Value) bool {
}
// match: (MOVBloadidx1 [c] {sym} (ADDLconst [d] idx) ptr mem)
// cond:
// result: (MOVBloadidx1 [c+d] {sym} ptr idx mem)
// result: (MOVBloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -3231,7 +3231,7 @@ func rewriteValue386_Op386MOVBloadidx1_0(v *Value) bool {
ptr := v.Args[1]
mem := v.Args[2]
v.reset(Op386MOVBloadidx1)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -3747,7 +3747,7 @@ func rewriteValue386_Op386MOVBstoreconstidx1_0(v *Value) bool {
func rewriteValue386_Op386MOVBstoreidx1_0(v *Value) bool {
// match: (MOVBstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem)
// cond:
// result: (MOVBstoreidx1 [c+d] {sym} ptr idx val mem)
// result: (MOVBstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -3762,7 +3762,7 @@ func rewriteValue386_Op386MOVBstoreidx1_0(v *Value) bool {
val := v.Args[2]
mem := v.Args[3]
v.reset(Op386MOVBstoreidx1)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -3772,7 +3772,7 @@ func rewriteValue386_Op386MOVBstoreidx1_0(v *Value) bool {
}
// match: (MOVBstoreidx1 [c] {sym} idx (ADDLconst [d] ptr) val mem)
// cond:
// result: (MOVBstoreidx1 [c+d] {sym} ptr idx val mem)
// result: (MOVBstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -3787,7 +3787,7 @@ func rewriteValue386_Op386MOVBstoreidx1_0(v *Value) bool {
val := v.Args[2]
mem := v.Args[3]
v.reset(Op386MOVBstoreidx1)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -3797,7 +3797,7 @@ func rewriteValue386_Op386MOVBstoreidx1_0(v *Value) bool {
}
// match: (MOVBstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem)
// cond:
// result: (MOVBstoreidx1 [c+d] {sym} ptr idx val mem)
// result: (MOVBstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -3812,7 +3812,7 @@ func rewriteValue386_Op386MOVBstoreidx1_0(v *Value) bool {
val := v.Args[2]
mem := v.Args[3]
v.reset(Op386MOVBstoreidx1)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -3822,7 +3822,7 @@ func rewriteValue386_Op386MOVBstoreidx1_0(v *Value) bool {
}
// match: (MOVBstoreidx1 [c] {sym} (ADDLconst [d] idx) ptr val mem)
// cond:
// result: (MOVBstoreidx1 [c+d] {sym} ptr idx val mem)
// result: (MOVBstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -3837,7 +3837,7 @@ func rewriteValue386_Op386MOVBstoreidx1_0(v *Value) bool {
val := v.Args[2]
mem := v.Args[3]
v.reset(Op386MOVBstoreidx1)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -4486,7 +4486,7 @@ func rewriteValue386_Op386MOVLloadidx1_0(v *Value) bool {
}
// match: (MOVLloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem)
// cond:
// result: (MOVLloadidx1 [c+d] {sym} ptr idx mem)
// result: (MOVLloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -4500,7 +4500,7 @@ func rewriteValue386_Op386MOVLloadidx1_0(v *Value) bool {
idx := v.Args[1]
mem := v.Args[2]
v.reset(Op386MOVLloadidx1)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -4509,7 +4509,7 @@ func rewriteValue386_Op386MOVLloadidx1_0(v *Value) bool {
}
// match: (MOVLloadidx1 [c] {sym} idx (ADDLconst [d] ptr) mem)
// cond:
// result: (MOVLloadidx1 [c+d] {sym} ptr idx mem)
// result: (MOVLloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -4523,7 +4523,7 @@ func rewriteValue386_Op386MOVLloadidx1_0(v *Value) bool {
ptr := v_1.Args[0]
mem := v.Args[2]
v.reset(Op386MOVLloadidx1)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -4532,7 +4532,7 @@ func rewriteValue386_Op386MOVLloadidx1_0(v *Value) bool {
}
// match: (MOVLloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem)
// cond:
// result: (MOVLloadidx1 [c+d] {sym} ptr idx mem)
// result: (MOVLloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -4546,7 +4546,7 @@ func rewriteValue386_Op386MOVLloadidx1_0(v *Value) bool {
idx := v_1.Args[0]
mem := v.Args[2]
v.reset(Op386MOVLloadidx1)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -4555,7 +4555,7 @@ func rewriteValue386_Op386MOVLloadidx1_0(v *Value) bool {
}
// match: (MOVLloadidx1 [c] {sym} (ADDLconst [d] idx) ptr mem)
// cond:
// result: (MOVLloadidx1 [c+d] {sym} ptr idx mem)
// result: (MOVLloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -4569,7 +4569,7 @@ func rewriteValue386_Op386MOVLloadidx1_0(v *Value) bool {
ptr := v.Args[1]
mem := v.Args[2]
v.reset(Op386MOVLloadidx1)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -4581,7 +4581,7 @@ func rewriteValue386_Op386MOVLloadidx1_0(v *Value) bool {
func rewriteValue386_Op386MOVLloadidx4_0(v *Value) bool {
// match: (MOVLloadidx4 [c] {sym} (ADDLconst [d] ptr) idx mem)
// cond:
// result: (MOVLloadidx4 [c+d] {sym} ptr idx mem)
// result: (MOVLloadidx4 [int64(int32(c+d))] {sym} ptr idx mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -4595,7 +4595,7 @@ func rewriteValue386_Op386MOVLloadidx4_0(v *Value) bool {
idx := v.Args[1]
mem := v.Args[2]
v.reset(Op386MOVLloadidx4)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -4604,7 +4604,7 @@ func rewriteValue386_Op386MOVLloadidx4_0(v *Value) bool {
}
// match: (MOVLloadidx4 [c] {sym} ptr (ADDLconst [d] idx) mem)
// cond:
// result: (MOVLloadidx4 [c+4*d] {sym} ptr idx mem)
// result: (MOVLloadidx4 [int64(int32(c+4*d))] {sym} ptr idx mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -4618,7 +4618,7 @@ func rewriteValue386_Op386MOVLloadidx4_0(v *Value) bool {
idx := v_1.Args[0]
mem := v.Args[2]
v.reset(Op386MOVLloadidx4)
v.AuxInt = c + 4*d
v.AuxInt = int64(int32(c + 4*d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -5114,7 +5114,7 @@ func rewriteValue386_Op386MOVLstoreidx1_0(v *Value) bool {
}
// match: (MOVLstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem)
// cond:
// result: (MOVLstoreidx1 [c+d] {sym} ptr idx val mem)
// result: (MOVLstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -5129,7 +5129,7 @@ func rewriteValue386_Op386MOVLstoreidx1_0(v *Value) bool {
val := v.Args[2]
mem := v.Args[3]
v.reset(Op386MOVLstoreidx1)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -5139,7 +5139,7 @@ func rewriteValue386_Op386MOVLstoreidx1_0(v *Value) bool {
}
// match: (MOVLstoreidx1 [c] {sym} idx (ADDLconst [d] ptr) val mem)
// cond:
// result: (MOVLstoreidx1 [c+d] {sym} ptr idx val mem)
// result: (MOVLstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -5154,7 +5154,7 @@ func rewriteValue386_Op386MOVLstoreidx1_0(v *Value) bool {
val := v.Args[2]
mem := v.Args[3]
v.reset(Op386MOVLstoreidx1)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -5164,7 +5164,7 @@ func rewriteValue386_Op386MOVLstoreidx1_0(v *Value) bool {
}
// match: (MOVLstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem)
// cond:
// result: (MOVLstoreidx1 [c+d] {sym} ptr idx val mem)
// result: (MOVLstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -5179,7 +5179,7 @@ func rewriteValue386_Op386MOVLstoreidx1_0(v *Value) bool {
val := v.Args[2]
mem := v.Args[3]
v.reset(Op386MOVLstoreidx1)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -5189,7 +5189,7 @@ func rewriteValue386_Op386MOVLstoreidx1_0(v *Value) bool {
}
// match: (MOVLstoreidx1 [c] {sym} (ADDLconst [d] idx) ptr val mem)
// cond:
// result: (MOVLstoreidx1 [c+d] {sym} ptr idx val mem)
// result: (MOVLstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -5204,7 +5204,7 @@ func rewriteValue386_Op386MOVLstoreidx1_0(v *Value) bool {
val := v.Args[2]
mem := v.Args[3]
v.reset(Op386MOVLstoreidx1)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -5217,7 +5217,7 @@ func rewriteValue386_Op386MOVLstoreidx1_0(v *Value) bool {
func rewriteValue386_Op386MOVLstoreidx4_0(v *Value) bool {
// match: (MOVLstoreidx4 [c] {sym} (ADDLconst [d] ptr) idx val mem)
// cond:
// result: (MOVLstoreidx4 [c+d] {sym} ptr idx val mem)
// result: (MOVLstoreidx4 [int64(int32(c+d))] {sym} ptr idx val mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -5232,7 +5232,7 @@ func rewriteValue386_Op386MOVLstoreidx4_0(v *Value) bool {
val := v.Args[2]
mem := v.Args[3]
v.reset(Op386MOVLstoreidx4)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -5242,7 +5242,7 @@ func rewriteValue386_Op386MOVLstoreidx4_0(v *Value) bool {
}
// match: (MOVLstoreidx4 [c] {sym} ptr (ADDLconst [d] idx) val mem)
// cond:
// result: (MOVLstoreidx4 [c+4*d] {sym} ptr idx val mem)
// result: (MOVLstoreidx4 [int64(int32(c+4*d))] {sym} ptr idx val mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -5257,7 +5257,7 @@ func rewriteValue386_Op386MOVLstoreidx4_0(v *Value) bool {
val := v.Args[2]
mem := v.Args[3]
v.reset(Op386MOVLstoreidx4)
v.AuxInt = c + 4*d
v.AuxInt = int64(int32(c + 4*d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -5431,7 +5431,7 @@ func rewriteValue386_Op386MOVSDload_0(v *Value) bool {
func rewriteValue386_Op386MOVSDloadidx1_0(v *Value) bool {
// match: (MOVSDloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem)
// cond:
// result: (MOVSDloadidx1 [c+d] {sym} ptr idx mem)
// result: (MOVSDloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -5445,7 +5445,7 @@ func rewriteValue386_Op386MOVSDloadidx1_0(v *Value) bool {
idx := v.Args[1]
mem := v.Args[2]
v.reset(Op386MOVSDloadidx1)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -5454,7 +5454,7 @@ func rewriteValue386_Op386MOVSDloadidx1_0(v *Value) bool {
}
// match: (MOVSDloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem)
// cond:
// result: (MOVSDloadidx1 [c+d] {sym} ptr idx mem)
// result: (MOVSDloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -5468,7 +5468,7 @@ func rewriteValue386_Op386MOVSDloadidx1_0(v *Value) bool {
idx := v_1.Args[0]
mem := v.Args[2]
v.reset(Op386MOVSDloadidx1)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -5480,7 +5480,7 @@ func rewriteValue386_Op386MOVSDloadidx1_0(v *Value) bool {
func rewriteValue386_Op386MOVSDloadidx8_0(v *Value) bool {
// match: (MOVSDloadidx8 [c] {sym} (ADDLconst [d] ptr) idx mem)
// cond:
// result: (MOVSDloadidx8 [c+d] {sym} ptr idx mem)
// result: (MOVSDloadidx8 [int64(int32(c+d))] {sym} ptr idx mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -5494,7 +5494,7 @@ func rewriteValue386_Op386MOVSDloadidx8_0(v *Value) bool {
idx := v.Args[1]
mem := v.Args[2]
v.reset(Op386MOVSDloadidx8)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -5503,7 +5503,7 @@ func rewriteValue386_Op386MOVSDloadidx8_0(v *Value) bool {
}
// match: (MOVSDloadidx8 [c] {sym} ptr (ADDLconst [d] idx) mem)
// cond:
// result: (MOVSDloadidx8 [c+8*d] {sym} ptr idx mem)
// result: (MOVSDloadidx8 [int64(int32(c+8*d))] {sym} ptr idx mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -5517,7 +5517,7 @@ func rewriteValue386_Op386MOVSDloadidx8_0(v *Value) bool {
idx := v_1.Args[0]
mem := v.Args[2]
v.reset(Op386MOVSDloadidx8)
v.AuxInt = c + 8*d
v.AuxInt = int64(int32(c + 8*d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -5677,7 +5677,7 @@ func rewriteValue386_Op386MOVSDstore_0(v *Value) bool {
func rewriteValue386_Op386MOVSDstoreidx1_0(v *Value) bool {
// match: (MOVSDstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem)
// cond:
// result: (MOVSDstoreidx1 [c+d] {sym} ptr idx val mem)
// result: (MOVSDstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -5692,7 +5692,7 @@ func rewriteValue386_Op386MOVSDstoreidx1_0(v *Value) bool {
val := v.Args[2]
mem := v.Args[3]
v.reset(Op386MOVSDstoreidx1)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -5702,7 +5702,7 @@ func rewriteValue386_Op386MOVSDstoreidx1_0(v *Value) bool {
}
// match: (MOVSDstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem)
// cond:
// result: (MOVSDstoreidx1 [c+d] {sym} ptr idx val mem)
// result: (MOVSDstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -5717,7 +5717,7 @@ func rewriteValue386_Op386MOVSDstoreidx1_0(v *Value) bool {
val := v.Args[2]
mem := v.Args[3]
v.reset(Op386MOVSDstoreidx1)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -5730,7 +5730,7 @@ func rewriteValue386_Op386MOVSDstoreidx1_0(v *Value) bool {
func rewriteValue386_Op386MOVSDstoreidx8_0(v *Value) bool {
// match: (MOVSDstoreidx8 [c] {sym} (ADDLconst [d] ptr) idx val mem)
// cond:
// result: (MOVSDstoreidx8 [c+d] {sym} ptr idx val mem)
// result: (MOVSDstoreidx8 [int64(int32(c+d))] {sym} ptr idx val mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -5745,7 +5745,7 @@ func rewriteValue386_Op386MOVSDstoreidx8_0(v *Value) bool {
val := v.Args[2]
mem := v.Args[3]
v.reset(Op386MOVSDstoreidx8)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -5755,7 +5755,7 @@ func rewriteValue386_Op386MOVSDstoreidx8_0(v *Value) bool {
}
// match: (MOVSDstoreidx8 [c] {sym} ptr (ADDLconst [d] idx) val mem)
// cond:
// result: (MOVSDstoreidx8 [c+8*d] {sym} ptr idx val mem)
// result: (MOVSDstoreidx8 [int64(int32(c+8*d))] {sym} ptr idx val mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -5770,7 +5770,7 @@ func rewriteValue386_Op386MOVSDstoreidx8_0(v *Value) bool {
val := v.Args[2]
mem := v.Args[3]
v.reset(Op386MOVSDstoreidx8)
v.AuxInt = c + 8*d
v.AuxInt = int64(int32(c + 8*d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -5944,7 +5944,7 @@ func rewriteValue386_Op386MOVSSload_0(v *Value) bool {
func rewriteValue386_Op386MOVSSloadidx1_0(v *Value) bool {
// match: (MOVSSloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem)
// cond:
// result: (MOVSSloadidx1 [c+d] {sym} ptr idx mem)
// result: (MOVSSloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -5958,7 +5958,7 @@ func rewriteValue386_Op386MOVSSloadidx1_0(v *Value) bool {
idx := v.Args[1]
mem := v.Args[2]
v.reset(Op386MOVSSloadidx1)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -5967,7 +5967,7 @@ func rewriteValue386_Op386MOVSSloadidx1_0(v *Value) bool {
}
// match: (MOVSSloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem)
// cond:
// result: (MOVSSloadidx1 [c+d] {sym} ptr idx mem)
// result: (MOVSSloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -5981,7 +5981,7 @@ func rewriteValue386_Op386MOVSSloadidx1_0(v *Value) bool {
idx := v_1.Args[0]
mem := v.Args[2]
v.reset(Op386MOVSSloadidx1)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -5993,7 +5993,7 @@ func rewriteValue386_Op386MOVSSloadidx1_0(v *Value) bool {
func rewriteValue386_Op386MOVSSloadidx4_0(v *Value) bool {
// match: (MOVSSloadidx4 [c] {sym} (ADDLconst [d] ptr) idx mem)
// cond:
// result: (MOVSSloadidx4 [c+d] {sym} ptr idx mem)
// result: (MOVSSloadidx4 [int64(int32(c+d))] {sym} ptr idx mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -6007,7 +6007,7 @@ func rewriteValue386_Op386MOVSSloadidx4_0(v *Value) bool {
idx := v.Args[1]
mem := v.Args[2]
v.reset(Op386MOVSSloadidx4)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -6016,7 +6016,7 @@ func rewriteValue386_Op386MOVSSloadidx4_0(v *Value) bool {
}
// match: (MOVSSloadidx4 [c] {sym} ptr (ADDLconst [d] idx) mem)
// cond:
// result: (MOVSSloadidx4 [c+4*d] {sym} ptr idx mem)
// result: (MOVSSloadidx4 [int64(int32(c+4*d))] {sym} ptr idx mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -6030,7 +6030,7 @@ func rewriteValue386_Op386MOVSSloadidx4_0(v *Value) bool {
idx := v_1.Args[0]
mem := v.Args[2]
v.reset(Op386MOVSSloadidx4)
v.AuxInt = c + 4*d
v.AuxInt = int64(int32(c + 4*d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -6190,7 +6190,7 @@ func rewriteValue386_Op386MOVSSstore_0(v *Value) bool {
func rewriteValue386_Op386MOVSSstoreidx1_0(v *Value) bool {
// match: (MOVSSstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem)
// cond:
// result: (MOVSSstoreidx1 [c+d] {sym} ptr idx val mem)
// result: (MOVSSstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -6205,7 +6205,7 @@ func rewriteValue386_Op386MOVSSstoreidx1_0(v *Value) bool {
val := v.Args[2]
mem := v.Args[3]
v.reset(Op386MOVSSstoreidx1)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -6215,7 +6215,7 @@ func rewriteValue386_Op386MOVSSstoreidx1_0(v *Value) bool {
}
// match: (MOVSSstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem)
// cond:
// result: (MOVSSstoreidx1 [c+d] {sym} ptr idx val mem)
// result: (MOVSSstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -6230,7 +6230,7 @@ func rewriteValue386_Op386MOVSSstoreidx1_0(v *Value) bool {
val := v.Args[2]
mem := v.Args[3]
v.reset(Op386MOVSSstoreidx1)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -6243,7 +6243,7 @@ func rewriteValue386_Op386MOVSSstoreidx1_0(v *Value) bool {
func rewriteValue386_Op386MOVSSstoreidx4_0(v *Value) bool {
// match: (MOVSSstoreidx4 [c] {sym} (ADDLconst [d] ptr) idx val mem)
// cond:
// result: (MOVSSstoreidx4 [c+d] {sym} ptr idx val mem)
// result: (MOVSSstoreidx4 [int64(int32(c+d))] {sym} ptr idx val mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -6258,7 +6258,7 @@ func rewriteValue386_Op386MOVSSstoreidx4_0(v *Value) bool {
val := v.Args[2]
mem := v.Args[3]
v.reset(Op386MOVSSstoreidx4)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -6268,7 +6268,7 @@ func rewriteValue386_Op386MOVSSstoreidx4_0(v *Value) bool {
}
// match: (MOVSSstoreidx4 [c] {sym} ptr (ADDLconst [d] idx) val mem)
// cond:
// result: (MOVSSstoreidx4 [c+4*d] {sym} ptr idx val mem)
// result: (MOVSSstoreidx4 [int64(int32(c+4*d))] {sym} ptr idx val mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -6283,7 +6283,7 @@ func rewriteValue386_Op386MOVSSstoreidx4_0(v *Value) bool {
val := v.Args[2]
mem := v.Args[3]
v.reset(Op386MOVSSstoreidx4)
v.AuxInt = c + 4*d
v.AuxInt = int64(int32(c + 4*d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -6715,7 +6715,7 @@ func rewriteValue386_Op386MOVWloadidx1_0(v *Value) bool {
}
// match: (MOVWloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem)
// cond:
// result: (MOVWloadidx1 [c+d] {sym} ptr idx mem)
// result: (MOVWloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -6729,7 +6729,7 @@ func rewriteValue386_Op386MOVWloadidx1_0(v *Value) bool {
idx := v.Args[1]
mem := v.Args[2]
v.reset(Op386MOVWloadidx1)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -6738,7 +6738,7 @@ func rewriteValue386_Op386MOVWloadidx1_0(v *Value) bool {
}
// match: (MOVWloadidx1 [c] {sym} idx (ADDLconst [d] ptr) mem)
// cond:
// result: (MOVWloadidx1 [c+d] {sym} ptr idx mem)
// result: (MOVWloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -6752,7 +6752,7 @@ func rewriteValue386_Op386MOVWloadidx1_0(v *Value) bool {
ptr := v_1.Args[0]
mem := v.Args[2]
v.reset(Op386MOVWloadidx1)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -6761,7 +6761,7 @@ func rewriteValue386_Op386MOVWloadidx1_0(v *Value) bool {
}
// match: (MOVWloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem)
// cond:
// result: (MOVWloadidx1 [c+d] {sym} ptr idx mem)
// result: (MOVWloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -6775,7 +6775,7 @@ func rewriteValue386_Op386MOVWloadidx1_0(v *Value) bool {
idx := v_1.Args[0]
mem := v.Args[2]
v.reset(Op386MOVWloadidx1)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -6784,7 +6784,7 @@ func rewriteValue386_Op386MOVWloadidx1_0(v *Value) bool {
}
// match: (MOVWloadidx1 [c] {sym} (ADDLconst [d] idx) ptr mem)
// cond:
// result: (MOVWloadidx1 [c+d] {sym} ptr idx mem)
// result: (MOVWloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -6798,7 +6798,7 @@ func rewriteValue386_Op386MOVWloadidx1_0(v *Value) bool {
ptr := v.Args[1]
mem := v.Args[2]
v.reset(Op386MOVWloadidx1)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -6810,7 +6810,7 @@ func rewriteValue386_Op386MOVWloadidx1_0(v *Value) bool {
func rewriteValue386_Op386MOVWloadidx2_0(v *Value) bool {
// match: (MOVWloadidx2 [c] {sym} (ADDLconst [d] ptr) idx mem)
// cond:
// result: (MOVWloadidx2 [c+d] {sym} ptr idx mem)
// result: (MOVWloadidx2 [int64(int32(c+d))] {sym} ptr idx mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -6824,7 +6824,7 @@ func rewriteValue386_Op386MOVWloadidx2_0(v *Value) bool {
idx := v.Args[1]
mem := v.Args[2]
v.reset(Op386MOVWloadidx2)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -6833,7 +6833,7 @@ func rewriteValue386_Op386MOVWloadidx2_0(v *Value) bool {
}
// match: (MOVWloadidx2 [c] {sym} ptr (ADDLconst [d] idx) mem)
// cond:
// result: (MOVWloadidx2 [c+2*d] {sym} ptr idx mem)
// result: (MOVWloadidx2 [int64(int32(c+2*d))] {sym} ptr idx mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -6847,7 +6847,7 @@ func rewriteValue386_Op386MOVWloadidx2_0(v *Value) bool {
idx := v_1.Args[0]
mem := v.Args[2]
v.reset(Op386MOVWloadidx2)
v.AuxInt = c + 2*d
v.AuxInt = int64(int32(c + 2*d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -7590,7 +7590,7 @@ func rewriteValue386_Op386MOVWstoreidx1_0(v *Value) bool {
}
// match: (MOVWstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem)
// cond:
// result: (MOVWstoreidx1 [c+d] {sym} ptr idx val mem)
// result: (MOVWstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -7605,7 +7605,7 @@ func rewriteValue386_Op386MOVWstoreidx1_0(v *Value) bool {
val := v.Args[2]
mem := v.Args[3]
v.reset(Op386MOVWstoreidx1)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -7615,7 +7615,7 @@ func rewriteValue386_Op386MOVWstoreidx1_0(v *Value) bool {
}
// match: (MOVWstoreidx1 [c] {sym} idx (ADDLconst [d] ptr) val mem)
// cond:
// result: (MOVWstoreidx1 [c+d] {sym} ptr idx val mem)
// result: (MOVWstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -7630,7 +7630,7 @@ func rewriteValue386_Op386MOVWstoreidx1_0(v *Value) bool {
val := v.Args[2]
mem := v.Args[3]
v.reset(Op386MOVWstoreidx1)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -7640,7 +7640,7 @@ func rewriteValue386_Op386MOVWstoreidx1_0(v *Value) bool {
}
// match: (MOVWstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem)
// cond:
// result: (MOVWstoreidx1 [c+d] {sym} ptr idx val mem)
// result: (MOVWstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -7655,7 +7655,7 @@ func rewriteValue386_Op386MOVWstoreidx1_0(v *Value) bool {
val := v.Args[2]
mem := v.Args[3]
v.reset(Op386MOVWstoreidx1)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -7665,7 +7665,7 @@ func rewriteValue386_Op386MOVWstoreidx1_0(v *Value) bool {
}
// match: (MOVWstoreidx1 [c] {sym} (ADDLconst [d] idx) ptr val mem)
// cond:
// result: (MOVWstoreidx1 [c+d] {sym} ptr idx val mem)
// result: (MOVWstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -7680,7 +7680,7 @@ func rewriteValue386_Op386MOVWstoreidx1_0(v *Value) bool {
val := v.Args[2]
mem := v.Args[3]
v.reset(Op386MOVWstoreidx1)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -8118,7 +8118,7 @@ func rewriteValue386_Op386MOVWstoreidx2_0(v *Value) bool {
_ = b
// match: (MOVWstoreidx2 [c] {sym} (ADDLconst [d] ptr) idx val mem)
// cond:
// result: (MOVWstoreidx2 [c+d] {sym} ptr idx val mem)
// result: (MOVWstoreidx2 [int64(int32(c+d))] {sym} ptr idx val mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -8133,7 +8133,7 @@ func rewriteValue386_Op386MOVWstoreidx2_0(v *Value) bool {
val := v.Args[2]
mem := v.Args[3]
v.reset(Op386MOVWstoreidx2)
v.AuxInt = c + d
v.AuxInt = int64(int32(c + d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)
@@ -8143,7 +8143,7 @@ func rewriteValue386_Op386MOVWstoreidx2_0(v *Value) bool {
}
// match: (MOVWstoreidx2 [c] {sym} ptr (ADDLconst [d] idx) val mem)
// cond:
// result: (MOVWstoreidx2 [c+2*d] {sym} ptr idx val mem)
// result: (MOVWstoreidx2 [int64(int32(c+2*d))] {sym} ptr idx val mem)
for {
c := v.AuxInt
sym := v.Aux
@@ -8158,7 +8158,7 @@ func rewriteValue386_Op386MOVWstoreidx2_0(v *Value) bool {
val := v.Args[2]
mem := v.Args[3]
v.reset(Op386MOVWstoreidx2)
v.AuxInt = c + 2*d
v.AuxInt = int64(int32(c + 2*d))
v.Aux = sym
v.AddArg(ptr)
v.AddArg(idx)

View File

@@ -5670,6 +5670,8 @@ func rewriteValuegeneric_OpArg_10(v *Value) bool {
return false
}
func rewriteValuegeneric_OpArraySelect_0(v *Value) bool {
b := v.Block
_ = b
// match: (ArraySelect (ArrayMake1 x))
// cond:
// result: x
@@ -5684,23 +5686,26 @@ func rewriteValuegeneric_OpArraySelect_0(v *Value) bool {
v.AddArg(x)
return true
}
// match: (ArraySelect [0] (Load ptr mem))
// match: (ArraySelect [0] x:(Load ptr mem))
// cond:
// result: (Load ptr mem)
// result: @x.Block (Load <v.Type> ptr mem)
for {
if v.AuxInt != 0 {
break
}
v_0 := v.Args[0]
if v_0.Op != OpLoad {
x := v.Args[0]
if x.Op != OpLoad {
break
}
_ = v_0.Args[1]
ptr := v_0.Args[0]
mem := v_0.Args[1]
v.reset(OpLoad)
v.AddArg(ptr)
v.AddArg(mem)
_ = x.Args[1]
ptr := x.Args[0]
mem := x.Args[1]
b = x.Block
v0 := b.NewValue0(v.Pos, OpLoad, v.Type)
v.reset(OpCopy)
v.AddArg(v0)
v0.AddArg(ptr)
v0.AddArg(mem)
return true
}
// match: (ArraySelect [0] x:(IData _))

View File

@@ -46,6 +46,9 @@ func ssaGenValue387(s *gc.SSAGenState, v *ssa.Value) {
case ssa.Op386MOVSSloadidx1, ssa.Op386MOVSDloadidx1:
p.From.Scale = 1
p.From.Index = v.Args[1].Reg()
if p.From.Index == x86.REG_SP {
p.From.Reg, p.From.Index = p.From.Index, p.From.Reg
}
case ssa.Op386MOVSSloadidx4:
p.From.Scale = 4
p.From.Index = v.Args[1].Reg()
@@ -95,6 +98,9 @@ func ssaGenValue387(s *gc.SSAGenState, v *ssa.Value) {
case ssa.Op386MOVSSstoreidx1, ssa.Op386MOVSDstoreidx1:
p.To.Scale = 1
p.To.Index = v.Args[1].Reg()
if p.To.Index == x86.REG_SP {
p.To.Reg, p.To.Index = p.To.Index, p.To.Reg
}
case ssa.Op386MOVSSstoreidx4:
p.To.Scale = 4
p.To.Index = v.Args[1].Reg()

View File

@@ -1769,14 +1769,20 @@ func (tx *Tx) closePrepared() {
// Commit commits the transaction.
func (tx *Tx) Commit() error {
if !atomic.CompareAndSwapInt32(&tx.done, 0, 1) {
return ErrTxDone
}
// Check context first to avoid transaction leak.
// If put it behind tx.done CompareAndSwap statement, we cant't ensure
// the consistency between tx.done and the real COMMIT operation.
select {
default:
case <-tx.ctx.Done():
if atomic.LoadInt32(&tx.done) == 1 {
return ErrTxDone
}
return tx.ctx.Err()
}
if !atomic.CompareAndSwapInt32(&tx.done, 0, 1) {
return ErrTxDone
}
var err error
withLock(tx.dc, func() {
err = tx.txi.Commit()

View File

@@ -1536,6 +1536,26 @@ func TestSqrt(t *testing.T) {
}
}
// We can't test this together with the other Exp tests above because
// it requires a different receiver setup.
func TestIssue22830(t *testing.T) {
one := new(Int).SetInt64(1)
base, _ := new(Int).SetString("84555555300000000000", 10)
mod, _ := new(Int).SetString("66666670001111111111", 10)
want, _ := new(Int).SetString("17888885298888888889", 10)
var tests = []int64{
0, 1, -1,
}
for _, n := range tests {
m := NewInt(n)
if got := m.Exp(base, one, mod); got.Cmp(want) != 0 {
t.Errorf("(%v).Exp(%s, 1, %s) = %s, want %s", n, base, mod, got, want)
}
}
}
func BenchmarkSqrt(b *testing.B) {
n, _ := new(Int).SetString("1"+strings.Repeat("0", 1001), 10)
b.ResetTimer()

View File

@@ -566,8 +566,8 @@ func (z nat) divLarge(u, uIn, v nat) (q, r nat) {
// determine if z can be reused
// TODO(gri) should find a better solution - this if statement
// is very costly (see e.g. time pidigits -s -n 10000)
if alias(z, uIn) || alias(z, v) {
z = nil // z is an alias for uIn or v - cannot reuse
if alias(z, u) || alias(z, uIn) || alias(z, v) {
z = nil // z is an alias for u or uIn or v - cannot reuse
}
q = z.make(m + 1)

View File

@@ -8222,6 +8222,14 @@ func (rl *http2clientConnReadLoop) processData(f *http2DataFrame) error {
return nil
}
if f.Length > 0 {
if cs.req.Method == "HEAD" && len(data) > 0 {
cc.logf("protocol error: received DATA on a HEAD request")
rl.endStreamError(cs, http2StreamError{
StreamID: f.StreamID,
Code: http2ErrCodeProtocol,
})
return nil
}
// Check connection-level flow control.
cc.mu.Lock()
if cs.inflow.available() >= int32(f.Length) {

View File

@@ -545,6 +545,9 @@ func parseAuthority(authority string) (user *Userinfo, host string, err error) {
return nil, host, nil
}
userinfo := authority[:i]
if !validUserinfo(userinfo) {
return nil, "", errors.New("net/url: invalid userinfo")
}
if !strings.Contains(userinfo, ":") {
if userinfo, err = unescape(userinfo, encodeUserPassword); err != nil {
return nil, "", err
@@ -1051,3 +1054,33 @@ func (u *URL) UnmarshalBinary(text []byte) error {
*u = *u1
return nil
}
// validUserinfo reports whether s is a valid userinfo string per RFC 3986
// Section 3.2.1:
// userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
// unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
// sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
// / "*" / "+" / "," / ";" / "="
//
// It doesn't validate pct-encoded. The caller does that via func unescape.
func validUserinfo(s string) bool {
for _, r := range s {
if 'A' <= r && r <= 'Z' {
continue
}
if 'a' <= r && r <= 'z' {
continue
}
if '0' <= r && r <= '9' {
continue
}
switch r {
case '-', '.', '_', ':', '~', '!', '$', '&', '\'',
'(', ')', '*', '+', ',', ';', '=', '%', '@':
continue
default:
return false
}
}
return true
}

View File

@@ -1683,3 +1683,10 @@ func TestGob(t *testing.T) {
t.Errorf("json decoded to: %s\nwant: %s\n", u1, u)
}
}
func TestInvalidUserPassword(t *testing.T) {
_, err := Parse("http://us\ner:pass\nword@foo.com/")
if got, wantsub := fmt.Sprint(err), "net/url: invalid userinfo"; !strings.Contains(got, wantsub) {
t.Errorf("error = %q; want substring %q", got, wantsub)
}
}

View File

@@ -411,3 +411,16 @@ func TestCgoNumGoroutine(t *testing.T) {
t.Errorf("expected %q got %v", want, got)
}
}
func TestSigStackSwapping(t *testing.T) {
switch runtime.GOOS {
case "plan9", "windows":
t.Skip("no sigaltstack on %s", runtime.GOOS)
}
t.Parallel()
got := runTestProg(t, "testprogcgo", "SigStack")
want := "OK\n"
if got != want {
t.Errorf("expected %q got %v", want, got)
}
}

View File

@@ -507,6 +507,94 @@ done:
return val
}
func mapassign_fast32ptr(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer {
if h == nil {
panic(plainError("assignment to entry in nil map"))
}
if raceenabled {
callerpc := getcallerpc(unsafe.Pointer(&t))
racewritepc(unsafe.Pointer(h), callerpc, funcPC(mapassign_fast32))
}
if h.flags&hashWriting != 0 {
throw("concurrent map writes")
}
hash := t.key.alg.hash(noescape(unsafe.Pointer(&key)), uintptr(h.hash0))
// Set hashWriting after calling alg.hash for consistency with mapassign.
h.flags |= hashWriting
if h.buckets == nil {
h.buckets = newarray(t.bucket, 1)
}
again:
bucket := hash & (uintptr(1)<<h.B - 1)
if h.growing() {
growWork(t, h, bucket)
}
b := (*bmap)(unsafe.Pointer(uintptr(h.buckets) + bucket*uintptr(t.bucketsize)))
top := uint8(hash >> (sys.PtrSize*8 - 8))
if top < minTopHash {
top += minTopHash
}
var inserti *uint8
var insertk unsafe.Pointer
var val unsafe.Pointer
for {
for i := uintptr(0); i < bucketCnt; i++ {
if b.tophash[i] != top {
if b.tophash[i] == empty && inserti == nil {
inserti = &b.tophash[i]
insertk = add(unsafe.Pointer(b), dataOffset+i*4)
val = add(unsafe.Pointer(b), dataOffset+bucketCnt*4+i*uintptr(t.valuesize))
}
continue
}
k := *((*unsafe.Pointer)(add(unsafe.Pointer(b), dataOffset+i*4)))
if k != key {
continue
}
val = add(unsafe.Pointer(b), dataOffset+bucketCnt*4+i*uintptr(t.valuesize))
goto done
}
ovf := b.overflow(t)
if ovf == nil {
break
}
b = ovf
}
// Did not find mapping for key. Allocate new cell & add entry.
// If we hit the max load factor or we have too many overflow buckets,
// and we're not already in the middle of growing, start growing.
if !h.growing() && (overLoadFactor(int64(h.count), h.B) || tooManyOverflowBuckets(h.noverflow, h.B)) {
hashGrow(t, h)
goto again // Growing the table invalidates everything, so try again
}
if inserti == nil {
// all current buckets are full, allocate a new one.
newb := h.newoverflow(t, b)
inserti = &newb.tophash[0]
insertk = add(unsafe.Pointer(newb), dataOffset)
val = add(insertk, bucketCnt*4)
}
// store new key/value at insert position
typedmemmove(t.key, insertk, unsafe.Pointer(&key))
*inserti = top
h.count++
done:
if h.flags&hashWriting == 0 {
throw("concurrent map writes")
}
h.flags &^= hashWriting
return val
}
func mapassign_fast64(t *maptype, h *hmap, key uint64) unsafe.Pointer {
if h == nil {
panic(plainError("assignment to entry in nil map"))
@@ -595,6 +683,94 @@ done:
return val
}
func mapassign_fast64ptr(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer {
if h == nil {
panic(plainError("assignment to entry in nil map"))
}
if raceenabled {
callerpc := getcallerpc(unsafe.Pointer(&t))
racewritepc(unsafe.Pointer(h), callerpc, funcPC(mapassign_fast64))
}
if h.flags&hashWriting != 0 {
throw("concurrent map writes")
}
hash := t.key.alg.hash(noescape(unsafe.Pointer(&key)), uintptr(h.hash0))
// Set hashWriting after calling alg.hash for consistency with mapassign.
h.flags |= hashWriting
if h.buckets == nil {
h.buckets = newarray(t.bucket, 1)
}
again:
bucket := hash & (uintptr(1)<<h.B - 1)
if h.growing() {
growWork(t, h, bucket)
}
b := (*bmap)(unsafe.Pointer(uintptr(h.buckets) + bucket*uintptr(t.bucketsize)))
top := uint8(hash >> (sys.PtrSize*8 - 8))
if top < minTopHash {
top += minTopHash
}
var inserti *uint8
var insertk unsafe.Pointer
var val unsafe.Pointer
for {
for i := uintptr(0); i < bucketCnt; i++ {
if b.tophash[i] != top {
if b.tophash[i] == empty && inserti == nil {
inserti = &b.tophash[i]
insertk = add(unsafe.Pointer(b), dataOffset+i*8)
val = add(unsafe.Pointer(b), dataOffset+bucketCnt*8+i*uintptr(t.valuesize))
}
continue
}
k := *((*unsafe.Pointer)(add(unsafe.Pointer(b), dataOffset+i*8)))
if k != key {
continue
}
val = add(unsafe.Pointer(b), dataOffset+bucketCnt*8+i*uintptr(t.valuesize))
goto done
}
ovf := b.overflow(t)
if ovf == nil {
break
}
b = ovf
}
// Did not find mapping for key. Allocate new cell & add entry.
// If we hit the max load factor or we have too many overflow buckets,
// and we're not already in the middle of growing, start growing.
if !h.growing() && (overLoadFactor(int64(h.count), h.B) || tooManyOverflowBuckets(h.noverflow, h.B)) {
hashGrow(t, h)
goto again // Growing the table invalidates everything, so try again
}
if inserti == nil {
// all current buckets are full, allocate a new one.
newb := h.newoverflow(t, b)
inserti = &newb.tophash[0]
insertk = add(unsafe.Pointer(newb), dataOffset)
val = add(insertk, bucketCnt*8)
}
// store new key/value at insert position
typedmemmove(t.key, insertk, unsafe.Pointer(&key))
*inserti = top
h.count++
done:
if h.flags&hashWriting == 0 {
throw("concurrent map writes")
}
h.flags &^= hashWriting
return val
}
func mapassign_faststr(t *maptype, h *hmap, ky string) unsafe.Pointer {
if h == nil {
panic(plainError("assignment to entry in nil map"))

View File

@@ -1251,7 +1251,12 @@ func gcStart(mode gcMode, trigger gcTrigger) {
gcResetMarkState()
work.stwprocs, work.maxprocs = gcprocs(), gomaxprocs
work.stwprocs, work.maxprocs = gomaxprocs, gomaxprocs
if work.stwprocs > ncpu {
// This is used to compute CPU time of the STW phases,
// so it can't be more than ncpu, even if GOMAXPROCS is.
work.stwprocs = ncpu
}
work.heap0 = atomic.Load64(&memstats.heap_live)
work.pauseNS = 0
work.mode = mode

View File

@@ -153,3 +153,6 @@ func setThreadCPUProfiler(hz int32) {
// TODO: Enable profiling interrupts.
getg().m.profilehz = hz
}
// gsignalStack is unused on Plan 9.
type gsignalStack struct{}

View File

@@ -285,6 +285,9 @@ func sigenable(uint32) {}
func sigignore(uint32) {}
func closeonexec(int32) {}
// gsignalStack is unused on nacl.
type gsignalStack struct{}
var writelock uint32 // test-and-set spin lock for write
/*

View File

@@ -386,10 +386,11 @@ type m struct {
divmod uint32 // div/mod denominator for arm - known to liblink
// Fields not known to debuggers.
procid uint64 // for debuggers, but offset not hard-coded
gsignal *g // signal-handling g
sigmask sigset // storage for saved signal mask
tls [6]uintptr // thread-local storage (for x86 extern register)
procid uint64 // for debuggers, but offset not hard-coded
gsignal *g // signal-handling g
goSigStack gsignalStack // Go-allocated signal handling stack
sigmask sigset // storage for saved signal mask
tls [6]uintptr // thread-local storage (for x86 extern register)
mstartfn func()
curg *g // current running goroutine
caughtsig guintptr // goroutine running during fatal signal

View File

@@ -702,7 +702,7 @@ func minitSignalStack() {
signalstack(&_g_.m.gsignal.stack)
_g_.m.newSigstack = true
} else {
setGsignalStack(&st, nil)
setGsignalStack(&st, &_g_.m.goSigStack)
_g_.m.newSigstack = false
}
}
@@ -732,6 +732,14 @@ func unminitSignals() {
if getg().m.newSigstack {
st := stackt{ss_flags: _SS_DISABLE}
sigaltstack(&st, nil)
} else {
// We got the signal stack from someone else. Restore
// the Go-allocated stack in case this M gets reused
// for another thread (e.g., it's an extram). Also, on
// Android, libc allocates a signal stack for all
// threads, so it's important to restore the Go stack
// even on Go-created threads so we can free it.
restoreGsignalStack(&getg().m.goSigStack)
}
}

View File

@@ -223,3 +223,6 @@ func crash() {
// It's okay to leave this empty for now: if crash returns
// the ordinary exit-after-panic happens.
}
// gsignalStack is unused on Windows.
type gsignalStack struct{}

View File

@@ -139,11 +139,31 @@ TEXT runtime·mincore(SB),NOSPLIT,$0-28
RET
// func walltime() (sec int64, nsec int32)
TEXT runtime·walltime(SB),NOSPLIT,$16
// Be careful. We're calling a function with gcc calling convention here.
// We're guaranteed 128 bytes on entry, and we've taken 16, and the
// call uses another 8.
// That leaves 104 for the gettime code to use. Hope that's enough!
TEXT runtime·walltime(SB),NOSPLIT,$0-12
// We don't know how much stack space the VDSO code will need,
// so switch to g0.
// In particular, a kernel configured with CONFIG_OPTIMIZE_INLINING=n
// and hardening can use a full page of stack space in gettime_sym
// due to stack probes inserted to avoid stack/heap collisions.
// See issue #20427.
MOVQ SP, BP // Save old SP; BP unchanged by C code.
get_tls(CX)
MOVQ g(CX), AX
MOVQ g_m(AX), CX
MOVQ m_curg(CX), DX
CMPQ AX, DX // Only switch if on curg.
JNE noswitch
MOVQ m_g0(CX), DX
MOVQ (g_sched+gobuf_sp)(DX), SP // Set SP to g0 stack
noswitch:
SUBQ $16, SP // Space for results
ANDQ $~15, SP // Align for C code
MOVQ runtime·__vdso_clock_gettime_sym(SB), AX
CMPQ AX, $0
JEQ fallback
@@ -152,6 +172,7 @@ TEXT runtime·walltime(SB),NOSPLIT,$16
CALL AX
MOVQ 0(SP), AX // sec
MOVQ 8(SP), DX // nsec
MOVQ BP, SP // Restore real SP
MOVQ AX, sec+0(FP)
MOVL DX, nsec+8(FP)
RET
@@ -163,13 +184,31 @@ fallback:
MOVQ 0(SP), AX // sec
MOVL 8(SP), DX // usec
IMULQ $1000, DX
MOVQ BP, SP // Restore real SP
MOVQ AX, sec+0(FP)
MOVL DX, nsec+8(FP)
RET
TEXT runtime·nanotime(SB),NOSPLIT,$16
// Duplicate time.now here to avoid using up precious stack space.
// See comment above in time.now.
TEXT runtime·nanotime(SB),NOSPLIT,$0-8
// Switch to g0 stack. See comment above in runtime·walltime.
MOVQ SP, BP // Save old SP; BX unchanged by C code.
get_tls(CX)
MOVQ g(CX), AX
MOVQ g_m(AX), CX
MOVQ m_curg(CX), DX
CMPQ AX, DX // Only switch if on curg.
JNE noswitch
MOVQ m_g0(CX), DX
MOVQ (g_sched+gobuf_sp)(DX), SP // Set SP to g0 stack
noswitch:
SUBQ $16, SP // Space for results
ANDQ $~15, SP // Align for C code
MOVQ runtime·__vdso_clock_gettime_sym(SB), AX
CMPQ AX, $0
JEQ fallback
@@ -178,6 +217,7 @@ TEXT runtime·nanotime(SB),NOSPLIT,$16
CALL AX
MOVQ 0(SP), AX // sec
MOVQ 8(SP), DX // nsec
MOVQ BP, SP // Restore real SP
// sec is in AX, nsec in DX
// return nsec in AX
IMULQ $1000000000, AX
@@ -191,6 +231,7 @@ fallback:
CALL AX
MOVQ 0(SP), AX // sec
MOVL 8(SP), DX // usec
MOVQ BP, SP // Restore real SP
IMULQ $1000, DX
// sec is in AX, nsec in DX
// return nsec in AX

View File

@@ -0,0 +1,95 @@
// Copyright 2017 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.
// +build !plan9,!windows
// Test handling of Go-allocated signal stacks when calling from
// C-created threads with and without signal stacks. (See issue
// #22930.)
package main
/*
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#ifndef MAP_STACK
#define MAP_STACK 0
#endif
extern void SigStackCallback();
static void* WithSigStack(void* arg __attribute__((unused))) {
// Set up an alternate system stack.
void* base = mmap(0, SIGSTKSZ, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON|MAP_STACK, -1, 0);
if (base == MAP_FAILED) {
perror("mmap failed");
abort();
}
stack_t st = {}, ost = {};
st.ss_sp = (char*)base;
st.ss_flags = 0;
st.ss_size = SIGSTKSZ;
if (sigaltstack(&st, &ost) < 0) {
perror("sigaltstack failed");
abort();
}
// Call Go.
SigStackCallback();
// Disable signal stack and protect it so we can detect reuse.
if (ost.ss_flags & SS_DISABLE) {
// Darwin libsystem has a bug where it checks ss_size
// even if SS_DISABLE is set. (The kernel gets it right.)
ost.ss_size = SIGSTKSZ;
}
if (sigaltstack(&ost, NULL) < 0) {
perror("sigaltstack restore failed");
abort();
}
mprotect(base, SIGSTKSZ, PROT_NONE);
return NULL;
}
static void* WithoutSigStack(void* arg __attribute__((unused))) {
SigStackCallback();
return NULL;
}
static void DoThread(int sigstack) {
pthread_t tid;
if (sigstack) {
pthread_create(&tid, NULL, WithSigStack, NULL);
} else {
pthread_create(&tid, NULL, WithoutSigStack, NULL);
}
pthread_join(tid, NULL);
}
*/
import "C"
func init() {
register("SigStack", SigStack)
}
func SigStack() {
C.DoThread(0)
C.DoThread(1)
C.DoThread(0)
C.DoThread(1)
println("OK")
}
var BadPtr *int
//export SigStackCallback
func SigStackCallback() {
// Cause the Go signal handler to run.
defer func() { recover() }()
*BadPtr = 42
}

View File

@@ -38,3 +38,25 @@ func f6(a []float32, i int64) float32 {
// like 0x80000000 and silently using them as
// signed 32 bit offsets.)
// f4 was ok, but testing it can't hurt.
func f7(ss []*string, i int) string {
const offset = 3 << 29 // 3<<29 * 4 = 3<<31 = 1<<31 mod 1<<32.
if i > offset {
return *ss[i-offset]
}
return ""
}
func f8(ss []*string, i int) string {
const offset = 3<<29 + 10
if i > offset {
return *ss[i-offset]
}
return ""
}
func f9(ss []*string, i int) string {
const offset = 3<<29 - 10
if i > offset {
return *ss[i-offset]
}
return ""
}

View File

@@ -0,0 +1,18 @@
// compile
// Copyright 2017 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.
// Make sure SSA->assembly pass can handle SP as an index register.
package p
type T struct {
a,b,c,d float32
}
func f(a *[8]T, i,j,k int) float32 {
b := *a
return b[i].a + b[j].b + b[k].c
}

View File

@@ -0,0 +1,26 @@
// compile
// Copyright 2017 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.
// Make sure KeepAlive introduces a use of the spilled variable.
package main
import "runtime"
type node struct {
next *node
}
var x bool
func main() {
var head *node
for x {
head = &node{head}
}
runtime.KeepAlive(head)
}

View File

@@ -0,0 +1,30 @@
// cmpout
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"fmt"
)
type foo struct {
bar [1]*int
}
func main() {
ch := make(chan foo, 2)
var a int
var b [1]*int
b[0] = &a
ch <- foo{bar: b}
close(ch)
for v := range ch {
for i := 0; i < 1; i++ {
fmt.Println(v.bar[0] != nil)
}
}
}

View File

@@ -0,0 +1 @@
true

View File

@@ -0,0 +1,29 @@
// run
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import "runtime/debug"
type T struct {
// >= 16 bytes to avoid tiny alloc.
a, b int
}
func main() {
debug.SetGCPercent(1)
for i := 0; i < 100000; i++ {
m := make(map[*T]struct{}, 0)
for j := 0; j < 20; j++ {
// During the call to mapassign_fast64, the key argument
// was incorrectly treated as a uint64. If the stack was
// scanned during that call, the only pointer to k was
// missed, leading to *k being collected prematurely.
k := new(T)
m[k] = struct{}{}
}
}
}