1. 27 Feb, 2018 16 commits
    • Josh Bleecher Snyder's avatar
      cmd/compile: clean up comments · 15b0d137
      Josh Bleecher Snyder authored
      Follow-up to CL 94256.
      
      Change-Id: I61c450dee5975492192453738f734f772e95c1a5
      Reviewed-on: https://go-review.googlesource.com/97515Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
      15b0d137
    • ChrisALiles's avatar
      cmd/compile: move the SSA local type definitions to a single location · 4f5389c3
      ChrisALiles authored
      Fixes #20304
      
      Change-Id: I52ee02d1602ed7fffc96b27fd60990203c771aaf
      Reviewed-on: https://go-review.googlesource.com/94256
      Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
      TryBot-Result: Gobot Gobot <gobot@golang.org>
      Reviewed-by: default avatarJosh Bleecher Snyder <josharian@gmail.com>
      4f5389c3
    • Ilya Tocar's avatar
      cmd/compile/internal/ssa: combine byte stores on amd64 · 0f2ef0ad
      Ilya Tocar authored
      On amd64 we optimize  encoding/binary.BigEndian.PutUint{16,32,64}
      into bswap + single store, but strangely enough not LittleEndian.PutUint{16,32}.
      We have similar rules, but they use 64-bit shifts everywhere,
      and fail for 16/32-bit case. Add rules that matchLittleEndian.PutUint,
      and relevant tests. Performance results:
      
      LittleEndianPutUint16-6    1.43ns ± 0%    1.07ns ± 0%   -25.17%  (p=0.000 n=9+9)
      LittleEndianPutUint32-6    2.14ns ± 0%    0.94ns ± 0%   -56.07%  (p=0.019 n=6+8)
      
      LittleEndianPutUint16-6  1.40GB/s ± 0%  1.87GB/s ± 0%   +33.24%  (p=0.000 n=9+9)
      LittleEndianPutUint32-6  1.87GB/s ± 0%  4.26GB/s ± 0%  +128.54%  (p=0.000 n=8+8)
      
      Discovered, while looking at ethereum_ethash from community benchmarks
      
      Change-Id: Id86d5443687ecddd2803edf3203dbdd1246f61fe
      Reviewed-on: https://go-review.googlesource.com/95475
      Run-TryBot: Ilya Tocar <ilya.tocar@intel.com>
      TryBot-Result: Gobot Gobot <gobot@golang.org>
      Reviewed-by: default avatarKeith Randall <khr@golang.org>
      0f2ef0ad
    • Matthew Dempsky's avatar
      cmd/compile: fix inlining of constant if statements · d7cd61ce
      Matthew Dempsky authored
      We accidentally overlooked needing to still visit Ninit for OIF
      statements with constant conditions in golang.org/cl/96778.
      
      Fixes #24120.
      
      Change-Id: I5b341913065ff90e1163fb872b9e8d47e2a789d2
      Reviewed-on: https://go-review.googlesource.com/97475
      Run-TryBot: Matthew Dempsky <mdempsky@google.com>
      Reviewed-by: default avatarJosh Bleecher Snyder <josharian@gmail.com>
      TryBot-Result: Gobot Gobot <gobot@golang.org>
      d7cd61ce
    • Heschi Kreinick's avatar
      cmd/link: fix up location lists for dsymutil · 230b0bad
      Heschi Kreinick authored
      LLVM tools, particularly lldb and dsymutil, don't support base address
      selection entries in location lists. When targeting GOOS=darwin,
      mode, have the linker translate location lists to CU-relative form
      instead.
      
      Technically, this isn't necessary when linking internally, as long as
      nobody plans to use anything other than Delve to look at the DWARF. But
      someone might want to use lldb, and it's really confusing when dwarfdump
      shows gibberish for the location entries. The performance cost isn't
      noticeable, so enable it even for internal linking.
      
      Doing this in the linker is a little weird, but it was more expensive in
      the compiler, probably because the compiler is much more stressful to
      the GC. Also, if we decide to only do it for external linking, the
      compiler can't see the link mode.
      
      Benchmark before and after this commit on Mac with -dwarflocationlists=1:
      
      name        old time/op       new time/op       delta
      StdCmd            21.3s ± 1%        21.3s ± 1%    ~     (p=0.310 n=27+27)
      
      Only StdCmd is relevant, because only StdCmd runs the linker. Whatever
      the cost is here, it's not very large.
      
      Change-Id: I200246dedaee4f824966f7551ac95f8d7123d3b1
      Reviewed-on: https://go-review.googlesource.com/89535Reviewed-by: default avatarDavid Chase <drchase@google.com>
      230b0bad
    • Tobias Klauser's avatar
      runtime: simplify walltime/nanotime on linux/{386,amd64} · 5b21bf6f
      Tobias Klauser authored
      Avoid an unnecessary MOVL/MOVQ.
      
      Follow CL 97377
      
      Change-Id: Ic43976d6b0cece3ed455496d18aedd67e0337d3f
      Reviewed-on: https://go-review.googlesource.com/97358
      Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
      Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
      5b21bf6f
    • Tobias Klauser's avatar
      os, syscall: use pipe2 instead of pipe syscall on OpenBSD · 2013ad89
      Tobias Klauser authored
      The pipe2 syscall is part of OpenBSD since version 5.7 and thus exists in
      all officially supported versions.
      
      Follows CL 38426 and CL 94035
      
      Change-Id: I8f93ecbc89664241f1b6b0d069e948776941b1d0
      Reviewed-on: https://go-review.googlesource.com/97356
      Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
      Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
      2013ad89
    • Philip Hofer's avatar
      cmd/compile/internal/ssa: clear branch likeliness in clobberBlock · 81786649
      Philip Hofer authored
      The branchelim pass makes some blocks unreachable, but does not
      remove them from Func.Values. Consequently, ssacheck complains
      when it finds a block with a non-zero likeliness value but no
      successors.
      
      Fixes #24014
      
      Change-Id: I2dcf1d8f4e769a2f363508dab3b11198ead336b6
      Reviewed-on: https://go-review.googlesource.com/96075Reviewed-by: default avatarJosh Bleecher Snyder <josharian@gmail.com>
      Run-TryBot: Philip Hofer <phofer@umich.edu>
      TryBot-Result: Gobot Gobot <gobot@golang.org>
      81786649
    • Josh Bleecher Snyder's avatar
      runtime: improve 386/amd64 systemstack · c5d6c42d
      Josh Bleecher Snyder authored
      Minor improvements, noticed while investigating other things.
      
      Shorten the prologue.
      
      Make branch direction better for static branch prediction;
      the most common case by far is switching stacks (g==curg).
      
      Change-Id: Ib2211d3efecb60446355cda56194221ccb78057d
      Reviewed-on: https://go-review.googlesource.com/97377
      Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
      TryBot-Result: Gobot Gobot <gobot@golang.org>
      Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
      c5d6c42d
    • Joe Tsai's avatar
      go/doc: replace unexported values with underscore if necessary · f399af31
      Joe Tsai authored
      When a var or const declaration contains a mixture of exported and unexported
      identifiers, replace the unexported identifiers with underscore.
      Otherwise, the LHS and the RHS may mismatch or the declaration may mismatch
      with an iota from above.
      
      Fixes #22426
      
      Change-Id: Icd5fb81b4ece647232a9f7d05cb140227091e9cb
      Reviewed-on: https://go-review.googlesource.com/94877
      Run-TryBot: Joe Tsai <thebrokentoaster@gmail.com>
      TryBot-Result: Gobot Gobot <gobot@golang.org>
      Reviewed-by: default avatarRobert Griesemer <gri@golang.org>
      f399af31
    • erifan01's avatar
      math: optimize sinh and cosh · ed6c6c9c
      erifan01 authored
      Improve performance by reducing unnecessary function calls
      
      Benchmarks:
      
      Tme    old time/op  new time/op  delta
      Cosh-8   229ns ± 0%   138ns ± 0%  -39.74%  (p=0.008 n=5+5)
      Sinh-8   231ns ± 0%   139ns ± 0%  -39.83%  (p=0.008 n=5+5)
      
      Change-Id: Icab5485849bbfaafca8429d06b67c558101f4f3c
      Reviewed-on: https://go-review.googlesource.com/85477Reviewed-by: default avatarRobert Griesemer <gri@golang.org>
      ed6c6c9c
    • Josh Bleecher Snyder's avatar
      runtime: short-circuit typedmemmove when dst==src · 486caa26
      Josh Bleecher Snyder authored
      Change-Id: I855268a4c0d07ad602ec90f5da66422d3d87c5f2
      Reviewed-on: https://go-review.googlesource.com/94595
      Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
      Reviewed-by: default avatarKeith Randall <khr@golang.org>
      486caa26
    • Giovanni Bajo's avatar
      cmd/compile: fix bit-test rules for highest bit · 68def820
      Giovanni Bajo authored
      Bit-test rules failed to match when matching the highest bit
      of a word because operands in SSA are signed int64. Fix
      them by treating them as unsigned (and correctly handling
      32-bit operands as well).
      
      Tests will be added in next CL.
      
      Change-Id: I491c4e88e7e2f87e9bb72bd0d9fa5d4025b90736
      Reviewed-on: https://go-review.googlesource.com/94765Reviewed-by: default avatarKeith Randall <khr@golang.org>
      68def820
    • Giovanni Bajo's avatar
      cmd/compile: fold bit masking on bits that have been shifted away · 098208a0
      Giovanni Bajo authored
      Spotted while working on #18943, it triggers once during bootstrap.
      
      Change-Id: Ia4330ccc6395627c233a8eb4dcc0e3e2a770bea7
      Reviewed-on: https://go-review.googlesource.com/94764Reviewed-by: default avatarKeith Randall <khr@golang.org>
      098208a0
    • Chad Rosier's avatar
      cmd/compile/internal/ssa: combine zero stores into larger stores on arm64 · ecd9e8a2
      Chad Rosier authored
      This reduces the go tool binary on arm64 by 12k.
      
      go1 results on Amberwing:
      name                   old time/op    new time/op    delta
      RegexpMatchEasy0_32       249ns ± 0%     249ns ± 0%    ~     (p=0.087 n=10+10)
      RegexpMatchEasy0_1K       584ns ± 0%     584ns ± 0%    ~     (all equal)
      RegexpMatchEasy1_32       246ns ± 0%     246ns ± 0%    ~     (p=1.000 n=10+10)
      RegexpMatchEasy1_1K       806ns ± 0%     806ns ± 0%    ~     (p=0.706 n=10+9)
      RegexpMatchMedium_32      314ns ± 0%     314ns ± 0%    ~     (all equal)
      RegexpMatchMedium_1K     52.1µs ± 0%    52.1µs ± 0%    ~     (p=0.245 n=10+8)
      RegexpMatchHard_32       2.75µs ± 1%    2.75µs ± 1%    ~     (p=0.690 n=10+10)
      RegexpMatchHard_1K       78.9µs ± 0%    78.9µs ± 1%    ~     (p=0.295 n=9+9)
      FmtFprintfEmpty          58.5ns ± 0%    58.5ns ± 0%    ~     (all equal)
      FmtFprintfString          112ns ± 0%     112ns ± 0%    ~     (all equal)
      FmtFprintfInt             117ns ± 0%     116ns ± 0%  -0.85%  (p=0.000 n=10+10)
      FmtFprintfIntInt          181ns ± 0%     181ns ± 0%    ~     (all equal)
      FmtFprintfPrefixedInt     222ns ± 0%     224ns ± 0%  +0.90%  (p=0.000 n=9+10)
      FmtFprintfFloat           318ns ± 1%     322ns ± 0%    ~     (p=0.059 n=10+8)
      FmtManyArgs               736ns ± 1%     735ns ± 0%    ~     (p=0.206 n=9+9)
      Gzip                      437ms ± 0%     436ms ± 0%  -0.25%  (p=0.000 n=10+10)
      HTTPClientServer         89.8µs ± 1%    90.2µs ± 2%    ~     (p=0.393 n=10+10)
      JSONEncode               20.1ms ± 1%    20.2ms ± 1%    ~     (p=0.065 n=9+10)
      JSONDecode               94.2ms ± 1%    93.9ms ± 1%  -0.42%  (p=0.043 n=10+10)
      GobDecode                12.7ms ± 1%    12.8ms ± 2%  +0.94%  (p=0.019 n=10+10)
      GobEncode                12.1ms ± 0%    12.1ms ± 0%    ~     (p=0.052 n=10+10)
      Mandelbrot200            5.06ms ± 0%    5.05ms ± 0%  -0.04%  (p=0.000 n=9+10)
      TimeParse                 450ns ± 3%     446ns ± 0%    ~     (p=0.238 n=10+9)
      TimeFormat                485ns ± 1%     483ns ± 1%    ~     (p=0.073 n=10+10)
      Template                 90.4ms ± 0%    90.7ms ± 0%  +0.29%  (p=0.000 n=8+10)
      GoParse                  6.01ms ± 0%    6.03ms ± 0%  +0.35%  (p=0.000 n=10+10)
      BinaryTree17              11.7s ± 0%     11.7s ± 0%    ~     (p=0.481 n=10+10)
      Revcomp                   669ms ± 0%     669ms ± 0%    ~     (p=0.315 n=10+10)
      Fannkuch11                3.40s ± 0%     3.37s ± 0%  -0.92%  (p=0.000 n=10+10)
      [Geo mean]               67.9µs         67.9µs       +0.02%
      
      name                   old speed      new speed      delta
      RegexpMatchEasy0_32     128MB/s ± 0%   128MB/s ± 0%  -0.08%  (p=0.003 n=8+10)
      RegexpMatchEasy0_1K    1.75GB/s ± 0%  1.75GB/s ± 0%    ~     (p=0.642 n=8+10)
      RegexpMatchEasy1_32     130MB/s ± 0%   130MB/s ± 0%    ~     (p=0.690 n=10+9)
      RegexpMatchEasy1_1K    1.27GB/s ± 0%  1.27GB/s ± 0%    ~     (p=0.661 n=10+9)
      RegexpMatchMedium_32   3.18MB/s ± 0%  3.18MB/s ± 0%    ~     (all equal)
      RegexpMatchMedium_1K   19.7MB/s ± 0%  19.6MB/s ± 0%    ~     (p=0.190 n=10+9)
      RegexpMatchHard_32     11.6MB/s ± 0%  11.6MB/s ± 1%    ~     (p=0.669 n=10+10)
      RegexpMatchHard_1K     13.0MB/s ± 0%  13.0MB/s ± 0%    ~     (p=0.718 n=9+9)
      Gzip                   44.4MB/s ± 0%  44.5MB/s ± 0%  +0.24%  (p=0.000 n=10+10)
      JSONEncode             96.5MB/s ± 1%  96.1MB/s ± 1%    ~     (p=0.065 n=9+10)
      JSONDecode             20.6MB/s ± 1%  20.7MB/s ± 1%  +0.42%  (p=0.041 n=10+10)
      GobDecode              60.6MB/s ± 1%  60.0MB/s ± 2%  -0.92%  (p=0.016 n=10+10)
      GobEncode              63.4MB/s ± 0%  63.6MB/s ± 0%    ~     (p=0.055 n=10+10)
      Template               21.5MB/s ± 0%  21.4MB/s ± 0%  -0.30%  (p=0.000 n=9+10)
      GoParse                9.64MB/s ± 0%  9.61MB/s ± 0%  -0.36%  (p=0.000 n=10+10)
      Revcomp                 380MB/s ± 0%   380MB/s ± 0%    ~     (p=0.323 n=10+10)
      [Geo mean]             56.0MB/s       55.9MB/s       -0.07%
      
      Change-Id: Ia732fa57fbcf4767d72382516d9f16705d177736
      Reviewed-on: https://go-review.googlesource.com/96435
      Run-TryBot: Cherry Zhang <cherryyz@google.com>
      Reviewed-by: default avatarCherry Zhang <cherryyz@google.com>
      ecd9e8a2
    • Josh Bleecher Snyder's avatar
      cmd/compile: tighten after lowering · 3a9e4440
      Josh Bleecher Snyder authored
      Moving tighten after lowering benefits from the removal of values by
      lowering and lowered CSE. It lets us make better decisions about
      which values are rematerializable and which generate flags.
      Empirically, it lowers stack usage (by avoiding spills)
      and generates slightly smaller and faster binaries.
      
      
      Fixes #19853
      Fixes #21041
      
      name        old time/op       new time/op       delta
      Template          195ms ± 4%        193ms ± 4%  -1.33%  (p=0.000 n=92+97)
      Unicode          94.1ms ± 9%       92.5ms ± 8%  -1.66%  (p=0.002 n=97+95)
      GoTypes           572ms ± 5%        566ms ± 7%  -0.92%  (p=0.001 n=95+98)
      Compiler          2.56s ± 4%        2.52s ± 3%  -1.41%  (p=0.000 n=94+97)
      SSA               6.52s ± 2%        6.47s ± 3%  -0.82%  (p=0.000 n=96+94)
      Flate             117ms ± 5%        116ms ± 7%  -0.72%  (p=0.018 n=97+97)
      GoParser          148ms ± 6%        146ms ± 4%  -0.97%  (p=0.002 n=98+95)
      Reflect           370ms ± 7%        363ms ± 6%  -1.79%  (p=0.000 n=99+98)
      Tar               175ms ± 6%        173ms ± 6%  -1.11%  (p=0.001 n=94+95)
      XML               204ms ± 6%        201ms ± 5%  -1.49%  (p=0.000 n=97+96)
      [Geo mean]        363ms             359ms       -1.22%
      
      name        old user-time/op  new user-time/op  delta
      Template          251ms ± 5%        245ms ± 5%  -2.40%  (p=0.000 n=97+93)
      Unicode           131ms ±10%        128ms ± 9%  -1.93%  (p=0.001 n=100+99)
      GoTypes           760ms ± 4%        752ms ± 4%  -0.96%  (p=0.000 n=97+95)
      Compiler          3.51s ± 3%        3.48s ± 2%  -1.04%  (p=0.000 n=96+95)
      SSA               9.57s ± 4%        9.52s ± 2%  -0.50%  (p=0.004 n=97+96)
      Flate             149ms ± 6%        147ms ± 6%  -1.46%  (p=0.000 n=98+96)
      GoParser          184ms ± 5%        181ms ± 7%  -1.84%  (p=0.000 n=98+97)
      Reflect           469ms ± 6%        461ms ± 6%  -1.69%  (p=0.000 n=100+98)
      Tar               219ms ± 8%        217ms ± 7%  -0.90%  (p=0.035 n=96+96)
      XML               255ms ± 5%        251ms ± 6%  -1.48%  (p=0.000 n=98+98)
      [Geo mean]        476ms             469ms       -1.42%
      
      name        old alloc/op      new alloc/op      delta
      Template         37.8MB ± 0%       37.8MB ± 0%  -0.17%  (p=0.000 n=100+100)
      Unicode          28.8MB ± 0%       28.8MB ± 0%  -0.02%  (p=0.000 n=100+95)
      GoTypes           112MB ± 0%        112MB ± 0%  -0.20%  (p=0.000 n=100+97)
      Compiler          466MB ± 0%        464MB ± 0%  -0.27%  (p=0.000 n=100+100)
      SSA              1.49GB ± 0%       1.49GB ± 0%  -0.08%  (p=0.000 n=100+99)
      Flate            24.4MB ± 0%       24.3MB ± 0%  -0.25%  (p=0.000 n=98+99)
      GoParser         30.7MB ± 0%       30.6MB ± 0%  -0.26%  (p=0.000 n=99+100)
      Reflect          76.4MB ± 0%       76.4MB ± 0%    ~     (p=0.253 n=100+100)
      Tar              38.9MB ± 0%       38.8MB ± 0%  -0.20%  (p=0.000 n=100+97)
      XML              41.5MB ± 0%       41.4MB ± 0%  -0.19%  (p=0.000 n=100+98)
      [Geo mean]       77.5MB            77.4MB       -0.16%
      
      name        old allocs/op     new allocs/op     delta
      Template           381k ± 0%         381k ± 0%  -0.15%  (p=0.000 n=100+100)
      Unicode            342k ± 0%         342k ± 0%  -0.01%  (p=0.000 n=100+98)
      GoTypes           1.19M ± 0%        1.18M ± 0%  -0.24%  (p=0.000 n=100+100)
      Compiler          4.52M ± 0%        4.50M ± 0%  -0.29%  (p=0.000 n=100+100)
      SSA               12.3M ± 0%        12.3M ± 0%  -0.11%  (p=0.000 n=100+100)
      Flate              234k ± 0%         234k ± 0%  -0.26%  (p=0.000 n=99+96)
      GoParser           318k ± 0%         317k ± 0%  -0.21%  (p=0.000 n=99+100)
      Reflect            974k ± 0%         974k ± 0%  -0.03%  (p=0.000 n=100+100)
      Tar                392k ± 0%         391k ± 0%  -0.17%  (p=0.000 n=100+99)
      XML                404k ± 0%         403k ± 0%  -0.24%  (p=0.000 n=99+99)
      [Geo mean]         794k              792k       -0.17%
      
      name        old object-bytes  new object-bytes  delta
      Template          393kB ± 0%        392kB ± 0%  -0.19%  (p=0.008 n=5+5)
      Unicode           207kB ± 0%        207kB ± 0%    ~     (all equal)
      GoTypes          1.23MB ± 0%       1.22MB ± 0%  -0.11%  (p=0.008 n=5+5)
      Compiler         4.34MB ± 0%       4.33MB ± 0%  -0.15%  (p=0.008 n=5+5)
      SSA              9.85MB ± 0%       9.85MB ± 0%  -0.07%  (p=0.008 n=5+5)
      Flate             235kB ± 0%        234kB ± 0%  -0.59%  (p=0.008 n=5+5)
      GoParser          297kB ± 0%        296kB ± 0%  -0.22%  (p=0.008 n=5+5)
      Reflect          1.03MB ± 0%       1.03MB ± 0%  -0.00%  (p=0.008 n=5+5)
      Tar               332kB ± 0%        331kB ± 0%  -0.15%  (p=0.008 n=5+5)
      XML               413kB ± 0%        412kB ± 0%  -0.19%  (p=0.008 n=5+5)
      [Geo mean]        728kB             727kB       -0.17%
      
      Change-Id: I9b5cdb668ed102a001897a05e833105acba220a2
      Reviewed-on: https://go-review.googlesource.com/95995
      Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
      TryBot-Result: Gobot Gobot <gobot@golang.org>
      Reviewed-by: default avatarKeith Randall <khr@golang.org>
      3a9e4440
  2. 26 Feb, 2018 22 commits
  3. 25 Feb, 2018 1 commit
  4. 24 Feb, 2018 1 commit
    • Lubomir I. Ivanov (VMware)'s avatar
      os/user: obtain a user home path on Windows · 7a218942
      Lubomir I. Ivanov (VMware) authored
      newUserFromSid() is extended so that the retriaval of the user home
      path based on a user SID becomes possible.
      
      (1) The primary method it uses is to lookup the Windows registry for
      the following key:
        HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\[SID]
      
      If the key does not exist the user might not have logged in yet.
      If (1) fails it falls back to (2)
      
      (2) The second method the function uses is to look at the default home
      path for users (e.g. WINAPI's GetProfilesDirectory()) and append
      the username to that. The procedure is in the lines of:
        c:\Users + \ + <username>
      
      The function newUser() now requires the following arguments:
        uid, gid, dir, username, domain
      This is done to avoid multiple calls to usid.String() and
      usid.LookupAccount("") in the case of a newUserFromSid()
      call stack.
      
      The functions current() and newUserFromSid() both call newUser()
      supplying the arguments in question. The helpers
      lookupUsernameAndDomain() and findHomeDirInRegistry() are
      added.
      
      This commit also updates:
      - go/build/deps_test.go, so that the test now includes the
      "internal/syscall/windows/registry" import.
      - os/user/user_test.go, so that User.HomeDir is tested on Windows.
      
      GitHub-Last-Rev: 25423e2a3820121f4c42321e7a77a3977f409724
      GitHub-Pull-Request: golang/go#23822
      Change-Id: I6c3ad1c4ce3e7bc0d1add024951711f615b84ee5
      Reviewed-on: https://go-review.googlesource.com/93935Reviewed-by: default avatarAlex Brainman <alex.brainman@gmail.com>
      Run-TryBot: Alex Brainman <alex.brainman@gmail.com>
      TryBot-Result: Gobot Gobot <gobot@golang.org>
      7a218942