Age | Commit message (Collapse) | Author |
|
The assembly is mostly a straightforward conversion of the
equivalent arm assembly.
This CL is part of a stack adding windows/arm64
support (#36439), intended to land in the Go 1.17 cycle.
Change-Id: I61b15d712ade4d3a7285c7680de8e0987aacba10
Reviewed-on: https://go-review.googlesource.com/c/go/+/288828
Trust: Russ Cox <rsc@golang.org>
Trust: Jason A. Donenfeld <Jason@zx2c4.com>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
|
|
memclrNoHeapPointers is the underlying implementation of
typedmemclr and memclrHasPointers, so it still needs to write
pointer-aligned words atomically. Document this requirement.
Updates #41428.
Change-Id: Ice00dee5de7a96a50e51ff019fcef069e8a8406a
Reviewed-on: https://go-review.googlesource.com/c/go/+/287692
Trust: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
|
|
Change-Id: I6940a4c747f2da871263afa6a4e3386395d5cf54
Reviewed-on: https://go-review.googlesource.com/c/go/+/180839
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
|
|
The function signatures in the comments used a C-like style. Using
Go function signatures is cleaner.
Change-Id: I1a093ed8fe5df59f3697c613cf3fce58bba4f5c1
Reviewed-on: https://go-review.googlesource.com/113876
Run-TryBot: Michael Munday <mike.munday@ibm.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
|
|
Improve runtime memclr_arm64.s using ZVA feature to zero out memory when n
is at least 64 bytes.
Also add DCZID_EL0 system register to use in MRS instruction.
Benchmark results of runtime/Memclr on Amberwing:
name old time/op new time/op delta
Memclr/5 12.7ns ± 0% 12.7ns ± 0% ~ (all equal)
Memclr/16 12.7ns ± 0% 12.2ns ± 1% -4.13% (p=0.000 n=7+8)
Memclr/64 14.0ns ± 0% 14.6ns ± 1% +4.29% (p=0.000 n=7+8)
Memclr/256 23.7ns ± 0% 25.7ns ± 0% +8.44% (p=0.000 n=8+7)
Memclr/4096 204ns ± 0% 74ns ± 0% -63.71% (p=0.000 n=8+8)
Memclr/65536 2.89µs ± 0% 0.84µs ± 0% -70.91% (p=0.000 n=8+8)
Memclr/1M 45.9µs ± 0% 17.0µs ± 0% -62.88% (p=0.000 n=8+8)
Memclr/4M 184µs ± 0% 77µs ± 4% -57.94% (p=0.001 n=6+8)
Memclr/8M 367µs ± 0% 144µs ± 1% -60.72% (p=0.000 n=7+8)
Memclr/16M 734µs ± 0% 293µs ± 1% -60.09% (p=0.000 n=8+8)
Memclr/64M 2.94ms ± 0% 1.23ms ± 0% -58.06% (p=0.000 n=7+8)
GoMemclr/5 8.00ns ± 0% 8.79ns ± 0% +9.83% (p=0.000 n=8+8)
GoMemclr/16 8.00ns ± 0% 7.60ns ± 0% -5.00% (p=0.000 n=8+8)
GoMemclr/64 10.8ns ± 0% 10.4ns ± 0% -3.70% (p=0.000 n=8+8)
GoMemclr/256 20.4ns ± 0% 21.2ns ± 0% +3.92% (p=0.000 n=8+8)
name old speed new speed delta
Memclr/5 394MB/s ± 0% 393MB/s ± 0% -0.28% (p=0.006 n=8+8)
Memclr/16 1.26GB/s ± 0% 1.31GB/s ± 1% +4.07% (p=0.000 n=7+8)
Memclr/64 4.57GB/s ± 0% 4.39GB/s ± 2% -3.91% (p=0.000 n=7+8)
Memclr/256 10.8GB/s ± 0% 10.0GB/s ± 0% -7.95% (p=0.001 n=7+6)
Memclr/4096 20.1GB/s ± 0% 55.3GB/s ± 0% +175.46% (p=0.000 n=8+8)
Memclr/65536 22.6GB/s ± 0% 77.8GB/s ± 0% +243.63% (p=0.000 n=7+8)
Memclr/1M 22.8GB/s ± 0% 61.5GB/s ± 0% +169.38% (p=0.000 n=8+8)
Memclr/4M 22.8GB/s ± 0% 54.3GB/s ± 4% +137.85% (p=0.001 n=6+8)
Memclr/8M 22.8GB/s ± 0% 58.1GB/s ± 1% +154.56% (p=0.000 n=7+8)
Memclr/16M 22.8GB/s ± 0% 57.2GB/s ± 1% +150.54% (p=0.000 n=8+8)
Memclr/64M 22.8GB/s ± 0% 54.4GB/s ± 0% +138.42% (p=0.000 n=7+8)
GoMemclr/5 625MB/s ± 0% 569MB/s ± 0% -8.90% (p=0.000 n=7+8)
GoMemclr/16 2.00GB/s ± 0% 2.10GB/s ± 0% +5.26% (p=0.000 n=8+8)
GoMemclr/64 5.92GB/s ± 0% 6.15GB/s ± 0% +3.83% (p=0.000 n=7+8)
GoMemclr/256 12.5GB/s ± 0% 12.1GB/s ± 0% -3.77% (p=0.000 n=8+7)
Benchmark results of runtime/Memclr on Amberwing without ZVA:
name old time/op new time/op delta
Memclr/5 12.7ns ± 0% 12.8ns ± 0% +0.79% (p=0.008 n=5+5)
Memclr/16 12.7ns ± 0% 12.7ns ± 0% ~ (p=0.444 n=5+5)
Memclr/64 14.0ns ± 0% 14.4ns ± 0% +2.86% (p=0.008 n=5+5)
Memclr/256 23.7ns ± 1% 19.2ns ± 0% -19.06% (p=0.008 n=5+5)
Memclr/4096 203ns ± 0% 119ns ± 0% -41.38% (p=0.008 n=5+5)
Memclr/65536 2.89µs ± 0% 1.66µs ± 0% -42.76% (p=0.008 n=5+5)
Memclr/1M 45.9µs ± 0% 26.2µs ± 0% -42.82% (p=0.008 n=5+5)
Memclr/4M 184µs ± 0% 105µs ± 0% -42.81% (p=0.008 n=5+5)
Memclr/8M 367µs ± 0% 210µs ± 0% -42.76% (p=0.008 n=5+5)
Memclr/16M 734µs ± 0% 420µs ± 0% -42.74% (p=0.008 n=5+5)
Memclr/64M 2.94ms ± 0% 1.69ms ± 0% -42.46% (p=0.008 n=5+5)
GoMemclr/5 8.00ns ± 0% 8.40ns ± 0% +5.00% (p=0.008 n=5+5)
GoMemclr/16 8.00ns ± 0% 8.40ns ± 0% +5.00% (p=0.008 n=5+5)
GoMemclr/64 10.8ns ± 0% 9.6ns ± 0% -11.02% (p=0.008 n=5+5)
GoMemclr/256 20.4ns ± 0% 17.2ns ± 0% -15.69% (p=0.008 n=5+5)
name old speed new speed delta
Memclr/5 393MB/s ± 0% 391MB/s ± 0% -0.64% (p=0.008 n=5+5)
Memclr/16 1.26GB/s ± 0% 1.26GB/s ± 0% -0.55% (p=0.008 n=5+5)
Memclr/64 4.57GB/s ± 0% 4.44GB/s ± 0% -2.79% (p=0.008 n=5+5)
Memclr/256 10.8GB/s ± 0% 13.3GB/s ± 0% +23.07% (p=0.016 n=4+5)
Memclr/4096 20.1GB/s ± 0% 34.3GB/s ± 0% +70.91% (p=0.008 n=5+5)
Memclr/65536 22.7GB/s ± 0% 39.6GB/s ± 0% +74.65% (p=0.008 n=5+5)
Memclr/1M 22.8GB/s ± 0% 40.0GB/s ± 0% +74.88% (p=0.008 n=5+5)
Memclr/4M 22.8GB/s ± 0% 39.9GB/s ± 0% +74.84% (p=0.008 n=5+5)
Memclr/8M 22.9GB/s ± 0% 39.9GB/s ± 0% +74.71% (p=0.008 n=5+5)
Memclr/16M 22.9GB/s ± 0% 39.9GB/s ± 0% +74.64% (p=0.008 n=5+5)
Memclr/64M 22.8GB/s ± 0% 39.7GB/s ± 0% +73.79% (p=0.008 n=5+5)
GoMemclr/5 625MB/s ± 0% 595MB/s ± 0% -4.77% (p=0.000 n=4+5)
GoMemclr/16 2.00GB/s ± 0% 1.90GB/s ± 0% -4.77% (p=0.008 n=5+5)
GoMemclr/64 5.92GB/s ± 0% 6.66GB/s ± 0% +12.48% (p=0.016 n=4+5)
GoMemclr/256 12.5GB/s ± 0% 14.9GB/s ± 0% +18.95% (p=0.008 n=5+5)
Fixes #22948
Change-Id: Iaae4e22391e25b54d299821bb7f8a81ac3986b93
Reviewed-on: https://go-review.googlesource.com/82055
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
|
|
Update runtime asm_arm64.s and memclr_arm64.s to improve performance by using
SIMD instructions to do more in parallel. It shows improvement on bytes, html
and go1 benchmarks (particualrly regexp, which uses IndexByte frequently).
Benchmark results of bytes:
name old time/op new time/op delta
IndexByte/10-8 28.5ns ± 0% 19.5ns ± 0% -31.58% (p=0.000 n=10+10)
IndexByte/32-8 52.6ns ± 0% 19.0ns ± 0% -63.88% (p=0.000 n=10+10)
IndexByte/4K-8 4.12µs ± 0% 0.49µs ± 0% -88.16% (p=0.000 n=10+10)
IndexByte/4M-8 4.29ms ± 1% 0.70ms ±26% -83.65% (p=0.000 n=10+10)
IndexByte/64M-8 69.7ms ± 0% 16.0ms ± 0% -76.97% (p=0.000 n=9+10)
IndexBytePortable/10-8 34.0ns ± 0% 34.0ns ± 0% ~ (all equal)
IndexBytePortable/32-8 66.1ns ± 0% 66.1ns ± 0% ~ (p=0.471 n=9+9)
IndexBytePortable/4K-8 6.17µs ± 0% 6.17µs ± 0% ~ (all equal)
IndexBytePortable/4M-8 6.33ms ± 0% 6.35ms ± 0% +0.21% (p=0.002 n=10+9)
IndexBytePortable/64M-8 103ms ± 0% 103ms ± 0% +0.01% (p=0.017 n=9+10)
name old speed new speed delta
IndexByte/10-8 351MB/s ± 0% 512MB/s ± 0% +46.14% (p=0.000 n=9+10)
IndexByte/32-8 609MB/s ± 0% 1683MB/s ± 0% +176.40% (p=0.000 n=10+10)
IndexByte/4K-8 994MB/s ± 0% 8378MB/s ± 0% +742.75% (p=0.000 n=10+10)
IndexByte/4M-8 977MB/s ± 1% 6149MB/s ±32% +529.29% (p=0.000 n=10+10)
IndexByte/64M-8 963MB/s ± 0% 4182MB/s ± 0% +334.29% (p=0.000 n=9+10)
IndexBytePortable/10-8 294MB/s ± 0% 294MB/s ± 0% +0.17% (p=0.000 n=8+8)
IndexBytePortable/32-8 484MB/s ± 0% 484MB/s ± 0% ~ (p=0.877 n=9+9)
IndexBytePortable/4K-8 664MB/s ± 0% 664MB/s ± 0% ~ (p=0.242 n=8+9)
IndexBytePortable/4M-8 662MB/s ± 0% 661MB/s ± 0% -0.21% (p=0.002 n=10+9)
IndexBytePortable/64M-8 652MB/s ± 0% 652MB/s ± 0% ~ (p=0.065 n=10+10)
Benchmark results of html:
name old time/op new time/op delta
Escape-8 62.0µs ± 1% 61.0µs ± 1% -1.69% (p=0.000 n=9+10)
EscapeNone-8 10.2µs ± 0% 10.2µs ± 0% -0.09% (p=0.022 n=9+10)
Unescape-8 71.9µs ± 0% 68.7µs ± 0% -4.35% (p=0.000 n=10+10)
UnescapeNone-8 4.03µs ± 0% 0.48µs ± 0% -88.08% (p=0.000 n=10+10)
UnescapeSparse-8 10.7µs ± 2% 7.1µs ± 3% -33.91% (p=0.000 n=10+10)
UnescapeDense-8 53.2µs ± 1% 53.5µs ± 1% ~ (p=0.143 n=10+10)
Benchmark results of go1:
name old time/op new time/op delta
BinaryTree17-8 6.53s ± 0% 6.48s ± 2% ~ (p=0.190 n=4+5)
Fannkuch11-8 6.35s ± 1% 6.35s ± 0% ~ (p=1.000 n=5+5)
FmtFprintfEmpty-8 108ns ± 1% 101ns ± 2% -6.32% (p=0.008 n=5+5)
FmtFprintfString-8 172ns ± 1% 182ns ± 2% +5.70% (p=0.008 n=5+5)
FmtFprintfInt-8 207ns ± 0% 207ns ± 0% ~ (p=0.444 n=5+5)
FmtFprintfIntInt-8 277ns ± 1% 276ns ± 1% ~ (p=0.873 n=5+5)
FmtFprintfPrefixedInt-8 386ns ± 0% 382ns ± 1% -1.04% (p=0.024 n=5+5)
FmtFprintfFloat-8 492ns ± 0% 492ns ± 1% ~ (p=0.571 n=4+5)
FmtManyArgs-8 1.32µs ± 1% 1.33µs ± 0% ~ (p=0.087 n=5+5)
GobDecode-8 16.8ms ± 2% 16.7ms ± 1% ~ (p=1.000 n=5+5)
GobEncode-8 14.1ms ± 1% 14.0ms ± 1% ~ (p=0.056 n=5+5)
Gzip-8 788ms ± 0% 802ms ± 0% +1.71% (p=0.008 n=5+5)
Gunzip-8 83.6ms ± 0% 83.9ms ± 0% +0.40% (p=0.008 n=5+5)
HTTPClientServer-8 120µs ± 0% 120µs ± 1% ~ (p=0.548 n=5+5)
JSONEncode-8 33.2ms ± 0% 33.0ms ± 1% -0.71% (p=0.008 n=5+5)
JSONDecode-8 152ms ± 1% 152ms ± 1% ~ (p=1.000 n=5+5)
Mandelbrot200-8 10.0ms ± 0% 10.0ms ± 0% -0.05% (p=0.008 n=5+5)
GoParse-8 7.97ms ± 0% 7.98ms ± 0% ~ (p=0.690 n=5+5)
RegexpMatchEasy0_32-8 233ns ± 1% 206ns ± 0% -11.44% (p=0.016 n=5+4)
RegexpMatchEasy0_1K-8 1.86µs ± 0% 0.77µs ± 1% -58.54% (p=0.008 n=5+5)
RegexpMatchEasy1_32-8 250ns ± 0% 205ns ± 0% -18.07% (p=0.008 n=5+5)
RegexpMatchEasy1_1K-8 2.28µs ± 0% 1.11µs ± 0% -51.09% (p=0.029 n=4+4)
RegexpMatchMedium_32-8 332ns ± 1% 301ns ± 2% -9.45% (p=0.008 n=5+5)
RegexpMatchMedium_1K-8 85.5µs ± 2% 78.8µs ± 0% -7.83% (p=0.008 n=5+5)
RegexpMatchHard_32-8 4.34µs ± 1% 4.27µs ± 0% -1.49% (p=0.008 n=5+5)
RegexpMatchHard_1K-8 130µs ± 1% 127µs ± 0% -2.53% (p=0.008 n=5+5)
Revcomp-8 1.35s ± 1% 1.13s ± 1% -16.17% (p=0.008 n=5+5)
Template-8 160ms ± 2% 162ms ± 2% ~ (p=0.222 n=5+5)
TimeParse-8 795ns ± 2% 778ns ± 1% ~ (p=0.095 n=5+5)
TimeFormat-8 782ns ± 0% 786ns ± 1% +0.59% (p=0.040 n=5+5)
name old speed new speed delta
GobDecode-8 45.8MB/s ± 2% 45.9MB/s ± 1% ~ (p=1.000 n=5+5)
GobEncode-8 54.3MB/s ± 1% 55.0MB/s ± 1% ~ (p=0.056 n=5+5)
Gzip-8 24.6MB/s ± 0% 24.2MB/s ± 0% -1.69% (p=0.008 n=5+5)
Gunzip-8 232MB/s ± 0% 231MB/s ± 0% -0.40% (p=0.008 n=5+5)
JSONEncode-8 58.4MB/s ± 0% 58.8MB/s ± 1% +0.71% (p=0.008 n=5+5)
JSONDecode-8 12.8MB/s ± 1% 12.8MB/s ± 1% ~ (p=1.000 n=5+5)
GoParse-8 7.27MB/s ± 0% 7.26MB/s ± 0% ~ (p=0.762 n=5+5)
RegexpMatchEasy0_32-8 137MB/s ± 1% 155MB/s ± 0% +12.93% (p=0.008 n=5+5)
RegexpMatchEasy0_1K-8 551MB/s ± 0% 1329MB/s ± 1% +141.11% (p=0.008 n=5+5)
RegexpMatchEasy1_32-8 128MB/s ± 0% 156MB/s ± 0% +22.00% (p=0.008 n=5+5)
RegexpMatchEasy1_1K-8 449MB/s ± 0% 920MB/s ± 0% +104.68% (p=0.016 n=4+5)
RegexpMatchMedium_32-8 3.00MB/s ± 0% 3.32MB/s ± 2% +10.60% (p=0.016 n=4+5)
RegexpMatchMedium_1K-8 12.0MB/s ± 2% 13.0MB/s ± 0% +8.48% (p=0.008 n=5+5)
RegexpMatchHard_32-8 7.38MB/s ± 1% 7.49MB/s ± 0% +1.49% (p=0.008 n=5+5)
RegexpMatchHard_1K-8 7.88MB/s ± 1% 8.08MB/s ± 0% +2.59% (p=0.008 n=5+5)
Revcomp-8 188MB/s ± 1% 224MB/s ± 1% +19.29% (p=0.008 n=5+5)
Template-8 12.2MB/s ± 2% 12.0MB/s ± 2% ~ (p=0.206 n=5+5)
Change-Id: I94116620a287d173a6f60510684362e500f54887
Reviewed-on: https://go-review.googlesource.com/33597
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
|
|
Since barrier-less memclr is only safe in very narrow circumstances,
this commit renames memclr to avoid accidentally calling memclr on
typed memory. This can cause subtle, non-deterministic bugs, so it's
worth some effort to prevent. In the near term, this will also prevent
bugs creeping in from any concurrent CLs that add calls to memclr; if
this happens, whichever patch hits master second will fail to compile.
This also adds the other new memclr variants to the compiler's
builtin.go to minimize the churn on that binary blob. We'll use these
in future commits.
Updates #17503.
Change-Id: I00eead049f5bd35ca107ea525966831f3d1ed9ca
Reviewed-on: https://go-review.googlesource.com/31369
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Rick Hudson <rlh@golang.org>
|
|
they can
Not only is this an obvious optimization:
benchmark old MB/s new MB/s speedup
BenchmarkMemmove1-4 35.35 29.65 0.84x
BenchmarkMemmove2-4 63.78 52.53 0.82x
BenchmarkMemmove3-4 89.72 73.96 0.82x
BenchmarkMemmove4-4 109.94 95.73 0.87x
BenchmarkMemmove5-4 127.60 112.80 0.88x
BenchmarkMemmove6-4 143.59 126.67 0.88x
BenchmarkMemmove7-4 157.90 138.92 0.88x
BenchmarkMemmove8-4 167.18 231.81 1.39x
BenchmarkMemmove9-4 175.23 252.07 1.44x
BenchmarkMemmove10-4 165.68 261.10 1.58x
BenchmarkMemmove11-4 174.43 263.31 1.51x
BenchmarkMemmove12-4 180.76 267.56 1.48x
BenchmarkMemmove13-4 189.06 284.93 1.51x
BenchmarkMemmove14-4 186.31 284.72 1.53x
BenchmarkMemmove15-4 195.75 281.62 1.44x
BenchmarkMemmove16-4 202.96 439.23 2.16x
BenchmarkMemmove32-4 264.77 775.77 2.93x
BenchmarkMemmove64-4 306.81 1209.64 3.94x
BenchmarkMemmove128-4 357.03 1515.41 4.24x
BenchmarkMemmove256-4 380.77 2066.01 5.43x
BenchmarkMemmove512-4 385.05 2556.45 6.64x
BenchmarkMemmove1024-4 381.23 2804.10 7.36x
BenchmarkMemmove2048-4 379.06 2814.83 7.43x
BenchmarkMemmove4096-4 387.43 3064.96 7.91x
BenchmarkMemmoveUnaligned1-4 28.91 25.40 0.88x
BenchmarkMemmoveUnaligned2-4 56.13 47.56 0.85x
BenchmarkMemmoveUnaligned3-4 74.32 69.31 0.93x
BenchmarkMemmoveUnaligned4-4 97.02 83.58 0.86x
BenchmarkMemmoveUnaligned5-4 110.17 103.62 0.94x
BenchmarkMemmoveUnaligned6-4 124.95 113.26 0.91x
BenchmarkMemmoveUnaligned7-4 142.37 130.82 0.92x
BenchmarkMemmoveUnaligned8-4 151.20 205.64 1.36x
BenchmarkMemmoveUnaligned9-4 166.97 215.42 1.29x
BenchmarkMemmoveUnaligned10-4 148.49 221.22 1.49x
BenchmarkMemmoveUnaligned11-4 159.47 239.57 1.50x
BenchmarkMemmoveUnaligned12-4 163.52 247.32 1.51x
BenchmarkMemmoveUnaligned13-4 167.55 256.54 1.53x
BenchmarkMemmoveUnaligned14-4 175.12 251.03 1.43x
BenchmarkMemmoveUnaligned15-4 192.10 267.13 1.39x
BenchmarkMemmoveUnaligned16-4 190.76 378.87 1.99x
BenchmarkMemmoveUnaligned32-4 259.02 562.98 2.17x
BenchmarkMemmoveUnaligned64-4 317.72 842.44 2.65x
BenchmarkMemmoveUnaligned128-4 355.43 1274.49 3.59x
BenchmarkMemmoveUnaligned256-4 378.17 1815.74 4.80x
BenchmarkMemmoveUnaligned512-4 362.15 2180.81 6.02x
BenchmarkMemmoveUnaligned1024-4 376.07 2453.58 6.52x
BenchmarkMemmoveUnaligned2048-4 381.66 2568.32 6.73x
BenchmarkMemmoveUnaligned4096-4 398.51 2669.36 6.70x
BenchmarkMemclr5-4 113.83 107.93 0.95x
BenchmarkMemclr16-4 223.84 389.63 1.74x
BenchmarkMemclr64-4 421.99 1209.58 2.87x
BenchmarkMemclr256-4 525.94 2411.58 4.59x
BenchmarkMemclr4096-4 581.66 4372.20 7.52x
BenchmarkMemclr65536-4 565.84 4747.48 8.39x
BenchmarkGoMemclr5-4 194.63 160.31 0.82x
BenchmarkGoMemclr16-4 295.30 630.07 2.13x
BenchmarkGoMemclr64-4 480.24 1884.03 3.92x
BenchmarkGoMemclr256-4 540.23 2926.49 5.42x
but it turns out that it's necessary to avoid the GC seeing partially written
pointers.
It's of course possible to be more sophisticated (using ldp/stp to move 16
bytes at a time in the core loop and unrolling the tail copying loops being
the obvious ideas) but I wanted something simple and (reasonably) obviously
correct.
Fixes #12552
Change-Id: Iaeaf8a812cd06f4747ba2f792de1ded738890735
Reviewed-on: https://go-review.googlesource.com/14813
Reviewed-by: Austin Clements <austin@google.com>
|
|
Change-Id: Ibda6a5bedaff57fd161d63fc04ad260931d34413
Reviewed-on: https://go-review.googlesource.com/7142
Reviewed-by: Russ Cox <rsc@golang.org>
|