We already combine const stores up-to MOVQstoreconst.
Combine 2 64-bit stores of const zero into 1 sse store of 128-bit zero.
Shaves significant (>1%) amount of code from go tool:
/localdisk/itocar/golang/bin/go 10334877
go_old 10388125 [53248 bytes]
global text (code) = 51041 bytes (1.343944%)
read-only data = 663 bytes (0.039617%)
Total difference 51704 bytes (0.873981%)
Change-Id: I7bc40968023c3a69f379b10fbb433cdb11364f1b
Reviewed-on: https://go-review.googlesource.com/56250
Run-TryBot: Ilya Tocar <ilya.tocar@intel.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Giovanni Bajo <rasky@develer.com>
Reviewed-by: Keith Randall <khr@golang.org>
Instructions are implemented in the following revisions:
PCMPESTRI - https://golang.org/cl/22337
PHMINPOSUW - https://golang.org/cl/18853
It is unknown when x86test will be updated/re-run, but tests are useful
to check which x86 instructions are not yet supported.
As an example of tool that uses this information, there is Damien
Lespiau x86db.
Part of the mission to add missing amd64 SSE4 instructions to Go asm.
Change-Id: I512ff26040f47a0976b3e37000fb1f37eac5b762
Reviewed-on: https://go-review.googlesource.com/55830
Run-TryBot: Ilya Tocar <ilya.tocar@intel.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ilya Tocar <ilya.tocar@intel.com>
This makes it much easier to run individual failing subtests.
Use $(go env CC) instead of always defaulting to clang; this makes it
easier to test with other compilers.
Run C binaries to detect incompatible compiler/kernel pairings instead
of sniffing versions.
updates #21196
Change-Id: I0debb3cc4a4244df44b825157ffdc97b5c09338d
Reviewed-on: https://go-review.googlesource.com/52910
Run-TryBot: Bryan Mills <bcmills@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
The existing implementation is translated from C, which uses a
polynomial coefficient very close to 1/6. If the function uses
1/6 as this coeffient, the result of Exp(1) will be more accurate.
And this change doesn't introduce more error to Exp function.
Fixes#20319
Change-Id: I94c236a18cf95570ebb69f7fb99884b0d7cf5f6e
Reviewed-on: https://go-review.googlesource.com/49294
Reviewed-by: Robert Griesemer <gri@golang.org>
Prioritized the chunks of code with 8 or more levels of indentation.
Basically early breaks/returns and joining nested ifs.
Change-Id: I6817df1303226acf2eb904a29f2db720e4f7427a
Reviewed-on: https://go-review.googlesource.com/55630
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
Current code detect runtime/cgo iff the package or sub packages imports
runtime/cgo directly. However, when we are using linkshared, imported
shared libraries might have already included runtime/cgo.
This CL handles later case by looking an actual runtime/cgo symbol.
Change-Id: I35e7dfdb5e1a939eafc95a0259ee1af9782bc864
Reviewed-on: https://go-review.googlesource.com/56310
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
While LoadCmdDylib represents LC_LOAD_DYLIB,
LoadCmdDylinker represents LC_ID_DYLINKER.
This is confusing because there is another command called LC_LOAD_DYLINKER.
LC_ID_DYLINKER is not included in normal binary, it is only used for
/usr/lib/dyld as far as I know. So, perhaps this is a mistake.
Change-Id: I6ea61664a26998962742914af5688e094a233541
Reviewed-on: https://go-review.googlesource.com/56330
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
add tests for LC_LOAD_DYLIB.
Change-Id: Ic4b7a0f6296709175e9a75240aecd1d5291ade4b
Reviewed-on: https://go-review.googlesource.com/56311
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Test is not run in short mode, except on builders.
Change-Id: I4456830770188951e05ac13669e834a25bf569ae
Reviewed-on: https://go-review.googlesource.com/55973
Run-TryBot: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Joe Tsai <joetsai@google.com>
Reviewed-by: Joe Tsai <joetsai@google.com>
Reviewed-by: Marvin Stenger <marvin.stenger94@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Currently, we have a workaround for solaris that enforce aboslute
addressing for external symbols. However, We don't want to use the
workaround for darwin.
This CL also refactors code a little bit, because the original function
name is not appropriate now.
Updates #17490
Change-Id: Id21f9cdf33dca6a40647226be49010c2c324ee24
Reviewed-on: https://go-review.googlesource.com/54871
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
* group load command structs.
* use hex literal for LoadCommand.
Decimal number is not a proper representation for some commands.
(e.g. LC_RPATH = 0x8000001c)
* move Symbol struct from macho.go to file.go.
Symbol is a high level representation, not in Mach-O.
Change-Id: I3c69923cb464fb1211f2e766c02e1b537e0b5de2
Reviewed-on: https://go-review.googlesource.com/56130
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Fixes#10010.
Change-Id: Ib13ac28eafed72c456d8b5b6549015cdf5fdda94
Reviewed-on: https://go-review.googlesource.com/56190
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
When calling a Go function that returns multiple values from C, cgo
generates a structure to hold the values. According to the documentation
this structure is called `struct <function-name>_return`. When compiling
for gccgo the generated structure name is `struct <function-name>_result`.
This change updates the output for gccgo to match the documentation and
output for gc.
Fixes#20910
Change-Id: Iaea8030a695a7aaf9d9f317447fc05615d8e4adc
Reviewed-on: https://go-review.googlesource.com/49350
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
TestSizes has been added in CL 50170. This test is
failing on Plan 9 because executables don't have
a DWARF symbol table.
Fixes#21480.
Change-Id: I51079abdc18ad944617bdbcfe2dad970a0cea0f2
Reviewed-on: https://go-review.googlesource.com/56210
Run-TryBot: David du Colombier <0intro@gmail.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
We use a call to strncpy to work around a TSAN bug (wherein TSAN only
delivers asynchronous signals when the thread receiving the signal
calls a libc function). Unfortunately, GCC 7 inlines the call,
avoiding the TSAN libc trap entirely.
Per Ian's suggestion, use global variables as strncpy arguments: that
way, the compiler can't make any assumptions about the concrete values
and can't inline the call away.
fixes#21196
Change-Id: Ie95f1feaf9af1a8056f924f49c29cfc8515385d7
Reviewed-on: https://go-review.googlesource.com/55872
Reviewed-by: Ian Lance Taylor <iant@golang.org>
This should fix NaCl build failure for CL 49530.
Change-Id: Id9a54f0c81b1b5db5b5efb12a2ad6509c4ab42b3
Reviewed-on: https://go-review.googlesource.com/55770
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
There are a few cases where this can be useful. Apart from the obvious
(and silly)
100*n + 200*n
where we generate one IMUL instead of two, consider:
15*n + 31*n
Currently, the compiler strength-reduces both imuls, generating:
0x0000 00000 MOVQ "".n+8(SP), AX
0x0005 00005 MOVQ AX, CX
0x0008 00008 SHLQ $4, AX
0x000c 00012 SUBQ CX, AX
0x000f 00015 MOVQ CX, DX
0x0012 00018 SHLQ $5, CX
0x0016 00022 SUBQ DX, CX
0x0019 00025 ADDQ CX, AX
0x001c 00028 MOVQ AX, "".~r1+16(SP)
0x0021 00033 RET
But combining the imuls is both faster and shorter:
0x0000 00000 MOVQ "".n+8(SP), AX
0x0005 00005 IMULQ $46, AX
0x0009 00009 MOVQ AX, "".~r1+16(SP)
0x000e 00014 RET
even without strength-reduction.
Moreover, consider:
5*n + 7*(n+1) + 11*(n+2)
We already have a rule that rewrites 7(n+1) into 7n+7, so the
generated code (without imuls merging) looks like this:
0x0000 00000 MOVQ "".n+8(SP), AX
0x0005 00005 LEAQ (AX)(AX*4), CX
0x0009 00009 MOVQ AX, DX
0x000c 00012 NEGQ AX
0x000f 00015 LEAQ (AX)(DX*8), AX
0x0013 00019 ADDQ CX, AX
0x0016 00022 LEAQ (DX)(CX*2), CX
0x001a 00026 LEAQ 29(AX)(CX*1), AX
0x001f 00031 MOVQ AX, "".~r1+16(SP)
But with imuls merging, the 5n, 7n and 11n factors get merged, and the
generated code looks like this:
0x0000 00000 MOVQ "".n+8(SP), AX
0x0005 00005 IMULQ $23, AX
0x0009 00009 ADDQ $29, AX
0x000d 00013 MOVQ AX, "".~r1+16(SP)
0x0012 00018 RET
Which is both faster and shorter; that's also the exact same code that
clang and the intel c compiler generate for the above expression.
Change-Id: Ib4d5503f05d2f2efe31a1be14e2fe6cac33730a9
Reviewed-on: https://go-review.googlesource.com/55143
Reviewed-by: Keith Randall <khr@golang.org>
The DWARF entries for type-specific sudog entries used the
channel value type instead of a pointer-to-value type for the elem field.
Fixes#21094
R=go1.10
Change-Id: I3f63a5664f42b571f729931309f2c9f6f38ab031
Reviewed-on: https://go-review.googlesource.com/50170
Reviewed-by: Ian Lance Taylor <iant@golang.org>
If the source importer only encounters "soft" type checking errors
it can safely return the type-checked package because it will be
completely set up. This makes the source importer slightly more
robust in the presence of errors.
Fixes#20855.
Change-Id: I5af9ccdb30eee6bca7a0fab872f6057bde521bf3
Reviewed-on: https://go-review.googlesource.com/55730
Reviewed-by: Alan Donovan <adonovan@google.com>
pkgPath always received the empty string. Worse yet, it panicked if it
received anything else. This has been the case ever since newName was
introduced in early 2016.
Change-Id: I5f164305bd30c34455ef35e776c7616f303b37e4
Reviewed-on: https://go-review.googlesource.com/54331
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Crawshaw <crawshaw@golang.org>
updates #13745
Multiprecision squaring can be done in a straightforward manner
with about half the multiplications of a basic multiplication
due to the symmetry of the operands. This change implements
basic squaring for nat types and uses it for Int multiplication
when the same variable is supplied to both arguments of
z.Mul(x, x). This has some overhead to allocate a temporary
variable to hold the cross products, shift them to double and
add them to the diagonal terms. There is a speed benefit in
the intermediate range when the overhead is neglible and the
asymptotic performance of karatsuba multiplication has not been
reached.
basicSqrThreshold = 20
karatsubaSqrThreshold = 400
Were set by running calibrate_test.go to measure timing differences
between the algorithms. Benchmarks for squaring:
name old time/op new time/op delta
IntSqr/1-4 51.5ns ±25% 25.1ns ± 7% -51.38% (p=0.008 n=5+5)
IntSqr/2-4 79.1ns ± 4% 72.4ns ± 2% -8.47% (p=0.008 n=5+5)
IntSqr/3-4 102ns ± 4% 97ns ± 5% ~ (p=0.056 n=5+5)
IntSqr/5-4 161ns ± 4% 163ns ± 7% ~ (p=0.952 n=5+5)
IntSqr/8-4 277ns ± 5% 267ns ± 6% ~ (p=0.087 n=5+5)
IntSqr/10-4 358ns ± 3% 360ns ± 4% ~ (p=0.730 n=5+5)
IntSqr/20-4 1.07µs ± 3% 1.01µs ± 6% ~ (p=0.056 n=5+5)
IntSqr/30-4 2.36µs ± 4% 1.72µs ± 2% -27.03% (p=0.008 n=5+5)
IntSqr/50-4 5.19µs ± 3% 3.88µs ± 4% -25.37% (p=0.008 n=5+5)
IntSqr/80-4 11.3µs ± 4% 8.6µs ± 3% -23.78% (p=0.008 n=5+5)
IntSqr/100-4 16.2µs ± 4% 12.8µs ± 3% -21.49% (p=0.008 n=5+5)
IntSqr/200-4 50.1µs ± 5% 44.7µs ± 3% -10.65% (p=0.008 n=5+5)
IntSqr/300-4 105µs ±11% 95µs ± 3% -9.50% (p=0.008 n=5+5)
IntSqr/500-4 231µs ± 5% 227µs ± 2% ~ (p=0.310 n=5+5)
IntSqr/800-4 496µs ± 9% 459µs ± 3% -7.40% (p=0.016 n=5+5)
IntSqr/1000-4 700µs ± 3% 710µs ± 5% ~ (p=0.841 n=5+5)
Show a speed up of 10-25% in the range where basicSqr is optimal,
improved single word squaring and no significant difference when
the fallback to standard multiplication is used.
Change-Id: Iae2c82ca91cf890823f91e5c83bbe9a2c534b72b
Reviewed-on: https://go-review.googlesource.com/53638
Reviewed-by: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
$ gotip tool -h says:
For more about each tool command, see 'go tool command -h'.
But it's better to suggest
go doc cmd/<command>
Fixes#18313
Change-Id: I0a36d585906a5e1879e5b7927d1b6173e97cb500
Reviewed-on: https://go-review.googlesource.com/55990
Reviewed-by: Ian Lance Taylor <iant@golang.org>
The current implementation of the extended Euclidean GCD algorithm
calculates both cosequences x and y inside the division loop. This
is unneccessary since the second Bezout coefficient can be obtained
at the end of calculation via a multiplication, subtraction and a
division. In case only one coefficient is needed, e.g. ModInverse
this calculation can be skipped entirely. This is a standard
optimization, see e.g.
"Handbook of Elliptic and Hyperelliptic Curve Cryptography"
Cohen et al pp 191
Available at:
http://cs.ucsb.edu/~koc/ccs130h/2013/EllipticHyperelliptic-CohenFrey.pdf
Updates #15833
Change-Id: I1e0d2e63567cfed97fd955048fe6373d36f22757
Reviewed-on: https://go-review.googlesource.com/50530
Reviewed-by: Robert Griesemer <gri@golang.org>
The current implementation uses a shift and add
loop to compute the product of x's exponent xe and
the integer part of y (yi) for yi up to 1<<63.
Since xe is an 11-bit exponent, this product can be
up to 74-bits and overflow both 32 and 64-bit int.
This change checks whether the accumulated exponent
will fit in the 11-bit float exponent of the output
and breaks out of the loop early if overflow is detected.
The current handling of yi >= 1<<63 uses Exp(y * Log(x))
which incorrectly returns Nan for x<0. In addition,
for y this large, Exp(y * Log(x)) can be enumerated
to only overflow except when x == -1 since the
boundary cases computed exactly:
Pow(NextAfter(1.0, Inf(1)), 1<<63) == 2.72332... * 10^889
Pow(NextAfter(1.0, Inf(-1)), 1<<63) == 1.91624... * 10^-445
exceed the range of float64. So, the call can be
replaced with a simple case statement analgous to
y == Inf that correctly handles x < 0 as well.
Fixes#7394
Change-Id: I6f50dc951f3693697f9669697599860604323102
Reviewed-on: https://go-review.googlesource.com/48290
Reviewed-by: Robert Griesemer <gri@golang.org>
The Writer logic was not consistent about when an IO error would
persist across multiple calls on Writer's methods.
Thus, to make the error handling more consistent we always check
the persistent state of the error prior to every exported method
call, and return an error if set. Otherwise, it is the responsibility
of every exported method to persist any fatal errors that may occur.
As a simplification, we can remove the close field since that
information can be represented by simply storing ErrWriteAfterClose
in the err field.
Change-Id: I8746ca36b3739803e0373253450db69b3bd12f38
Reviewed-on: https://go-review.googlesource.com/55590
Run-TryBot: Joe Tsai <joetsai@digital-static.net>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
The GNU tar format defines the following type flags:
TypeGNULongName = 'L' // Next file has a long name
TypeGNULongLink = 'K' // Next file symlinks to a file w/ a long name
Anytime a string exceeds the field dedicated to store it, the GNU format
permits a fake "file" to be prepended where that file entry has a Typeflag
of 'L' or 'K' and the contents of the file is a NUL-terminated string.
Contrary to previous TODO comments,
the GNU format supports arbitrary strings (without NUL) rather UTF-8 strings.
The manual says the following:
<<<
The name, linkname, magic, uname, and gname are
null-terminated character strings
>>>
<<<
All characters in header blocks are represented
by using 8-bit characters in the local variant of ASCII.
>>>
From this description, we gather the following:
* We must forbid NULs in any GNU strings
* Any 8-bit value (other than NUL) is permitted
Since the modern world has moved to UTF-8, it is really difficult to
determine what a "local variant of ASCII" means. For this reason,
we treat strings as just an arbitrary binary string (without NUL)
and leave it to the user to determine the encoding of this string.
(Practically, it seems that UTF-8 is the typical encoding used
in GNU archives seen in the wild).
The implementation of GNU tar seems to confirm this interpretation
of the manual where it permits any arbitrary binary string to exist
within these fields so long as they do not contain the NUL character.
$ touch `echo -e "not\x80\x81\x82\x83utf8"`
$ gnutar -H gnu --tar -cvf gnu-not-utf8.tar $(echo -e "not\x80\x81\x82\x83utf8")
The fact that we permit arbitrary binary in GNU strings goes
hand-in-hand with the fact that GNU also permits a "base-256" encoding
of numeric fields, which is effectively two-complement binary.
Change-Id: Ic037ec6bed306d07d1312f0058594bd9b64d9880
Reviewed-on: https://go-review.googlesource.com/55573
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Joe Tsai <thebrokentoaster@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
In the existing implementation, if pattern is an empty string,
program calls a panic with the message which is a concatenation of
"http: invalid pattern " and pattern.
In this case, pattern is an empty, so the commit removes
this concatenation and the trailing space.
Fixes: #21102
Change-Id: I49f58b52d835311a6ac642de871eb15646e48a54
Reviewed-on: https://go-review.googlesource.com/50350
Reviewed-by: Dmitri Shuralyov <shurcool@gmail.com>
Reviewed-by: Tom Bergan <tombergan@google.com>
Run-TryBot: Tom Bergan <tombergan@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
The code was adding race.Errors to t.raceErrors before checking
Failed, but Failed was using t.raceErrors+race.Errors. We don't want
to change Failed, since that would affect tests themselves, so modify
the harness to not unnecessarily change t.raceErrors.
Updates #19851Fixes#21338
Change-Id: I7bfdf281f90e045146c92444f1370d55c45221d4
Reviewed-on: https://go-review.googlesource.com/54050
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
Run-TryBot: Joe Tsai <thebrokentoaster@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This reduces the code footprint of code like:
println("foo=", foo, "bar=", bar)
which is fairly common in the runtime.
Prior to this change, this makes function calls to print each of:
"foo=", " ", foo, " ", "bar=", " ", bar, "\n"
After this change, this prints:
"foo= ", foo, " bar= ", bar, "\n"
This shrinks the hello world binary by 0.4%.
More importantly, this improves the instruction
density of important runtime routines.
Change-Id: I8971bdf5382fbaaf4a82bad4442f9da07c28d395
Reviewed-on: https://go-review.googlesource.com/55098
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Rather than emitting spaces and newlines for println
as we walk the expression, construct it all up front.
This enables further optimizations.
This requires using printstring instead of print in
the implementation of printsp and printnl,
on pain of infinite recursion.
That's ok; it's more efficient anyway, and just as simple.
While we're here, do it for other print routines as well.
Change-Id: I61d7df143810e00710c4d4d948d904007a7fd190
Reviewed-on: https://go-review.googlesource.com/55097
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Writing to selectdone on the stack of another goroutine meant a
pretty subtle dance between the select code and the stack copying
code. Instead move the selectdone variable into the g struct.
Change-Id: Id246aaf18077c625adef7ca2d62794afef1bdd1b
Reviewed-on: https://go-review.googlesource.com/53390
Reviewed-by: Austin Clements <austin@google.com>
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
I noticed that we don't set an itab's function pointers at compile
time. Instead, we currently do it at executable startup.
Set the function pointers at compile time instead. This shortens
startup time. It has no effect on normal binary size. Object files
will have more relocations, but that isn't a big deal.
For PIE there are additional pointers that will need to be adjusted at
load time. There are already other pointers in an itab that need to be
adjusted, so the cache line will already be paged in. There might be
some binary size overhead to mark these pointers. The "go test -c
-buildmode=pie net/http" binary is 0.18% bigger.
Update #20505
Change-Id: I267c82489915b509ff66e512fc7319b2dd79b8f7
Reviewed-on: https://go-review.googlesource.com/44341
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Martin Möhrmann <moehrmann@google.com>
Currently, GC captures the start-the-world time stamp after
startTheWorldWithSema returns. This is problematic for two reasons:
1. It's possible to get preempted between startTheWorldWithSema
starting the world and calling nanotime.
2. startTheWorldWithSema does several clean-up tasks after the world
is up and running that on rare occasions can take upwards of 10ms.
Since the runtime uses the start-the-world time stamp to compute the
STW duration, both of these can significantly inflate the reported STW
duration.
Fix this by having startTheWorldWithSema itself call nanotime once the
world is started.
Change-Id: I114630234fb73c9dabae50a2ef1884661f2459db
Reviewed-on: https://go-review.googlesource.com/55410
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rick Hudson <rlh@golang.org>