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)
Change-Id: Ie55baeab89abad9b9f13e9f6ca886a670c30dba9
Reviewed-on: https://go-review.googlesource.com/122461
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
A number of explicit function literals found through the
unlambda linter are removed.
Fixes#26802
Change-Id: I0b122bdd95e9cb804c77efe20483fdf681c8154e
Reviewed-on: https://go-review.googlesource.com/127756
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
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)
Updates #5683.
Change-Id: I12757c325a68abb2856026cf719c122612a1f38e
Reviewed-on: https://go-review.googlesource.com/125417
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
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)
Updates #5683.
Change-Id: I0dd47783530f439b125e084aede09dda172eb1e8
Reviewed-on: https://go-review.googlesource.com/125416
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
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.
Fixes#27125
Change-Id: I92adade2fe456103d2d5c0315629ca0256953764
Reviewed-on: https://go-review.googlesource.com/130535
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Since the 12.x branch, the getrandom syscall had been introduced
with similar interface as Linux's and consistent syscall id
across architectures.
Change-Id: I63d6b45dbe9e29f07f1b5b6c2ec8be4fa624b9ee
GitHub-Last-Rev: 6fb76e6522
GitHub-Pull-Request: golang/go#25976
Reviewed-on: https://go-review.googlesource.com/120055
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
_GoStringLen performs an implicit conversion from intgo to size_t.
Explicitly cast to size_t.
This change avoids warnings when using cgo with CFLAGS:
-Wconversion.
Change-Id: I58f75a35e17f669a67f9805061c041b03eddbb5c
GitHub-Last-Rev: b5df1ac0c3
GitHub-Pull-Request: golang/go#27092
Reviewed-on: https://go-review.googlesource.com/129820
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
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>
Ceil and Trunc of -0.2 return -0, not +0, but we didn't test that.
Updates #23647
Change-Id: Idbd4699376abfb4ca93f16c73c114d610d86a9f2
Reviewed-on: https://go-review.googlesource.com/91335
Run-TryBot: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
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>
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.
Change-Id: I2836f779b88bf8876d5fa725043a6042bdda0390
Reviewed-on: https://go-review.googlesource.com/130515
Run-TryBot: Ilya Tocar <ilya.tocar@intel.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
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.
Change-Id: Ib1240d0b278e9d667ad419fe91fa52b23d28cfc0
Reviewed-on: https://go-review.googlesource.com/130478
Run-TryBot: Ilya Tocar <ilya.tocar@intel.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
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)
Updates #5683.
Change-Id: I9d751e22502221962da696e48996ffdeb777277d
Reviewed-on: https://go-review.googlesource.com/122468
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Calling Name on a reflect.Type is somewhat expensive, as it involves a
number of nested calls and string handling.
This cost was showing up when decoding structs, as we were calling it to
set up an error context.
We can avoid the extra work unless we do encounter an error, which makes
decoding via struct types faster.
name old time/op new time/op delta
CodeDecoder-4 31.0ms ± 1% 29.9ms ± 1% -3.69% (p=0.002 n=6+6)
name old speed new speed delta
CodeDecoder-4 62.6MB/s ± 1% 65.0MB/s ± 1% +3.83% (p=0.002 n=6+6)
Updates #5683.
Change-Id: I48a3a85ef0ba96f524b7c3e9096cb2c4589e077a
Reviewed-on: https://go-review.googlesource.com/122467
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
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.
Change-Id: I5cf01800d08554ca364e46cfc1d9445cf3c711a0
Reviewed-on: https://go-review.googlesource.com/115555
Run-TryBot: Michael Munday <mike.munday@ibm.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
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>
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>
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.
Change-Id: Id49f6991f36775b152b9c47b9923cd0a08053bcb
Reviewed-on: https://go-review.googlesource.com/130356
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
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.
Change-Id: Ia9e07cb01f989d144a620d268daa8ec946788861
Reviewed-on: https://go-review.googlesource.com/130336
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
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.
Change-Id: I708c60f75f787a410bdfa4ceebd2825874e92511
Reviewed-on: https://go-review.googlesource.com/130335
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Complete CL117178 removing all references to GitHub, and leaving
a small note to make sure we remember that it's not supported.
Change-Id: Id4257515a864875808fa7a67f002ed52cfd635a3
Reviewed-on: https://go-review.googlesource.com/130395
Reviewed-by: Daniel Martí <mvdan@mvdan.cc>
ssaConfig.Race was being set by many goroutines concurrently, resulting
in a data race seen below. This was very likely introduced by CL 121235.
WARNING: DATA RACE
Write at 0x00c000344408 by goroutine 12:
cmd/compile/internal/gc.buildssa()
/workdir/go/src/cmd/compile/internal/gc/ssa.go:134 +0x7a8
cmd/compile/internal/gc.compileSSA()
/workdir/go/src/cmd/compile/internal/gc/pgen.go:259 +0x5d
cmd/compile/internal/gc.compileFunctions.func2()
/workdir/go/src/cmd/compile/internal/gc/pgen.go:323 +0x5a
Previous write at 0x00c000344408 by goroutine 11:
cmd/compile/internal/gc.buildssa()
/workdir/go/src/cmd/compile/internal/gc/ssa.go:134 +0x7a8
cmd/compile/internal/gc.compileSSA()
/workdir/go/src/cmd/compile/internal/gc/pgen.go:259 +0x5d
cmd/compile/internal/gc.compileFunctions.func2()
/workdir/go/src/cmd/compile/internal/gc/pgen.go:323 +0x5a
Goroutine 12 (running) created at:
cmd/compile/internal/gc.compileFunctions()
/workdir/go/src/cmd/compile/internal/gc/pgen.go:321 +0x39b
cmd/compile/internal/gc.Main()
/workdir/go/src/cmd/compile/internal/gc/main.go:651 +0x437d
main.main()
/workdir/go/src/cmd/compile/main.go:51 +0x100
Goroutine 11 (running) created at:
cmd/compile/internal/gc.compileFunctions()
/workdir/go/src/cmd/compile/internal/gc/pgen.go:321 +0x39b
cmd/compile/internal/gc.Main()
/workdir/go/src/cmd/compile/internal/gc/main.go:651 +0x437d
main.main()
/workdir/go/src/cmd/compile/main.go:51 +0x100
Instead, set up the field exactly once as part of initssaconfig.
Change-Id: I2c30c6b1cf92b8fd98e7cb5c2e10c526467d0b0a
Reviewed-on: https://go-review.googlesource.com/130375
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Dave Cheney <dave@cheney.net>
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.
name old time/op new time/op delta
MarshalBytes/32-4 420ns ± 1% 383ns ± 1% -8.69% (p=0.002 n=6+6)
MarshalBytes/256-4 913ns ± 1% 915ns ± 0% ~ (p=0.580 n=5+6)
MarshalBytes/4096-4 7.72µs ± 0% 7.74µs ± 0% ~ (p=0.340 n=5+6)
name old alloc/op new alloc/op delta
MarshalBytes/32-4 112B ± 0% 64B ± 0% -42.86% (p=0.002 n=6+6)
MarshalBytes/256-4 736B ± 0% 736B ± 0% ~ (all equal)
MarshalBytes/4096-4 7.30kB ± 0% 7.30kB ± 0% ~ (all equal)
name old allocs/op new allocs/op delta
MarshalBytes/32-4 2.00 ± 0% 1.00 ± 0% -50.00% (p=0.002 n=6+6)
MarshalBytes/256-4 2.00 ± 0% 2.00 ± 0% ~ (all equal)
MarshalBytes/4096-4 2.00 ± 0% 2.00 ± 0% ~ (all equal)
Updates #5683.
Change-Id: I5fa55c27bd7728338d770ae7c0756885ba9a5724
Reviewed-on: https://go-review.googlesource.com/122462
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
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)
Updates #5683.
Change-Id: I6f6a340d0de4670799ce38cf95b2092822d2e3ef
Reviewed-on: https://go-review.googlesource.com/122460
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
They are no longer used outside the package since CL 38080.
Passes toolstash-check -all
Change-Id: I30977ed2b233b7c8c53632cc420938bc3b0e37c6
Reviewed-on: https://go-review.googlesource.com/129781
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
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>
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.
Fixes#20759
Change-Id: I5a350675536f81412af384d1a316fd6cd6241563
GitHub-Last-Rev: 8b0b644cd0
GitHub-Pull-Request: golang/go#26768
Reviewed-on: https://go-review.googlesource.com/127576
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
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>
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>
The code was fixed in CL 108559 but the testing TODO was not implemented.
Updates #22936
Change-Id: I20a703260a181bbcf5f87609d6fb8221a182be1a
Reviewed-on: https://go-review.googlesource.com/125038
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rob Pike <r@golang.org>
Reviewed-by: Daniel Martí <mvdan@mvdan.cc>
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>
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>