cmd/compile: add sources for inlined functions to ssa.html
This CL adds the source code of all inlined functions
into the function specified in $GOSSAFUNC.
The code is appended to the sources column of ssa.html.
ssaDumpInlined is populated with references to inlined functions.
Then it is used for dumping the sources in buildssa.
The source columns contains code in following order:
target function, inlined functions sorted by filename, lineno.
This CL exports the Func.Endlineno value for inlineable functions.
It is needed to grab the source code of an imported function
inlined into the function specified in $GOSSAFUNC.
Since we print almost everything to ssa.html in the GOSSAFUNC mode,
there is a need to stop spamming stdout when user just wants to see
ssa.html.
This changes cleans output of the GOSSAFUNC debug mode.
To enable the dump of the debug data to stdout, one must
put suffix + after the function name like that:
GOSSAFUNC=Foo+
Otherwise gc will not print the IR and ASM to stdout after each phase.
AST IR is still sent to stdout because it is not included
into ssa.html. It will be fixed in a separate change.
The change adds printing out the full path to the ssa.html file.
Oryan Moshe [Fri, 3 Aug 2018 11:52:39 +0000 (14:52 +0300)]
cmd/cgo: pass explicit -O0 to the compiler
The current implementation removes all of the optimization flags from
the compiler.
Added the -O0 optimization flag after the removal loop, so go can
compile cgo on every OS consistently.
Fixes #26487
Change-Id: Ia98bca90def186dfe10f50b1787c2f40d85533da
Reviewed-on: https://go-review.googlesource.com/127755
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
Brian Kessler [Tue, 19 Sep 2017 05:02:55 +0000 (22:02 -0700)]
math/big: streamline divLarge initialization
The divLarge code contained "todo"s about avoiding alias
and clear calls in the initialization of variables. By
rearranging the order of initialization and always using
an auxiliary variable for the shifted divisor, all of these
calls can be safely avoided. On average, normalizing
the divisor (shift>0) is required 31/32 or 63/64 of the
time. If one always performs the shift into an auxiliary
variable first, this avoids the need to check for aliasing of
vIn in the output variables u and z. The remainder u is
initialized via a left shift of uIn and thus needs no
alias check against uIn. Since uIn and vIn were both used,
z needs no alias checks except against u which is used for
storage of the remainder. This change has a minimal impact
on performance (see below), but cleans up the initialization
code and eliminates the "todo"s.
Emmanuel T Odeke [Wed, 22 Aug 2018 05:58:08 +0000 (22:58 -0700)]
internal/poll: use F_FULLFSYNC fcntl for FD.Fsync on OS X
As reported in #26650 and also cautioned on the man page
for fsync on OS X, fsync doesn't properly flush content
to permanent storage, and might cause corruption of data if
the OS crashes or if the drive loses power. Thus it is recommended
to use the F_FULLFSYNC fcntl, which flushes all buffered data to
permanent storage and is important for applications such as
databases that require a strict ordering of writes.
Also added a note in syscall_darwin.go that syscall.Fsync is
not invoked for os.File.Sync.
Fixes #26650.
Change-Id: Idecd9adbbdd640b9c5b02e73b60ed254c98b48b6
Reviewed-on: https://go-review.googlesource.com/130676
Run-TryBot: Emmanuel Odeke <emm.odeke@gmail.com>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
If two goroutines are racing on a map, one of them will exit
cleanly, clearing the hashWriting bit, and the other will
likely notice and panic. If we use XOR instead of OR to
set the bit in the first place, even numbers of racers will
hopefully all see the bit cleared and panic simultaneously,
giving the full set of available stacks. If a third racer
sneaks in, we are no worse than the current code, and
the generated code should be no more expensive.
In practice, this catches most racing goroutines even in
very tight races. See the demonstration program posted
on https://github.com/golang/go/issues/26703 for an example.
Martin Möhrmann [Sun, 19 Aug 2018 05:50:39 +0000 (07:50 +0200)]
fmt: print values for map keys with non-reflexive equality
Previously fmt would first obtain a list of map keys
and then look up the value for each key. Since NaNs can
be map keys but cannot be fetched directly, the lookup would
fail and return a zero reflect.Value, which formats as <nil>.
golang.org/cl/33572 added a map iterator to the reflect package
that is used in this CL to retrieve the key and value from
the map and prints the correct value even for keys that are not
equal to themselves.
Fixes #14427
Change-Id: I9e1522959760b3de8b7ecf7a6e67cd603339632a
Reviewed-on: https://go-review.googlesource.com/129777 Reviewed-by: Alan Donovan <adonovan@google.com>
cmd/compile: cache the value of environment variable GOSSAFUNC
Store the value of GOSSAFUNC in a global variable to avoid
multiple calls to os.Getenv from gc.buildssa and gc.mkinlcall1.
The latter is implemented in the CL 126606.
Brian Kessler [Tue, 8 May 2018 06:07:13 +0000 (00:07 -0600)]
math/big: optimize multiplication by 2 and 1/2 in float Sqrt
The Sqrt code previously used explicit constants for 2 and 1/2. This change
replaces multiplication by these constants with increment and decrement of
the floating point exponent directly. This improves performance by ~7-10%
for small inputs and minimal improvement for large inputs.
Martin Möhrmann [Wed, 22 Aug 2018 20:34:39 +0000 (22:34 +0200)]
runtime: skip TestGcSys on Windows
This is causing failures on TryBots and BuildBots:
--- FAIL: TestGcSys (0.06s)
gc_test.go:27: expected "OK\n", but got "using too much memory: 39882752 bytes\n"
FAIL
Yury Smolsky [Thu, 14 Jun 2018 15:20:03 +0000 (18:20 +0300)]
cmd/compile: display Go code for a function in ssa.html
This CL adds the "sources" column at the beginning of SSA table.
This column displays the source code for the function being passed
in the GOSSAFUNC env variable.
Also UI was extended so that clicking on particular line will
highlight all places this line is referenced.
JS code was cleaned and formatted.
This CL does not handle inlined functions. See issue 25904.
Ian Lance Taylor [Sat, 7 Jul 2018 05:57:35 +0000 (22:57 -0700)]
runtime: make TestGcSys actually test something
The workthegc function was being inlined, and the slice did not
escape, so there was no memory allocation. Use a sink variable to
force memory allocation, at least for now.
Fixes #23343
Change-Id: I02f4618e343c8b6cb552cb4e9f272e112785f7cf
Reviewed-on: https://go-review.googlesource.com/122576
Run-TryBot: Ian Lance Taylor <iant@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Daniel Martí [Fri, 18 May 2018 17:31:05 +0000 (18:31 +0100)]
encoding/base64: slight decoding speed-up
First, use a dummy slice access on decode64 and decode32 to ensure that
there is a single bounds check for src.
Second, move the PutUint64/PutUint32 calls out of these functions,
meaning that they are simpler and smaller. This may also open the door
to inlineability in the future, but for now, they both go past the
budget.
While at it, get rid of the ilen and olen variables, which have no
impact whatsoever on performance. At least, not measurable by any of the
benchmarks.
Change-Id: I0dfbdafa2a41dc4c582f63aef94b90b8e473731c
Reviewed-on: https://go-review.googlesource.com/113776 Reviewed-by: Ian Lance Taylor <iant@golang.org>
Ian Lance Taylor [Tue, 21 Aug 2018 14:58:10 +0000 (07:58 -0700)]
regexp/syntax: don't do both linear and binary sesarch in MatchRunePos
MatchRunePos is a significant element of regexp performance, so some
attention to optimization is appropriate. Before this CL, a
non-matching rune would do both a linear search in the first four
entries, and a binary search over all the entries. Change the code to
optimize for the common case of two runes, to only do a linear search
when there are up to four entries, and to only do a binary search when
there are more than four entries.
andrius4669 [Thu, 17 May 2018 14:43:30 +0000 (14:43 +0000)]
bufio: avoid rescanning buffer multiple times in ReadSlice
When existing data in buffer does not have delimiter,
and new data is added with b.fill(), continue search from
previous point instead of starting from beginning.
Daniel Martí [Sat, 7 Jul 2018 18:07:14 +0000 (19:07 +0100)]
encoding/json: simplify some pieces of the encoder
Some WriteByte('\\') calls can be deduplicated.
fillField is used in two occasions, but it is unnecessary when adding
fields to the "next" stack, as those aren't used for the final encoding.
Inline the func with its only remaining call.
Finally, unindent a default-if block.
The performance of the encoder is unaffected:
name old time/op new time/op delta
CodeEncoder-4 6.65ms ± 1% 6.65ms ± 0% ~ (p=0.662 n=6+5)
Daniel Martí [Sun, 22 Jul 2018 11:36:15 +0000 (12:36 +0100)]
encoding/json: inline fieldByIndex
This function was only used in a single place - in the field encoding
loop within the struct encoder.
Inlining the function call manually lets us get rid of the call
overhead. But most importantly, it lets us simplify the logic afterward.
We no longer need to use reflect.Value{} and !fv.IsValid(), as we can
skip the field immediately.
The two factors combined (mostly just the latter) give a moderate speed
improvement to this hot loop.
name old time/op new time/op delta
CodeEncoder-4 6.01ms ± 1% 5.91ms ± 1% -1.66% (p=0.002 n=6+6)
name old speed new speed delta
CodeEncoder-4 323MB/s ± 1% 328MB/s ± 1% +1.69% (p=0.002 n=6+6)
Daniel Martí [Sun, 22 Jul 2018 11:26:38 +0000 (12:26 +0100)]
encoding/json: simplify the structEncoder type
structEncoder had two slices - the list of fields, and a list containing
the encoder for each field. structEncoder.encode then looped over the
fields, and indexed into the second slice to grab the field encoder.
However, this makes it very hard for the compiler to be able to prove
that the two slices always have the same length, and that the index
expression doesn't need a bounds check.
Merge the two slices into one to completely remove the need for bounds
checks in the hot loop.
While at it, don't copy the field elements when ranging, which greatly
speeds up the hot loop in structEncoder.
name old time/op new time/op delta
CodeEncoder-4 6.18ms ± 0% 5.56ms ± 0% -10.08% (p=0.002 n=6+6)
name old speed new speed delta
CodeEncoder-4 314MB/s ± 0% 349MB/s ± 0% +11.21% (p=0.002 n=6+6)
name old alloc/op new alloc/op delta
CodeEncoder-4 93.2kB ± 0% 62.1kB ± 0% -33.33% (p=0.002 n=6+6)
Filippo Valsorda [Tue, 21 Aug 2018 20:50:04 +0000 (14:50 -0600)]
crypto/tls: make ConnectionState.ExportKeyingMaterial a method
The unexported field is hidden from reflect based marshalers, which
would break otherwise. Also, make it return an error, as there are
multiple reasons it might fail.
Alberto Donizetti [Sun, 24 Jun 2018 11:42:59 +0000 (13:42 +0200)]
time: accept anything between -23 and 23 as offset namezone name
time.Parse currently rejects numeric timezones names with UTC offsets
bigger than +12, but this is incorrect: there's a +13 timezone and a
+14 timezone:
$ zdump Pacific/Kiritimati
Pacific/Kiritimati Mon Jun 25 02:15:03 2018 +14
For convenience, this cl changes the ranges of accepted offsets from
-14..+12 to -23..+23 (zero still excluded), i.e. every possible offset
that makes sense. We don't validate three-letter abbreviations for the
timezones names, so there's no need to be too strict on numeric names.
This change also fixes a bug in the parseTimeZone, that is currently
unconditionally returning true (i.e. valid timezone), without checking
the value returned by parseSignedOffset.
This fixes 5 of 17 time.Parse() failures listed in Issue #26032.
Updates #26032
Change-Id: I2f08ca9aa41ea4c6149ed35ed2dd8f23eeb42bff
Reviewed-on: https://go-review.googlesource.com/120558 Reviewed-by: Rob Pike <r@golang.org>
Jordan Rhee [Tue, 24 Jul 2018 22:13:41 +0000 (15:13 -0700)]
cmd/link: support windows/arm
Enable the Go linker to generate executables for windows/arm.
Generates PE relocation tables, which are used by Windows to
dynamically relocate the Go binary in memory. Windows on ARM
requires all modules to be relocatable, unlike x86/amd64 which are
permitted to have fixed base addresses.
Updates #26148
Change-Id: Ie63964ff52c2377e121b2885e9d05ec3ed8dc1cd
Reviewed-on: https://go-review.googlesource.com/125648
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Ilya Tocar [Tue, 21 Aug 2018 19:50:48 +0000 (14:50 -0500)]
net: use internal/bytealg insetad of linkname tricks
We are currently using go:linkname for some algorithms from
strings/bytes packages, to avoid importing strings/bytes.
But strings/bytes are just wrappers around internal/bytealg, so
we should use internal/bytealg directly.
Ilya Tocar [Tue, 21 Aug 2018 19:40:01 +0000 (14:40 -0500)]
time: optimize big4
Use the same load order in big4 as in encoding/binary.BigEndian.
This order is recognized by the compiler and converted into single load.
This isn't in the hot path, but doesn't hurt readability, so lets do this.
Andreas Auernhammer [Tue, 21 Aug 2018 14:12:36 +0000 (16:12 +0200)]
crypto/rc4: remove assembler implementations
This CL removes the RC4 assembler implementations.
RC4 is broken and should not be used for encryption
anymore. Therefore it's not worth maintaining
platform-specific assembler implementations.
The native Go implementation may be slower
or faster depending on the CPU:
vendor_id : GenuineIntel
cpu family : 6
model : 142
model name : Intel(R) Core(TM) i5-7Y54 CPU @ 1.20GHz
stepping : 9
microcode : 0x84
cpu MHz : 800.036
cache size : 4096 KB
vendor_id : GenuineIntel
cpu family : 6
model : 63
model name : Intel(R) Xeon(R) CPU @ 2.30GHz
stepping : 0
microcode : 0x1
cpu MHz : 2300.000
cache size : 46080 KB
Daniel Martí [Sun, 8 Jul 2018 15:14:35 +0000 (16:14 +0100)]
encoding/json: various minor decoder speed-ups
Reuse v.Type() and cachedTypeFields(t) when decoding maps and structs.
Always use the same data slices when in hot loops, to ensure that the
compiler generates good code. "for i < len(data) { use(d.data[i]) }"
makes it harder for the compiler.
Finally, do other minor clean-ups, such as deduplicating switch cases,
and using a switch instead of three chained ifs.
The decoder sees a noticeable speed-up, in particular when decoding
structs.
name old time/op new time/op delta
CodeDecoder-4 29.8ms ± 1% 27.5ms ± 0% -7.83% (p=0.002 n=6+6)
name old speed new speed delta
CodeDecoder-4 65.0MB/s ± 1% 70.6MB/s ± 0% +8.49% (p=0.002 n=6+6)
Michael Munday [Thu, 31 May 2018 12:06:27 +0000 (13:06 +0100)]
crypto/{aes,cipher,rand}: use binary.{Big,Little}Endian methods
Use the binary.{Big,Little}Endian integer encoding methods rather
than unsafe or local implementations. These methods are tested to
ensure they inline correctly and don't add unnecessary bounds checks,
so it seems better to use them wherever possible.
This introduces a dependency on encoding/binary to crypto/cipher. I
think this is OK because other "L3" packages already import
encoding/binary.
Alberto Donizetti [Tue, 21 Aug 2018 12:02:56 +0000 (14:02 +0200)]
cmd/gofmt: skip gofmt idempotency check on known issue
gofmt's TestAll runs gofmt on all the go files in the tree and checks,
among other things, that gofmt is idempotent (i.e. that a second
invocation does not change the input again).
There's a known bug of gofmt not being idempotent (Issue #24472), and
unfortunately the fixedbugs/issue22662.go file triggers it. We can't
just gofmt the file, because it tests the effect of various line
directives inside weirdly-placed comments, and gofmt moves those
comments, making the test useless.
Instead, just skip the idempotency check when gofmt-ing the
problematic file.
This fixes go test on the cmd/gofmt package, and a failure seen on the
longtest builder.
Updates #24472
Change-Id: Ib06300977cd8fce6c609e688b222e9b2186f5aa7
Reviewed-on: https://go-review.googlesource.com/130377 Reviewed-by: Daniel Martí <mvdan@mvdan.cc> Reviewed-by: Robert Griesemer <gri@golang.org>
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Ian Lance Taylor [Thu, 9 Aug 2018 00:26:23 +0000 (17:26 -0700)]
runtime: don't use linkname to refer to internal/cpu
The runtime package already imports the internal/cpu package, so there
is no reason for it to use go:linkname comments to refer to
internal/cpu functions and variables. Since internal/cpu is internal,
we can just export those names. Removing the obscurity of go:linkname
outweighs the minor additional complexity added to the internal/cpu API.
Change-Id: Id89951b7f3fc67cd9bce67ac6d01d44a647a10ad
Reviewed-on: https://go-review.googlesource.com/128755
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Reviewed-by: Martin Möhrmann <moehrmann@google.com>
Tobias Klauser [Tue, 21 Aug 2018 08:48:00 +0000 (10:48 +0200)]
syscall: add S_IRWXG and S_IRWXO on Solaris
As discussed in CL 126621, these constants are already defined on Linux,
Darwin, FreeBSD and NetBSD. In order to ensure portability of existing
code using the syscall package, provide them for Solaris as well.
Tobias Klauser [Tue, 21 Aug 2018 06:31:38 +0000 (08:31 +0200)]
syscall: add S_IRWXG and S_IRWXO on OpenBSD
As discussed in CL 126621, these constants are already defined on Linux,
Darwin, FreeBSD and NetBSD. In order to ensure portability of existing
code using the syscall package, provide them for OpenBSD (and
DragonflyBSD, in a separate CL) as well.
Tobias Klauser [Tue, 21 Aug 2018 06:28:16 +0000 (08:28 +0200)]
syscall: add S_IRWXG and S_IRWXO on DragonflyBSD
As discussed in CL 126621, these constants are already defined on Linux,
Darwin, FreeBSD and NetBSD. In order to ensure portability of existing
code using the syscall package, provide them for DragonflyBSD (and
OpenBSD, in a separate CL) as well.
Daniel Martí [Sat, 7 Jul 2018 20:40:28 +0000 (21:40 +0100)]
encoding/json: remove alloc when encoding short byte slices
If the encoded bytes fit in the bootstrap array encodeState.scratch, use
that instead of allocating a new byte slice.
Also tweaked the Encoding vs Encoder heuristic to use the length of the
encoded bytes, not the length of the input bytes. Encoding is used for
allocations of up to 1024 bytes, as we measured 2048 to be the point
where it no longer provides a noticeable advantage.
Also added some benchmarks. Only the first case changes in behavior.
Daniel Martí [Sat, 7 Jul 2018 14:59:20 +0000 (15:59 +0100)]
encoding/json: encode struct field names ahead of time
Struct field names are static, so we can run HTMLEscape on them when
building each struct type encoder. Then, when running the struct
encoder, we can select either the original or the escaped field name to
write directly.
When the encoder is not escaping HTML, using the original string works
because neither Go struct field names nor JSON tags allow any characters
that would need to be escaped, like '"', '\\', or '\n'.
When the encoder is escaping HTML, the only difference is that '<', '>',
and '&' are allowed via JSON struct field tags, hence why we use
HTMLEscape to properly escape them.
All of the above lets us encode field names with a simple if/else and
WriteString calls, which are considerably simpler and faster than
encoding an arbitrary string.
While at it, also include the quotes and colon in these strings, to
avoid three WriteByte calls in the loop hot path.
Also added a few tests, to ensure that the behavior in these edge cases
is not broken. The output of the tests is the same if this optimization
is reverted.
name old time/op new time/op delta
CodeEncoder-4 7.12ms ± 0% 6.14ms ± 0% -13.85% (p=0.004 n=6+5)
name old speed new speed delta
CodeEncoder-4 272MB/s ± 0% 316MB/s ± 0% +16.08% (p=0.004 n=6+5)
name old alloc/op new alloc/op delta
CodeEncoder-4 91.9kB ± 0% 93.2kB ± 0% +1.43% (p=0.002 n=6+6)
name old allocs/op new allocs/op delta
CodeEncoder-4 0.00 0.00 ~ (all equal)
Daniel Martí [Wed, 15 Aug 2018 11:40:07 +0000 (12:40 +0100)]
cmd/go: fix 'go vet -h' to print the right text
For the last two releases, its output has been the same as 'go -h'.
The test and vet sub-commands share their flag logic via the cmdflag
package, so fixing it there would mean a larger refactor. Moreover, the
test subcommand handles its '-h' flag in a special way; that's #26999.
For now, use a much less invasive fix, mirroring the special-casing of
'test -h' to simply print vet's short usage text.
Also add a regression test via a cmd/go test script.
Fixes #26998.
Change-Id: Ie6b866d98116a1bc5f84a204e1c9f1c2f6b48bff
Reviewed-on: https://go-review.googlesource.com/129318
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Rob Pike <r@golang.org> Reviewed-by: Russ Cox <rsc@golang.org>
Marcus Willock [Fri, 3 Aug 2018 15:13:14 +0000 (15:13 +0000)]
net/http: add an example of creating a custom FileSystem
The existing documentation of http.Dir is clear in that, if you want to hide
your files and directories that start with a period, you must create
a custom FileSystem. However, there are currently no example on how
to create a custom FileSystem. This commit provides an example.
Brad Fitzpatrick [Thu, 2 Aug 2018 19:15:25 +0000 (19:15 +0000)]
net: lazily look up the listenerBacklog value on first use
Don't open files or do sysctls in init.
Updates #26775
Change-Id: I017bed6c24ef1e4bc30040120349fb779f203225
Reviewed-on: https://go-review.googlesource.com/127655 Reviewed-by: Ian Lance Taylor <iant@golang.org>
Peter Collingbourne [Tue, 21 Aug 2018 01:42:02 +0000 (18:42 -0700)]
cmd/link: pass provided ldflags when testing whether an ldflag is supported
It's possible for one of the ldflags to cause the compiler driver to
use a different linker than the default, so we need to make sure that
the flag is supported by whichever linker is specified.
Fixes #27110.
Change-Id: Ic0c51b886e34344d324e68cbf6673b168c14992f
Reviewed-on: https://go-review.googlesource.com/130316
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
Ian Lance Taylor [Sat, 30 Jun 2018 04:14:47 +0000 (21:14 -0700)]
cmd/compile: only support -race and -msan where they work
Consolidate decision about whether -race and -msan options are
supported in cmd/internal/sys. Use consolidated functions in
cmd/compile and cmd/go. Use a copy of them in cmd/dist; cmd/dist can't
import cmd/internal/sys because Go 1.4 doesn't have it.
Fixes #24315
Change-Id: I9cecaed4895eb1a2a49379b4848db40de66d32a9
Reviewed-on: https://go-review.googlesource.com/121816
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Brad Fitzpatrick [Fri, 3 Aug 2018 19:21:11 +0000 (19:21 +0000)]
go/doc: compile regexps lazily
Compile go/doc's 4 regexps lazily, on demand.
Also, add a test for the one that had no test coverage.
This reduces init-time CPU as well as heap by ~20KB when they're not
used, which seems to be common enough. As an example, cmd/doc only
seems to use 1 of them. (as noted by temporary print statements)
Updates #26775
Change-Id: I85df89b836327a53fb8e1ace3f92480374270368
Reviewed-on: https://go-review.googlesource.com/127875
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>