Most Go objects are compiled with known package path, so the
symbol name is already fully expanded. Nevertheless, currently
in the linker strings.Replace is called unconditionally, and most
of the time it doesn't do anything.
This CL records a per-object flag in the object file, and do the
name expansion only when the name is not expanded at compile time.
This gives small speedups for the linker. Linking cmd/compile:
name old time/op new time/op delta
Loadlib 35.1ms ± 2% 32.8ms ± 4% -6.43% (p=0.008 n=5+5)
Symtab 15.8ms ± 2% 14.0ms ± 8% -11.45% (p=0.008 n=5+5)
TotalTime 399ms ± 1% 385ms ± 2% -3.63% (p=0.008 n=5+5)
Change-Id: I735084971a051cd9be4284ad294c284cd5b545f4
Reviewed-on: https://go-review.googlesource.com/c/go/+/234490
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
The runtime needs to find the PC of the deferreturn call in a few
places. So for functions that have defer, we record the PC of
deferreturn call in its funcdata.
For very large binaries, the deferreturn call could be made
through a trampoline. The current code of finding deferreturn PC
fails in this case. This CL handles the trampoline as well.
Fixes#39049.
Change-Id: I929be54d6ae436f5294013793217dc2a35f080d4
Reviewed-on: https://go-review.googlesource.com/c/go/+/234105
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
This deletes all sym.Symbol and sym.Reloc references. This is
certainly not complete, and there are more cleanups to do. But I
feel this makes a good first round.
Change-Id: I7621d016957f7ef114be5f0606fcb3ad6aee71c8
Reviewed-on: https://go-review.googlesource.com/c/go/+/234097
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
Use uint32 consistently for local index (this is what the object
file uses).
Use a index, instead of a pointer, to refer to the object file.
This reduces memory usage and GC work.
This reduces some allocations. Linking cmd/compile,
name old alloc/op new alloc/op delta
Loadlib_GC 19.9MB ± 0% 16.9MB ± 0% -15.33% (p=0.008 n=5+5)
name old live-B new live-B delta
Loadlib_GC 12.6M ± 0% 11.3M ± 0% -9.97% (p=0.008 n=5+5)
Change-Id: I20ce60bbb6d31abd2e9e932bdf959e2ae840ab98
Reviewed-on: https://go-review.googlesource.com/c/go/+/233779
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
Remove the loader's PropagateSymbolChangesBackToLoader and
PropagateLoaderChangesToSymbols shim functions. These were used at one
point to enable conversion of phases in the linker that were
"downstream" of loadlibfull -- given the current wavefront position
there's not much point keeping them around.
Change-Id: I3f01f25b70b1b80240369c8f3a10dca89931610f
Reviewed-on: https://go-review.googlesource.com/c/go/+/233817
Run-TryBot: Than McIntosh <thanm@google.com>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
We have the information from auxs. Remove the field, slightly
reduce memory usage.
Change-Id: I3881777cfb40b03d0e2b0e7a326b0738080548b0
Reviewed-on: https://go-review.googlesource.com/c/go/+/233778
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
Now we no longer do loadlibfull on windows.
Change-Id: Ideb015597c28f27538bd50829e089ea728017162
Reviewed-on: https://go-review.googlesource.com/c/go/+/232979
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
We are not going to merge to master until Go 1.16 cycle. The old
object support can go now.
Change-Id: I93e6f584974c7749d0a0c2e7a96def35134dc566
Reviewed-on: https://go-review.googlesource.com/c/go/+/231918
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
Add code to the loader to enforce the invariant that there is only a
single level of 'outer' symbol nesting. That is, if outer(X) = Y, then
outer(Y) is always zero.
Revise foldSubSymbolOffset based on the new invariant, allowing it to
be inlined, and then fix the various "for s.Outer != nil" loops in the
linker to just use an "if" instead of a loop.
Change-Id: Ib895702bc6de52718248f09a5368b84cb2e0a3fa
Reviewed-on: https://go-review.googlesource.com/c/go/+/231137
Run-TryBot: Than McIntosh <thanm@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Convert the part that uses relocations to use loader.ExtReloc
directly. It still uses sym.Symbols for now, but not sym.Relocs.
This reduces some memory usage: linking cmd/compile with external
linking,
name old allocs/op new allocs/op delta
Loadlibfull_GC 52.2MB ± 0% 13.9MB ± 0% -73.40% (p=0.008 n=5+5)
name old live-B new live-B delta
Loadlibfull_GC 75.5M ± 0% 61.9M ± 0% -18.02% (p=0.008 n=5+5)
Change-Id: I317ecbf516063c42b255b2caba310ea6281342d7
Reviewed-on: https://go-review.googlesource.com/c/go/+/231319
Reviewed-by: Jeremy Faller <jeremy@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
Switch the storage mechanism for symbol alignment away from a map and
to a slice of uint8 values per symbol, where value K indicates
alignment 2^K. Intended to help speed up alignment get/set in dodata.
Change-Id: I26416e455c808f697dd0d7f6d2582247ee5c5b40
Reviewed-on: https://go-review.googlesource.com/c/go/+/231220
Run-TryBot: Than McIntosh <thanm@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
Currently, for external relocations, the ExtReloc structure
contains all the fields of the relocation. In fact, many of the
fields are the same with the original relocation. So, instead, we
can just use an index to reference the original relocation and
not expand the fields.
There is one place where we modify relocation type: changing
R_DWARFSECTREF to R_ADDR. Get away with it by changing
downstreams.
It also makes it easier to retrieve the reloc variant.
This reduces some allocation. Linking cmd/compile with external
linking,
name old alloc/op new alloc/op delta
Reloc_GC 34.1MB ± 0% 22.7MB ± 0% -33.30% (p=0.000 n=5+4)
Change-Id: Id08a89ed2aee705296886d3b95014b806a0d55cf
Reviewed-on: https://go-review.googlesource.com/c/go/+/231217
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
We call (or will call) ResolveABIAlias in many places. Doing zero
symbol check everytime is annoying. Fold the condition into
ResolveABIAlias.
Change-Id: I10485fe83b9cce2d19b6bd17dc42176f72dae48b
Reviewed-on: https://go-review.googlesource.com/c/go/+/231046
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
Once the symbol is compressed, we will not need the uncompressed
symbol content. Free its memory.
Linking cmd/compile,
name old live-B new live-B delta
Dwarfcompress_GC 42.7M ± 0% 37.9M ± 0% -11.31% (p=0.008 n=5+5)
Change-Id: Ib6cc73832946d158ff4f5b4f31be9c35ba7cf103
Reviewed-on: https://go-review.googlesource.com/c/go/+/230859
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
After LoadFull, we'll be using sym.Symbols mostly. We still need
the loader information for symbol index mappings and name
lookups, but not much else. Free some memory.
Linking cmd/compile,
name old time/op new time/op delta
Loadlibfull_GC 44.5M ± 0% 35.8M ± 0% -19.66% (p=0.008 n=5+5)
Archive_GC 46.4M ± 0% 37.6M ± 0% -18.89% (p=0.008 n=5+5)
Linking cmd/compile with external linking,
name old time/op new time/op delta
Loadlibfull_GC 82.5M ± 0% 57.4M ± 0% -30.41% (p=0.008 n=5+5)
Archive_GC 86.8M ± 0% 61.7M ± 0% -28.90% (p=0.008 n=5+5)
Change-Id: I6859d488172ef8968918b86de527fbfed6832ebf
Reviewed-on: https://go-review.googlesource.com/c/go/+/230300
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
Support external linking for the new reloc pass as well, and
enable it on AMD64 and 386.
Change-Id: Ia71aec3d7c14e9d661e0748d2e988f29f220d1e1
Reviewed-on: https://go-review.googlesource.com/c/go/+/230308
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
Remove 'Sub' field from sym.Symbol, replacing uses (those downstream of
loadlibfull) with loader method calls.
NB: removing the Outer field will have to wait for now; it is accessed
in archreloc methods that don't have access to link ctxt or loader
currently.
Change-Id: I2abe5906fc169c64b2ab7d5ad213619bea5a17c7
Reviewed-on: https://go-review.googlesource.com/c/go/+/230617
Run-TryBot: Than McIntosh <thanm@google.com>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Only enabled for AMD64 when internal linking for now.
Change-Id: I2aa9ee47c0f7413ea7bbcdd31b8317c14220bba3
Reviewed-on: https://go-review.googlesource.com/c/go/+/230302
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
Remove sym.Symbol 'Unit' field, replacing accesses to the field with
calls into the loader instead.
Change-Id: Ia1abd4c3d93036705dd624a49cb3d9cbe6a5188b
Reviewed-on: https://go-review.googlesource.com/c/go/+/230307
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
Add new get/set methods to the loader for recording the ELF symbol
index for a given loader symbol. These are map-based, since it is
expected that many/most symbols will not need an ELF symbol table
entry.
Change-Id: I1102c3637775515ccc6650118e8b059468a2c3ea
Reviewed-on: https://go-review.googlesource.com/c/go/+/230461
Run-TryBot: Than McIntosh <thanm@google.com>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Remove the 'Gotype' field from sym.Symbol, as it is now no longer
used. Store the loader.Sym for a symbol as a field in sym.Symbol
("SymIdx"). Then remove sym.Symbol 'File' field, and replace the field
accesses in question with calls into the loader instead.
Change-Id: I01c5504425006b8d3fe77fac2b69a86e198c7a5a
Reviewed-on: https://go-review.googlesource.com/c/go/+/230304
Run-TryBot: Than McIntosh <thanm@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
This change is just the mechanical work of moving the wavefront past
address.
Change-Id: I519ec49fa8ba50760c7d23fc084fcd3bb0544546
Reviewed-on: https://go-review.googlesource.com/c/go/+/229700
Run-TryBot: Jeremy Faller <jeremy@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Previous CL introduced index fingerprint in the object files.
This CL implements the second part: checking fingerprint
consistency in the linker when packages are loaded.
Change-Id: I05dd4c4045a65adfd95e77b625d6c75a7a70e4f1
Reviewed-on: https://go-review.googlesource.com/c/go/+/229618
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
The new object files use indices for symbol references, instead
of names. Fundamental to the design, it requires that the
importing and imported packages have consistent view of symbol
indices. The Go command should already ensure this, when using
"go build". But in case it goes wrong, it could lead to obscure
errors like run-time crashes. It would be better to check the
index consistency at build time.
To do that, we add a fingerprint to each object file, which is
a hash of symbol indices. In the object file it records the
fingerprints of all imported packages, as well as its own
fingerprint. At link time, the linker checks that a package's
fingerprint matches the fingerprint recorded in the importing
packages, and issue an error if they don't match.
This CL does the first part: introducing the fingerprint in the
object file, and propagating fingerprints through
importing/exporting by the compiler. It is not yet used by the
linker. Next CL will do.
Change-Id: I0aa372da652e4afb11f2867cb71689a3e3f9966e
Reviewed-on: https://go-review.googlesource.com/c/go/+/229617
Reviewed-by: Austin Clements <austin@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
This patch begins the work of converting the linker's dodata phase to
work with loader APIs. Passes all.bash on linux/amd64, but hasn't been
tested on anything else (more arch-specific code needs to be written).
Use of the new dodata() phase is currently gated by a temporary
command line flag ("-newdodata"), and there is code in the linker's
main routine to insure that we only use the new version for the right
GOOS/GOARCH (currently restricted to ELF + AMD64).
Change-Id: Ied3966677d2a450bc3e0990e0f519b3fceaab806
Reviewed-on: https://go-review.googlesource.com/c/go/+/229706
Run-TryBot: Than McIntosh <thanm@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Move the guts of ctxt.Errorf into loader.Loader, so that we can make
calls to it from functions that have a "*loader.Loader" available but
not a "ctxt *Link". This is needed to start converting hooks like
"adddynrel" in the arch-specific portions of the linker to use loader
APIs.
Change-Id: Ieedd4583b66504be0e77d7f3fbadafe0d2307a69
Reviewed-on: https://go-review.googlesource.com/c/go/+/229497
Run-TryBot: Than McIntosh <thanm@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
Clients may need to invoke the loader.Reloc2.SetType method to reset
the type of a relocation from external flavor to internal flavor,
meaning that the external type add-in needs to be zeroed (this is
needed when adding dynsym entries).
Add a new SymbolBuider method to support mutating the type of a reloc
for an external symbol, so that the external type can be changed as
well (Reloc2 doesn't have access to that). Also add similar methods
for updating target symbol and addend, so as to have a consistent
interface for ext reloc mutation.
Change-Id: I8e26cdae0a0f353019acba5f9c8a0506e3970266
Reviewed-on: https://go-review.googlesource.com/c/go/+/229604
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
Allow for the possibility that a client could call newExtSym(), then
ask for the section of the new sym before SetSectSym is called on it
(check in SymSect for this case).
Change-Id: I7bd78e7b3b7618943705b616f62ea78c4a1b68d0
Reviewed-on: https://go-review.googlesource.com/c/go/+/229603
Reviewed-by: Jeremy Faller <jeremy@golang.org>
The code that runs as a part of loadlibfull converts the linker's
outer/sub state and sets the sym.Symbol AttrSubSymbol if a symbol has
both A) an outer sym, and B) is listed as a sub-symbol by some other
symbol.
Make sure that we have the same logic in the original loader method,
since we need to use it as part of dodata() prior to loadlibfull.
Change-Id: I200adab741d778a6ba821419e8ea131ad19375bc
Reviewed-on: https://go-review.googlesource.com/c/go/+/229440
Run-TryBot: Than McIntosh <thanm@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Change the timing for preprocessing of integer/floating point constant
symbols so that we populate them with content at an earlier stage.
This is needed to allow them can be picked up by the loader-API
version of dodata().
Change-Id: Icf09f4f4b318b4f77e11d4a0f0a9cbecd76a1d6b
Reviewed-on: https://go-review.googlesource.com/c/go/+/229438
Run-TryBot: Than McIntosh <thanm@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
It is no longer needed as we have converted the fieldtrack pass
to using the loader.
Also free loader.Reachparent after we are done with it.
Change-Id: Ibc4b29f282e1e4aea363a1b549755e31f84b0295
Reviewed-on: https://go-review.googlesource.com/c/go/+/229322
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
Currently, we use a dense array to store symbol's sections. The
array element is a *sym.Section, which takes 8 bytes per symbol
on a 64-bit machine. And the array is created upfront.
To reduce memory usage, use a 16-bit index for sections, so we
store 2 bytes per symbol. The array is pointerless, reducing GC
work. Also create the array lazily.
This reduces some memory usage: linking cmd/compile,
name old alloc/op new alloc/op delta
Loadlib_GC 42.1MB ± 0% 36.2MB ± 0% -14.01% (p=0.008 n=5+5)
name old live-B new live-B delta
Loadlib_GC 16.8M ± 0% 15.4M ± 0% -8.36% (p=0.008 n=5+5)
Archive_GC 98.2M ± 0% 97.2M ± 0% -1.02% (p=0.008 n=5+5) # at the end
Change-Id: If8c41eded8859660bca648c5e6fdf5830810fbf6
Reviewed-on: https://go-review.googlesource.com/c/go/+/229306
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
This is more or less a direct translation, to get things going.
There are more things we can do to make it better, especially on
the handling of container symbols.
Change-Id: I11a0087e402be8d42b9d06869385ead531755272
Reviewed-on: https://go-review.googlesource.com/c/go/+/229125
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
deadcode's been completely replaced. Make its death official.
Change-Id: I85f1e3968463f216b8bce2fb7217c3b51641939f
Reviewed-on: https://go-review.googlesource.com/c/go/+/229002
Run-TryBot: Jeremy Faller <jeremy@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
lib.Textp2 is used to assemble the global Textp2. It is not used
after that point. Free some memory.
Slightly reduces allocation: for linking cmd/compile,
Linksetup_GC 1.10MB ± 0% 0.84MB ± 0% -23.43% (p=0.008 n=5+5)
Change-Id: Iec4572e282655306d5ff3e490f8855d479e45acf
Reviewed-on: https://go-review.googlesource.com/c/go/+/228481
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
The types funcAllocInfo and funcInfoSym are no longer referenced.
Fixes#38456.
Change-Id: Icd32445f6027429f4a2781554d2086790ebe5daf
Reviewed-on: https://go-review.googlesource.com/c/go/+/228318
Run-TryBot: Than McIntosh <thanm@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Hoist dwarfGenerateDebugSyms call up out of dodata to before
loadlibfull. This required a couple of small tweaks to the
loader and to loadlibfull.
Change-Id: I48ffb450d2e48b9e55775b73a6debcd27dbb7b9c
Reviewed-on: https://go-review.googlesource.com/c/go/+/228221
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
lib.Textp was used for text address assignment and trampoline
insertion. Now that it has been converted to using the loader,
no need to populate lib.Textp.
Port the logic of canonicalizing dupok symbol's package to the
loader.
unit.Textp was used for DWARF generation, which has also been
converted to using the loader.
Change-Id: I22d4dd30a52a29dd5b1b7b795d43a19f6215e4ac
Reviewed-on: https://go-review.googlesource.com/c/go/+/228140
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
As we have converted the pclntab generation, FuncInfo is not
needed after. No need to load it.
Change-Id: Idcfe4da44dfc94d8d44509d12179b354a2e295e9
Reviewed-on: https://go-review.googlesource.com/c/go/+/228139
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
Remove the loader's AttrContainer method, since it is no longer
needed. All of the code in the linker that used s.Attr.Container() is
now upstream of loadlibfull(), and the code in question now uses local
bitmaps to keep track of container text symbols as opposed to loader
methods.
Change-Id: Iae956d24bef2776e181c3b8208476dcb0b9a2916
Reviewed-on: https://go-review.googlesource.com/c/go/+/227959
Run-TryBot: Than McIntosh <thanm@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>