One intrinsic was needed to help get the very best
performance out of a future GC; as long as that one was
being added, I also added Bswap since that is sometimes
a handy thing to have. I had intended to fill out the
bit-scan intrinsic family, but the mismatch between the
"scan forward" instruction and "count leading zeroes"
was large enough to cause me to leave it out -- it poses
a dilemma that I'd rather dodge right now.
These intrinsics are not exposed for general use.
That's a separate issue requiring an API proposal change
( https://github.com/golang/proposal )
All intrinsics are tested, both that they are substituted
on the appropriate architecture, and that they produce the
expected result.
Change-Id: I5848037cfd97de4f75bdc33bdd89bba00af4a8ee
Reviewed-on: https://go-review.googlesource.com/20564
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Calling the read only Linkrlookup will now not cause the name
string to escape. So a lookup can be performed on a []byte
casted to a string without allocating. This will help a followup
cl and it is also much simpler and cleaner.
Performance not impacted by this.
name old s/op new s/op delta
LinkCmdGo 0.51 ± 6% 0.51 ± 5% ~ (p=0.192 n=98+98)
Change-Id: I7846ba3160eb845a3a29cbf0be703c47369ece16
Reviewed-on: https://go-review.googlesource.com/21187
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: David Crawshaw <crawshaw@golang.org>
Run-TryBot: David Crawshaw <crawshaw@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
I want to get rid of OTFUNC, which serves no useful purpose. However,
it turns out that the escape analysis pass looks at the node slices set
up for OTFUNC, even though by the time escape analysis runs the OTFUNC
has been converted to OTYPE. This CL converts the escape analysis code
to look at the function decls instead, and clears the OTFUNC info when
converting to OTYPE to ensure that nothing else looks at it.
Change-Id: I3f2f5997ea8ea7a127a858e94b20aabfab84a5bf
Reviewed-on: https://go-review.googlesource.com/21202
Run-TryBot: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Remove all special handling of Google Code, which has shut down.
Commit 4ec2fd3e6a suggested that maybe the
shutdown warning should remain. However, it has been missing from Go 1.6
already, and by Go 1.7 people will most likely have realised that Google
Code has shut down.
Updates #10193.
Change-Id: I5749bbbe2fe3b07cff4edd20303bbedaeaa8d77b
Reviewed-on: https://go-review.googlesource.com/21189
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Make verbs b,c,o and U work for any array and slice of integer
type including byte and uint8.
Fix a bug that triggers badverb for []uint8 and []byte type
on the slice/array level instead of on each element like for
any other slice or array type.
Add tests that make sure we do not accidentally alter the
behavior of printing []byte for []byte and []uint8 type
if they are used at the top level when formatting with %#v.
name old time/op new time/op delta
SprintfHexBytes-2 177ns ± 2% 176ns ± 2% ~ (p=0.066 n=48+49)
SprintfBytes-2 330ns ± 1% 329ns ± 1% ~ (p=0.118 n=45+47)
Fixes#13478
Change-Id: I99328a184973ae219bcc0f69c3978cb1ff462888
Reviewed-on: https://go-review.googlesource.com/20686
Run-TryBot: Rob Pike <r@golang.org>
Reviewed-by: Rob Pike <r@golang.org>
Merge printReflectValue into printValue. Determine if handleMethods
was already called in printArg by checking if depth is 0. Do not
call handleMethods on depth 0 again in printValue to not introduce
a performance regression. handleMethods is called already in printArg
to not introduce a performance penalty for top-level Stringer,
GoStringer, Errors and Formatters by using reflect.ValueOf on them
just to retrieve them again as interface{} values in printValue.
Clear p.arg in printValue after handleMethods to print the type
of the value inside the reflect.Value when a bad verb is encountered
on the top level instead of printing "reflect.Value=" as the type of
the argument. This also fixes a bug that incorrectly prints the
whole map instead of just the value for a key if the returned value
by the map for the key is an invalid reflect value.
name old time/op new time/op delta
SprintfPadding-2 229ns ± 2% 227ns ± 1% -0.50% (p=0.013 n=20+20)
SprintfEmpty-2 36.4ns ± 6% 37.2ns ±14% ~ (p=0.091 n=18+20)
SprintfString-2 102ns ± 1% 102ns ± 0% ~ (p=0.751 n=20+20)
SprintfTruncateString-2 142ns ± 0% 141ns ± 1% -0.95% (p=0.000 n=16+20)
SprintfQuoteString-2 389ns ± 0% 388ns ± 0% -0.12% (p=0.019 n=20+20)
SprintfInt-2 100ns ± 2% 100ns ± 1% ~ (p=0.188 n=20+15)
SprintfIntInt-2 155ns ± 3% 154ns ± 2% ~ (p=0.092 n=20+20)
SprintfPrefixedInt-2 250ns ± 2% 251ns ± 3% ~ (p=0.559 n=20+20)
SprintfFloat-2 177ns ± 2% 175ns ± 1% -1.30% (p=0.000 n=20+20)
SprintfComplex-2 516ns ± 1% 510ns ± 1% -1.13% (p=0.000 n=19+16)
SprintfBoolean-2 90.9ns ± 3% 90.6ns ± 1% ~ (p=0.193 n=19+19)
SprintfHexString-2 171ns ± 1% 169ns ± 1% -1.44% (p=0.000 n=19+20)
SprintfHexBytes-2 180ns ± 1% 180ns ± 1% ~ (p=0.060 n=19+18)
SprintfBytes-2 330ns ± 1% 329ns ± 1% -0.42% (p=0.003 n=20+20)
SprintfStringer-2 354ns ± 3% 352ns ± 3% ~ (p=0.525 n=20+19)
SprintfStructure-2 804ns ± 3% 776ns ± 2% -3.56% (p=0.000 n=20+20)
FprintInt-2 155ns ± 0% 151ns ± 1% -2.35% (p=0.000 n=19+20)
FprintfBytes-2 169ns ± 0% 170ns ± 1% +0.81% (p=0.000 n=18+19)
FprintIntNoAlloc-2 112ns ± 0% 109ns ± 1% -2.28% (p=0.000 n=20+20)
Change-Id: Ib9a39082ed1be0f1f7499ee6fb6c9530f043e43a
Reviewed-on: https://go-review.googlesource.com/20923
Run-TryBot: Rob Pike <r@golang.org>
Reviewed-by: Rob Pike <r@golang.org>
Remove format flag reset from doPrint. Flags will not be set in
doPrint and printArg will not return with flags modified.
Remove the extra arguments addspace and addnewline and split up
doPrint into two simpler and specialized functions.
Change-Id: Ib884d027abfbb31c6f01b008f51d6d76fc0c1a17
Reviewed-on: https://go-review.googlesource.com/21181
Run-TryBot: Rob Pike <r@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rob Pike <r@golang.org>
Use a type switch instead of calling Val.Ctype (which in turn just
uses a type switch anyway).
Use continue statements to simplify the control flow.
Change-Id: I65c139d706d4d78e5b4ce09d1b1505a3e424496b
Reviewed-on: https://go-review.googlesource.com/21173
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Try to avoid a race condition in the test. Passed 500 times on my
laptop.
Fixes#14956.
Change-Id: I5de2e1e3623832f0ab4f180149f7c57ce7cd23c0
Reviewed-on: https://go-review.googlesource.com/21171
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This is in support of https://golang.org/cl/18057 which adds
support for c-archive to the Windows platform.
The signal handling tests do not compile on Windows. This splits
them out into a separate main_unix.c file, and conditionally
includes them for non-Windows platforms.
Change-Id: Ic79ce83da7656d6703505e514554748a482b81a1
Reviewed-on: https://go-review.googlesource.com/21086
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
The colas function allocates 2 slice headers in each call (via Nodes.Set)
only to throw away those slice headers in the common case where both the
lhs and rhs in "lhs := rhs" have length 1.
Avoid the Nodes.Set calls in those cases. For make.bash, this eliminates
~63,000 slice header allocations.
Also: Minor cleanups in colasdefn.
Change-Id: Ib114a67c3adeb8821868bd71a5e0f5e2e19fcd4f
Reviewed-on: https://go-review.googlesource.com/21170
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
For #14876.
Change-Id: I0992859264cbaf9c9b691fad53345bbb01b4cf3b
Reviewed-on: https://go-review.googlesource.com/21085
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
For #14876.
Change-Id: I33947f74e8058437a784862f1f064974afc99250
Reviewed-on: https://go-review.googlesource.com/21084
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
- Fix a typo.
- Skip this test on -short on non-builders.
Change-Id: Id102eceb59451694bf92b618e02ccee6603b6852
Reviewed-on: https://go-review.googlesource.com/21113
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
High tag number form may not be used for tag numbers that fit in low tag number
form.
Change-Id: I93edde0e1f86087047e0b3f2e55d6180b01e78bf
Reviewed-on: https://go-review.googlesource.com/18224
Reviewed-by: Adam Langley <agl@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
For #14962.
Change-Id: I3539d882487c99dee99ac953e039b79c6b963cf9
Reviewed-on: https://go-review.googlesource.com/21150
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: David Crawshaw <crawshaw@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Fixes#14944
Change-Id: I73e0997cb6ebaeced1045b0ddadac893319bd78f
Reviewed-on: https://go-review.googlesource.com/21065
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
I recently added TestUnexportedMethods which uses an interface type
to pin type information for an unexported method. But as written,
the interface type is not accessible to the reflect package.
You can imagine a future compiler optimization realizing that and
removing the type information for f. In fact, cl/20901 happens to
do that.
Change-Id: I1ddb67f50cb9b5737253b58f10545f3de652c29d
Reviewed-on: https://go-review.googlesource.com/21112
Reviewed-by: Michel Lespinasse <walken@google.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: David Crawshaw <crawshaw@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This is a follow-up of https://go-review.googlesource.com/#/c/20653/
Special case computation for slices with elements of byte size or
pointer size.
name old time/op new time/op delta
GrowSliceBytes-4 86.2ns ± 3% 75.4ns ± 2% -12.50% (p=0.000 n=20+20)
GrowSliceInts-4 161ns ± 3% 136ns ± 3% -15.59% (p=0.000 n=19+19)
GrowSlicePtr-4 239ns ± 2% 233ns ± 2% -2.52% (p=0.000 n=20+20)
GrowSliceStruct24Bytes-4 258ns ± 3% 256ns ± 3% ~ (p=0.134 n=20+20)
Change-Id: Ice5fa648058fe9d7fa89dee97ca359966f671128
Reviewed-on: https://go-review.googlesource.com/21101
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
The exec wrapper lock file was opened, locked and then never used
again, assuming it would close and unlock at process exit.
However, the garbage collector could collect and run the *os.File
finalizer that closes the file prematurely, rendering the lock
ineffective.
Make the lock global so that the lock is live during the entire
execution.
(Hopefully) fix the iOS builders.
Change-Id: I62429e92042a0a49c4f1ea553fdb32b6ea53a43e
Reviewed-on: https://go-review.googlesource.com/21137
Reviewed-by: David Crawshaw <crawshaw@golang.org>
When creating binaries for dynamic linking, the linker moves
read-only data symbols that contain pointers into relro sections.
It is not setup for handling a go.string symbol moving to relro.
Instead of teaching it how (because go.string symbols with pointers
are unusual anyhow), put the data in a type.. section.
Fixes the android builder.
Change-Id: Ica4722d32241643c060923517b90276ff8ac6b07
Reviewed-on: https://go-review.googlesource.com/21110
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
There's a race between runtime.goexitsall killing all OS processes
of a go program in order to exit, and runtime.newosproc forking a
new one. If the new process has been created but not yet stored
its pid in m.procid, it will not be killed by goexitsall and
deadlock results.
This CL prevents the race by making the newly forked process
check whether the program is exiting. It also prevents a
potential "shoot-out" if multiple goroutines call Exit at
the same time, which could possibly lead to two processes
killing each other and leaving the rest deadlocked.
Change-Id: I3170b4a62d2461f6b029b3d6aad70373714ed53e
Reviewed-on: https://go-review.googlesource.com/21135
Run-TryBot: David du Colombier <0intro@gmail.com>
Reviewed-by: Marvin Stenger <marvin.stenger94@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David du Colombier <0intro@gmail.com>
During random stealing we steal 4*GOMAXPROCS times from random procs.
One would expect that most of the time we check all procs this way,
but due to low quality PRNG we actually miss procs with frightening
probability. Below are modelling experiment results for 1e6 tries:
GOMAXPROCS = 2 : missed 1 procs 7944 times
GOMAXPROCS = 3 : missed 1 procs 101620 times
GOMAXPROCS = 3 : missed 2 procs 3571 times
GOMAXPROCS = 4 : missed 1 procs 63916 times
GOMAXPROCS = 4 : missed 2 procs 61 times
GOMAXPROCS = 4 : missed 3 procs 16 times
GOMAXPROCS = 5 : missed 1 procs 133136 times
GOMAXPROCS = 5 : missed 2 procs 1025 times
GOMAXPROCS = 5 : missed 3 procs 101 times
GOMAXPROCS = 5 : missed 4 procs 15 times
GOMAXPROCS = 8 : missed 1 procs 151765 times
GOMAXPROCS = 8 : missed 2 procs 5057 times
GOMAXPROCS = 8 : missed 3 procs 1726 times
GOMAXPROCS = 8 : missed 4 procs 68 times
GOMAXPROCS = 12 : missed 1 procs 199081 times
GOMAXPROCS = 12 : missed 2 procs 27489 times
GOMAXPROCS = 12 : missed 3 procs 3113 times
GOMAXPROCS = 12 : missed 4 procs 233 times
GOMAXPROCS = 12 : missed 5 procs 9 times
GOMAXPROCS = 16 : missed 1 procs 237477 times
GOMAXPROCS = 16 : missed 2 procs 30037 times
GOMAXPROCS = 16 : missed 3 procs 9466 times
GOMAXPROCS = 16 : missed 4 procs 1334 times
GOMAXPROCS = 16 : missed 5 procs 192 times
GOMAXPROCS = 16 : missed 6 procs 5 times
GOMAXPROCS = 16 : missed 7 procs 1 times
GOMAXPROCS = 16 : missed 8 procs 1 times
A missed proc won't lead to underutilization because we check all procs
again after dropping P. But it can lead to an unpleasant situation
when we miss a proc, drop P, check all procs, discover work, acquire P,
miss the proc again, repeat.
Improve stealing logic to cover all procs.
Also don't enter spinning mode and try to steal when there is nobody around.
Change-Id: Ibb6b122cc7fb836991bad7d0639b77c807aab4c2
Reviewed-on: https://go-review.googlesource.com/20836
Reviewed-by: Rick Hudson <rlh@golang.org>
Run-TryBot: Dmitry Vyukov <dvyukov@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
Reviewed-by: Marvin Stenger <marvin.stenger94@gmail.com>
Change control flow to probe with N=1. This calls benchFunc
the same number of times as the old implementation in the
absence of subbenchmarks.
To be compatible with existing tools, benchmarking only
prints a line for "leaf" benchmarks. This means, though, that
the name of a benchmark can only be printed after the first
iteration.
Issue #14863
Change-Id: Ic7b9b89b058f8ebb5287755f24f9e47df8c9537c
Reviewed-on: https://go-review.googlesource.com/21043
Run-TryBot: Marcel van Lohuizen <mpvl@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
This change removes a lot of dead code. Some of the code has never been
used, not even when it was first commited. The rest shouldn't have
survived refactors.
This change doesn't remove unused routines helpful for debugging, nor
does it remove code that's used in commented out blocks of code that are
only unused temporarily. Furthermore, unused constants weren't removed
when they were part of a set of constants from specifications.
One noteworthy omission from this CL are about 1000 lines of unused code
in cmd/fix, 700 lines of which are the typechecker, which hasn't been
used ever since the pre-Go 1 fixes have been removed. I wasn't sure if
this code should stick around for future uses of cmd/fix or be culled as
well.
Change-Id: Ib714bc7e487edc11ad23ba1c3222d1fd02e4a549
Reviewed-on: https://go-review.googlesource.com/20926
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Store already padded keys instead of storing key and padding it during
Reset and Sum. This simplifies code and makes Reset-Write-Sum sequences
faster, which helps /x/crypto/pbkdf2.
HMAC benchmark:
benchmark old ns/op new ns/op delta
BenchmarkHMACSHA256_1K-4 7669 7613 -0.73%
BenchmarkHMACSHA256_32-4 1880 1737 -7.61%
benchmark old MB/s new MB/s speedup
BenchmarkHMACSHA256_1K-4 133.52 134.50 1.01x
BenchmarkHMACSHA256_32-4 17.02 18.41 1.08x
PBKDF2 benchmark:
benchmark old ns/op new ns/op delta
BenchmarkPBKDF2HMACSHA256-4 1943196 1807699 -6.97%
Change-Id: I6697028370c226715ab477b0844951a83eb3488c
Reviewed-on: https://go-review.googlesource.com/21024
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Adam Langley <agl@golang.org>
The Lookup method provides a way to extract a tag value, while
determining whether the tag key exists in the struct field's tag.
Fixes#14883
Change-Id: I7460cb68f0ca1aaa025935050b9e182efcb64db3
Reviewed-on: https://go-review.googlesource.com/20864
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Ther darwin/arm{,64} exec wrapper now limits the number of concurrent
executions to 1, so remove the higher level parallel task limit from
the Go command.
Change-Id: Id84f65c3908305bde0452b3c8db6df8c5a8881bb
Reviewed-on: https://go-review.googlesource.com/21100
Reviewed-by: David Crawshaw <crawshaw@golang.org>
I failed to rebase (and re-test) CL 21102 before submit, which meant
that two extra tests sneaked into testcarchive that still referenced
runtime.GOOS and runtime.GOARCH.
Convert the new tests.
While we're here, make sure pending tasks are flushed before running
the host tests. If not, the "##### misc/cgo/testcarchive" banner
and "PASS" won't show up in the all.bash output.
Change-Id: I41fc4ec9515f9a193fa052f7c31fac452153c897
Reviewed-on: https://go-review.googlesource.com/21106
Run-TryBot: Elias Naur <elias.naur@gmail.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Create a byte encoding designed for static Go names.
It is intended to be a compact representation of a name
and optional tag data that can be turned into a Go string
without allocating, and describes whether or not it is
exported without unicode table.
The encoding is described in reflect/type.go:
// The first byte is a bit field containing:
//
// 1<<0 the name is exported
// 1<<1 tag data follows the name
// 1<<2 pkgPath *string follow the name and tag
//
// The next two bytes are the data length:
//
// l := uint16(data[1])<<8 | uint16(data[2])
//
// Bytes [3:3+l] are the string data.
//
// If tag data follows then bytes 3+l and 3+l+1 are the tag length,
// with the data following.
//
// If the import path follows, then ptrSize bytes at the end of
// the data form a *string. The import path is only set for concrete
// methods that are defined in a different package than their type.
Shrinks binary sizes:
cmd/go: 164KB (1.6%)
jujud: 1.0MB (1.5%)
For #6853.
Change-Id: I46b6591015b17936a443c9efb5009de8dfe8b609
Reviewed-on: https://go-review.googlesource.com/20968
Run-TryBot: David Crawshaw <crawshaw@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
The c-archive test were recently converted from shell script to Go.
Unfortunately, it also lost the ability to target iOS and Android
that lack C compilers and require exec wrappers.
Compile the c-archive test for the host and run it with the target
GOOS/GOARCH environment. Change the test to rely on go env GOOS
and go env GOARCH instead of runtime.GOOS and runtime.GOARCH.
Fixes#8345
Change-Id: I290ace2f7e96b87c55d99492feb7d660140dcb32
Reviewed-on: https://go-review.googlesource.com/21102
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
In f the extra & 63 is redundant because SHRQ already
looks at the bottom 6 bits only. This is a trick on AMD64
to get rid of CMPQ/SBBQ/ANDQ if one knows that the shift
counter is small.
func f(x uint64, s uint) uint64 {
return x >> (s & 63)
}
Change-Id: I4861c902168dabec9a6a14a85750246dde94fc08
Reviewed-on: https://go-review.googlesource.com/21073
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: Alexandru Moșoi <alexandru@mosoi.ro>
TryBot-Result: Gobot Gobot <gobot@golang.org>
g used to produce CMPQ/SBBQ/ANDQ, but f didn't even though
s&15 is at most s&63.
func f(x uint64, s uint) uint64 {
return x >> (s & 63)
}
func g(x uint64, s uint) uint64 {
return x >> (s & 15)
}
Change-Id: Iab4a1a6e10b471dead9f1203e9d894677cf07bb2
Reviewed-on: https://go-review.googlesource.com/21048
Run-TryBot: Alexandru Moșoi <alexandru@mosoi.ro>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>