go/src/cmd/compile/internal/gc/subr.go

1929 lines
45 KiB
Go
Raw Normal View History

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package gc
import (
"cmd/compile/internal/types"
"cmd/internal/objabi"
"cmd/internal/src"
"crypto/md5"
"encoding/binary"
"fmt"
"os"
"runtime/debug"
"sort"
"strconv"
"strings"
cmd/compile: add initial backend concurrency support This CL adds initial support for concurrent backend compilation. BACKGROUND The compiler currently consists (very roughly) of the following phases: 1. Initialization. 2. Lexing and parsing into the cmd/compile/internal/syntax AST. 3. Translation into the cmd/compile/internal/gc AST. 4. Some gc AST passes: typechecking, escape analysis, inlining, closure handling, expression evaluation ordering (order.go), and some lowering and optimization (walk.go). 5. Translation into the cmd/compile/internal/ssa SSA form. 6. Optimization and lowering of SSA form. 7. Translation from SSA form to assembler instructions. 8. Translation from assembler instructions to machine code. 9. Writing lots of output: machine code, DWARF symbols, type and reflection info, export data. Phase 2 was already concurrent as of Go 1.8. Phase 3 is planned for eventual removal; we hope to go straight from syntax AST to SSA. Phases 5–8 are per-function; this CL adds support for processing multiple functions concurrently. The slowest phases in the compiler are 5 and 6, so this offers the opportunity for some good speed-ups. Unfortunately, it's not quite that straightforward. In the current compiler, the latter parts of phase 4 (order, walk) are done function-at-a-time as needed. Making order and walk concurrency-safe proved hard, and they're not particularly slow, so there wasn't much reward. To enable phases 5–8 to be done concurrently, when concurrent backend compilation is requested, we complete phase 4 for all functions before starting later phases for any functions. Also, in reality, we automatically generate new functions in phase 9, such as method wrappers and equality and has routines. Those new functions then go through phases 4–8. This CL disables concurrent backend compilation after the first, big, user-provided batch of functions has been compiled. This is done to keep things simple, and because the autogenerated functions tend to be small, few, simple, and fast to compile. USAGE Concurrent backend compilation still defaults to off. To set the number of functions that may be backend-compiled concurrently, use the compiler flag -c. In future work, cmd/go will automatically set -c. Furthermore, this CL has been intentionally written so that the c=1 path has no backend concurrency whatsoever, not even spawning any goroutines. This helps ensure that, should problems arise late in the development cycle, we can simply have cmd/go set c=1 always, and revert to the original compiler behavior. MUTEXES Most of the work required to make concurrent backend compilation safe has occurred over the past month. This CL adds a handful of mutexes to get the rest of the way there; they are the mutexes that I didn't see a clean way to avoid. Some of them may still be eliminable in future work. In no particular order: * gc.funcsymsmu. The global funcsyms slice is populated lazily when we need function symbols for closures. This occurs during gc AST to SSA translation. The function funcsym also does a package lookup, which is a source of races on types.Pkg.Syms; funcsymsmu also covers that package lookup. This mutex is low priority: it adds a single global, it is in an infrequently used code path, and it is low contention. Since funcsyms may now be added in any order, we must sort them to preserve reproducible builds. * gc.largeStackFramesMu. We don't discover until after SSA compilation that a function's stack frame is gigantic. Recording that error happens basically never, but it does happen concurrently. Fix with a low priority mutex and sorting. * obj.Link.hashmu. ctxt.hash stores the mapping from types.Syms (compiler symbols) to obj.LSyms (linker symbols). It is accessed fairly heavily through all the phases. This is the only heavily contended mutex. * gc.signatlistmu. The global signatlist map is populated with types through several of the concurrent phases, including notably via ngotype during DWARF generation. It is low priority for removal. * gc.typepkgmu. Looking up symbols in the types package happens a fair amount during backend compilation and DWARF generation, particularly via ngotype. This mutex helps us to avoid a broader mutex on types.Pkg.Syms. It has low-to-moderate contention. * types.internedStringsmu. gc AST to SSA conversion and some SSA work introduce new autotmps. Those autotmps have their names interned to reduce allocations. That interning requires protecting types.internedStrings. The autotmp names are heavily re-used, and the mutex overhead and contention here are low, so it is probably a worthwhile performance optimization to keep this mutex. TESTING I have been testing this code locally by running 'go install -race cmd/compile' and then doing 'go build -a -gcflags=-c=128 std cmd' for all architectures and a variety of compiler flags. This obviously needs to be made part of the builders, but it is too expensive to make part of all.bash. I have filed #19962 for this. REPRODUCIBLE BUILDS This version of the compiler generates reproducible builds. Testing reproducible builds also needs automation, however, and is also too expensive for all.bash. This is #19961. Also of note is that some of the compiler flags used by 'toolstash -cmp' are currently incompatible with concurrent backend compilation. They still work fine with c=1. Time will tell whether this is a problem. NEXT STEPS * Continue to find and fix races and bugs, using a combination of code inspection, fuzzing, and hopefully some community experimentation. I do not know of any outstanding races, but there probably are some. * Improve testing. * Improve performance, for many values of c. * Integrate with cmd/go and fine tune. * Support concurrent compilation with the -race flag. It is a sad irony that it does not yet work. * Minor code cleanup that has been deferred during the last month due to uncertainty about the ultimate shape of this CL. PERFORMANCE Here's the buried lede, at last. :) All benchmarks are from my 8 core 2.9 GHz Intel Core i7 darwin/amd64 laptop. First, going from tip to this CL with c=1 has almost no impact. name old time/op new time/op delta Template 195ms ± 3% 194ms ± 5% ~ (p=0.370 n=30+29) Unicode 86.6ms ± 3% 87.0ms ± 7% ~ (p=0.958 n=29+30) GoTypes 548ms ± 3% 555ms ± 4% +1.35% (p=0.001 n=30+28) Compiler 2.51s ± 2% 2.54s ± 2% +1.17% (p=0.000 n=28+30) SSA 5.16s ± 3% 5.16s ± 2% ~ (p=0.910 n=30+29) Flate 124ms ± 5% 124ms ± 4% ~ (p=0.947 n=30+30) GoParser 146ms ± 3% 146ms ± 3% ~ (p=0.150 n=29+28) Reflect 354ms ± 3% 352ms ± 4% ~ (p=0.096 n=29+29) Tar 107ms ± 5% 106ms ± 3% ~ (p=0.370 n=30+29) XML 200ms ± 4% 201ms ± 4% ~ (p=0.313 n=29+28) [Geo mean] 332ms 333ms +0.10% name old user-time/op new user-time/op delta Template 227ms ± 5% 225ms ± 5% ~ (p=0.457 n=28+27) Unicode 109ms ± 4% 109ms ± 5% ~ (p=0.758 n=29+29) GoTypes 713ms ± 4% 721ms ± 5% ~ (p=0.051 n=30+29) Compiler 3.36s ± 2% 3.38s ± 3% ~ (p=0.146 n=30+30) SSA 7.46s ± 3% 7.47s ± 3% ~ (p=0.804 n=30+29) Flate 146ms ± 7% 147ms ± 3% ~ (p=0.833 n=29+27) GoParser 179ms ± 5% 179ms ± 5% ~ (p=0.866 n=30+30) Reflect 431ms ± 4% 429ms ± 4% ~ (p=0.593 n=29+30) Tar 124ms ± 5% 123ms ± 5% ~ (p=0.140 n=29+29) XML 243ms ± 4% 242ms ± 7% ~ (p=0.404 n=29+29) [Geo mean] 415ms 415ms +0.02% name old obj-bytes new obj-bytes delta Template 382k ± 0% 382k ± 0% ~ (all equal) Unicode 203k ± 0% 203k ± 0% ~ (all equal) GoTypes 1.18M ± 0% 1.18M ± 0% ~ (all equal) Compiler 3.98M ± 0% 3.98M ± 0% ~ (all equal) SSA 8.28M ± 0% 8.28M ± 0% ~ (all equal) Flate 230k ± 0% 230k ± 0% ~ (all equal) GoParser 287k ± 0% 287k ± 0% ~ (all equal) Reflect 1.00M ± 0% 1.00M ± 0% ~ (all equal) Tar 190k ± 0% 190k ± 0% ~ (all equal) XML 416k ± 0% 416k ± 0% ~ (all equal) [Geo mean] 660k 660k +0.00% Comparing this CL to itself, from c=1 to c=2 improves real times 20-30%, costs 5-10% more CPU time, and adds about 2% alloc. The allocation increase comes from allocating more ssa.Caches. name old time/op new time/op delta Template 202ms ± 3% 149ms ± 3% -26.15% (p=0.000 n=49+49) Unicode 87.4ms ± 4% 84.2ms ± 3% -3.68% (p=0.000 n=48+48) GoTypes 560ms ± 2% 398ms ± 2% -28.96% (p=0.000 n=49+49) Compiler 2.46s ± 3% 1.76s ± 2% -28.61% (p=0.000 n=48+46) SSA 6.17s ± 2% 4.04s ± 1% -34.52% (p=0.000 n=49+49) Flate 126ms ± 3% 92ms ± 2% -26.81% (p=0.000 n=49+48) GoParser 148ms ± 4% 107ms ± 2% -27.78% (p=0.000 n=49+48) Reflect 361ms ± 3% 281ms ± 3% -22.10% (p=0.000 n=49+49) Tar 109ms ± 4% 86ms ± 3% -20.81% (p=0.000 n=49+47) XML 204ms ± 3% 144ms ± 2% -29.53% (p=0.000 n=48+45) name old user-time/op new user-time/op delta Template 246ms ± 9% 246ms ± 4% ~ (p=0.401 n=50+48) Unicode 109ms ± 4% 111ms ± 4% +1.47% (p=0.000 n=44+50) GoTypes 728ms ± 3% 765ms ± 3% +5.04% (p=0.000 n=46+50) Compiler 3.33s ± 3% 3.41s ± 2% +2.31% (p=0.000 n=49+48) SSA 8.52s ± 2% 9.11s ± 2% +6.93% (p=0.000 n=49+47) Flate 149ms ± 4% 161ms ± 3% +8.13% (p=0.000 n=50+47) GoParser 181ms ± 5% 192ms ± 2% +6.40% (p=0.000 n=49+46) Reflect 452ms ± 9% 474ms ± 2% +4.99% (p=0.000 n=50+48) Tar 126ms ± 6% 136ms ± 4% +7.95% (p=0.000 n=50+49) XML 247ms ± 5% 264ms ± 3% +6.94% (p=0.000 n=48+50) name old alloc/op new alloc/op delta Template 38.8MB ± 0% 39.3MB ± 0% +1.48% (p=0.008 n=5+5) Unicode 29.8MB ± 0% 30.2MB ± 0% +1.19% (p=0.008 n=5+5) GoTypes 113MB ± 0% 114MB ± 0% +0.69% (p=0.008 n=5+5) Compiler 443MB ± 0% 447MB ± 0% +0.95% (p=0.008 n=5+5) SSA 1.25GB ± 0% 1.26GB ± 0% +0.89% (p=0.008 n=5+5) Flate 25.3MB ± 0% 25.9MB ± 1% +2.35% (p=0.008 n=5+5) GoParser 31.7MB ± 0% 32.2MB ± 0% +1.59% (p=0.008 n=5+5) Reflect 78.2MB ± 0% 78.9MB ± 0% +0.91% (p=0.008 n=5+5) Tar 26.6MB ± 0% 27.0MB ± 0% +1.80% (p=0.008 n=5+5) XML 42.4MB ± 0% 43.4MB ± 0% +2.35% (p=0.008 n=5+5) name old allocs/op new allocs/op delta Template 379k ± 0% 378k ± 0% ~ (p=0.421 n=5+5) Unicode 322k ± 0% 321k ± 0% ~ (p=0.222 n=5+5) GoTypes 1.14M ± 0% 1.14M ± 0% ~ (p=0.548 n=5+5) Compiler 4.12M ± 0% 4.11M ± 0% -0.14% (p=0.032 n=5+5) SSA 9.72M ± 0% 9.72M ± 0% ~ (p=0.421 n=5+5) Flate 234k ± 1% 234k ± 0% ~ (p=0.421 n=5+5) GoParser 316k ± 1% 315k ± 0% ~ (p=0.222 n=5+5) Reflect 980k ± 0% 979k ± 0% ~ (p=0.095 n=5+5) Tar 249k ± 1% 249k ± 1% ~ (p=0.841 n=5+5) XML 392k ± 0% 391k ± 0% ~ (p=0.095 n=5+5) From c=1 to c=4, real time is down ~40%, CPU usage up 10-20%, alloc up ~5%: name old time/op new time/op delta Template 203ms ± 3% 131ms ± 5% -35.45% (p=0.000 n=50+50) Unicode 87.2ms ± 4% 84.1ms ± 2% -3.61% (p=0.000 n=48+47) GoTypes 560ms ± 4% 310ms ± 2% -44.65% (p=0.000 n=50+49) Compiler 2.47s ± 3% 1.41s ± 2% -43.10% (p=0.000 n=50+46) SSA 6.17s ± 2% 3.20s ± 2% -48.06% (p=0.000 n=49+49) Flate 126ms ± 4% 74ms ± 2% -41.06% (p=0.000 n=49+48) GoParser 148ms ± 4% 89ms ± 3% -39.97% (p=0.000 n=49+50) Reflect 360ms ± 3% 242ms ± 3% -32.81% (p=0.000 n=49+49) Tar 108ms ± 4% 73ms ± 4% -32.48% (p=0.000 n=50+49) XML 203ms ± 3% 119ms ± 3% -41.56% (p=0.000 n=49+48) name old user-time/op new user-time/op delta Template 246ms ± 9% 287ms ± 9% +16.98% (p=0.000 n=50+50) Unicode 109ms ± 4% 118ms ± 5% +7.56% (p=0.000 n=46+50) GoTypes 735ms ± 4% 806ms ± 2% +9.62% (p=0.000 n=50+50) Compiler 3.34s ± 4% 3.56s ± 2% +6.78% (p=0.000 n=49+49) SSA 8.54s ± 3% 10.04s ± 3% +17.55% (p=0.000 n=50+50) Flate 149ms ± 6% 176ms ± 3% +17.82% (p=0.000 n=50+48) GoParser 181ms ± 5% 213ms ± 3% +17.47% (p=0.000 n=50+50) Reflect 453ms ± 6% 499ms ± 2% +10.11% (p=0.000 n=50+48) Tar 126ms ± 5% 149ms ±11% +18.76% (p=0.000 n=50+50) XML 246ms ± 5% 287ms ± 4% +16.53% (p=0.000 n=49+50) name old alloc/op new alloc/op delta Template 38.8MB ± 0% 40.4MB ± 0% +4.21% (p=0.008 n=5+5) Unicode 29.8MB ± 0% 30.9MB ± 0% +3.68% (p=0.008 n=5+5) GoTypes 113MB ± 0% 116MB ± 0% +2.71% (p=0.008 n=5+5) Compiler 443MB ± 0% 455MB ± 0% +2.75% (p=0.008 n=5+5) SSA 1.25GB ± 0% 1.27GB ± 0% +1.84% (p=0.008 n=5+5) Flate 25.3MB ± 0% 26.9MB ± 1% +6.31% (p=0.008 n=5+5) GoParser 31.7MB ± 0% 33.2MB ± 0% +4.61% (p=0.008 n=5+5) Reflect 78.2MB ± 0% 80.2MB ± 0% +2.53% (p=0.008 n=5+5) Tar 26.6MB ± 0% 27.9MB ± 0% +5.19% (p=0.008 n=5+5) XML 42.4MB ± 0% 44.6MB ± 0% +5.20% (p=0.008 n=5+5) name old allocs/op new allocs/op delta Template 380k ± 0% 379k ± 0% -0.39% (p=0.032 n=5+5) Unicode 321k ± 0% 321k ± 0% ~ (p=0.841 n=5+5) GoTypes 1.14M ± 0% 1.14M ± 0% ~ (p=0.421 n=5+5) Compiler 4.12M ± 0% 4.14M ± 0% +0.52% (p=0.008 n=5+5) SSA 9.72M ± 0% 9.76M ± 0% +0.37% (p=0.008 n=5+5) Flate 234k ± 1% 234k ± 1% ~ (p=0.690 n=5+5) GoParser 316k ± 0% 317k ± 1% ~ (p=0.841 n=5+5) Reflect 981k ± 0% 981k ± 0% ~ (p=1.000 n=5+5) Tar 250k ± 0% 249k ± 1% ~ (p=0.151 n=5+5) XML 393k ± 0% 392k ± 0% ~ (p=0.056 n=5+5) Going beyond c=4 on my machine tends to increase CPU time and allocs without impacting real time. The CPU time numbers matter, because when there are many concurrent compilation processes, that will impact the overall throughput. The numbers above are in many ways the best case scenario; we can take full advantage of all cores. Fortunately, the most common compilation scenario is incremental re-compilation of a single package during a build/test cycle. Updates #15756 Change-Id: I6725558ca2069edec0ac5b0d1683105a9fff6bea Reviewed-on: https://go-review.googlesource.com/40693 Reviewed-by: Matthew Dempsky <mdempsky@google.com> Reviewed-by: Robert Griesemer <gri@golang.org> Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
2017-03-19 08:27:26 -07:00
"sync"
"unicode"
"unicode/utf8"
)
type Error struct {
2016-12-15 17:17:01 -08:00
pos src.XPos
msg string
}
var errors []Error
// largeStack is info about a function whose stack frame is too large (rare).
type largeStack struct {
locals int64
args int64
callee int64
pos src.XPos
}
cmd/compile: add initial backend concurrency support This CL adds initial support for concurrent backend compilation. BACKGROUND The compiler currently consists (very roughly) of the following phases: 1. Initialization. 2. Lexing and parsing into the cmd/compile/internal/syntax AST. 3. Translation into the cmd/compile/internal/gc AST. 4. Some gc AST passes: typechecking, escape analysis, inlining, closure handling, expression evaluation ordering (order.go), and some lowering and optimization (walk.go). 5. Translation into the cmd/compile/internal/ssa SSA form. 6. Optimization and lowering of SSA form. 7. Translation from SSA form to assembler instructions. 8. Translation from assembler instructions to machine code. 9. Writing lots of output: machine code, DWARF symbols, type and reflection info, export data. Phase 2 was already concurrent as of Go 1.8. Phase 3 is planned for eventual removal; we hope to go straight from syntax AST to SSA. Phases 5–8 are per-function; this CL adds support for processing multiple functions concurrently. The slowest phases in the compiler are 5 and 6, so this offers the opportunity for some good speed-ups. Unfortunately, it's not quite that straightforward. In the current compiler, the latter parts of phase 4 (order, walk) are done function-at-a-time as needed. Making order and walk concurrency-safe proved hard, and they're not particularly slow, so there wasn't much reward. To enable phases 5–8 to be done concurrently, when concurrent backend compilation is requested, we complete phase 4 for all functions before starting later phases for any functions. Also, in reality, we automatically generate new functions in phase 9, such as method wrappers and equality and has routines. Those new functions then go through phases 4–8. This CL disables concurrent backend compilation after the first, big, user-provided batch of functions has been compiled. This is done to keep things simple, and because the autogenerated functions tend to be small, few, simple, and fast to compile. USAGE Concurrent backend compilation still defaults to off. To set the number of functions that may be backend-compiled concurrently, use the compiler flag -c. In future work, cmd/go will automatically set -c. Furthermore, this CL has been intentionally written so that the c=1 path has no backend concurrency whatsoever, not even spawning any goroutines. This helps ensure that, should problems arise late in the development cycle, we can simply have cmd/go set c=1 always, and revert to the original compiler behavior. MUTEXES Most of the work required to make concurrent backend compilation safe has occurred over the past month. This CL adds a handful of mutexes to get the rest of the way there; they are the mutexes that I didn't see a clean way to avoid. Some of them may still be eliminable in future work. In no particular order: * gc.funcsymsmu. The global funcsyms slice is populated lazily when we need function symbols for closures. This occurs during gc AST to SSA translation. The function funcsym also does a package lookup, which is a source of races on types.Pkg.Syms; funcsymsmu also covers that package lookup. This mutex is low priority: it adds a single global, it is in an infrequently used code path, and it is low contention. Since funcsyms may now be added in any order, we must sort them to preserve reproducible builds. * gc.largeStackFramesMu. We don't discover until after SSA compilation that a function's stack frame is gigantic. Recording that error happens basically never, but it does happen concurrently. Fix with a low priority mutex and sorting. * obj.Link.hashmu. ctxt.hash stores the mapping from types.Syms (compiler symbols) to obj.LSyms (linker symbols). It is accessed fairly heavily through all the phases. This is the only heavily contended mutex. * gc.signatlistmu. The global signatlist map is populated with types through several of the concurrent phases, including notably via ngotype during DWARF generation. It is low priority for removal. * gc.typepkgmu. Looking up symbols in the types package happens a fair amount during backend compilation and DWARF generation, particularly via ngotype. This mutex helps us to avoid a broader mutex on types.Pkg.Syms. It has low-to-moderate contention. * types.internedStringsmu. gc AST to SSA conversion and some SSA work introduce new autotmps. Those autotmps have their names interned to reduce allocations. That interning requires protecting types.internedStrings. The autotmp names are heavily re-used, and the mutex overhead and contention here are low, so it is probably a worthwhile performance optimization to keep this mutex. TESTING I have been testing this code locally by running 'go install -race cmd/compile' and then doing 'go build -a -gcflags=-c=128 std cmd' for all architectures and a variety of compiler flags. This obviously needs to be made part of the builders, but it is too expensive to make part of all.bash. I have filed #19962 for this. REPRODUCIBLE BUILDS This version of the compiler generates reproducible builds. Testing reproducible builds also needs automation, however, and is also too expensive for all.bash. This is #19961. Also of note is that some of the compiler flags used by 'toolstash -cmp' are currently incompatible with concurrent backend compilation. They still work fine with c=1. Time will tell whether this is a problem. NEXT STEPS * Continue to find and fix races and bugs, using a combination of code inspection, fuzzing, and hopefully some community experimentation. I do not know of any outstanding races, but there probably are some. * Improve testing. * Improve performance, for many values of c. * Integrate with cmd/go and fine tune. * Support concurrent compilation with the -race flag. It is a sad irony that it does not yet work. * Minor code cleanup that has been deferred during the last month due to uncertainty about the ultimate shape of this CL. PERFORMANCE Here's the buried lede, at last. :) All benchmarks are from my 8 core 2.9 GHz Intel Core i7 darwin/amd64 laptop. First, going from tip to this CL with c=1 has almost no impact. name old time/op new time/op delta Template 195ms ± 3% 194ms ± 5% ~ (p=0.370 n=30+29) Unicode 86.6ms ± 3% 87.0ms ± 7% ~ (p=0.958 n=29+30) GoTypes 548ms ± 3% 555ms ± 4% +1.35% (p=0.001 n=30+28) Compiler 2.51s ± 2% 2.54s ± 2% +1.17% (p=0.000 n=28+30) SSA 5.16s ± 3% 5.16s ± 2% ~ (p=0.910 n=30+29) Flate 124ms ± 5% 124ms ± 4% ~ (p=0.947 n=30+30) GoParser 146ms ± 3% 146ms ± 3% ~ (p=0.150 n=29+28) Reflect 354ms ± 3% 352ms ± 4% ~ (p=0.096 n=29+29) Tar 107ms ± 5% 106ms ± 3% ~ (p=0.370 n=30+29) XML 200ms ± 4% 201ms ± 4% ~ (p=0.313 n=29+28) [Geo mean] 332ms 333ms +0.10% name old user-time/op new user-time/op delta Template 227ms ± 5% 225ms ± 5% ~ (p=0.457 n=28+27) Unicode 109ms ± 4% 109ms ± 5% ~ (p=0.758 n=29+29) GoTypes 713ms ± 4% 721ms ± 5% ~ (p=0.051 n=30+29) Compiler 3.36s ± 2% 3.38s ± 3% ~ (p=0.146 n=30+30) SSA 7.46s ± 3% 7.47s ± 3% ~ (p=0.804 n=30+29) Flate 146ms ± 7% 147ms ± 3% ~ (p=0.833 n=29+27) GoParser 179ms ± 5% 179ms ± 5% ~ (p=0.866 n=30+30) Reflect 431ms ± 4% 429ms ± 4% ~ (p=0.593 n=29+30) Tar 124ms ± 5% 123ms ± 5% ~ (p=0.140 n=29+29) XML 243ms ± 4% 242ms ± 7% ~ (p=0.404 n=29+29) [Geo mean] 415ms 415ms +0.02% name old obj-bytes new obj-bytes delta Template 382k ± 0% 382k ± 0% ~ (all equal) Unicode 203k ± 0% 203k ± 0% ~ (all equal) GoTypes 1.18M ± 0% 1.18M ± 0% ~ (all equal) Compiler 3.98M ± 0% 3.98M ± 0% ~ (all equal) SSA 8.28M ± 0% 8.28M ± 0% ~ (all equal) Flate 230k ± 0% 230k ± 0% ~ (all equal) GoParser 287k ± 0% 287k ± 0% ~ (all equal) Reflect 1.00M ± 0% 1.00M ± 0% ~ (all equal) Tar 190k ± 0% 190k ± 0% ~ (all equal) XML 416k ± 0% 416k ± 0% ~ (all equal) [Geo mean] 660k 660k +0.00% Comparing this CL to itself, from c=1 to c=2 improves real times 20-30%, costs 5-10% more CPU time, and adds about 2% alloc. The allocation increase comes from allocating more ssa.Caches. name old time/op new time/op delta Template 202ms ± 3% 149ms ± 3% -26.15% (p=0.000 n=49+49) Unicode 87.4ms ± 4% 84.2ms ± 3% -3.68% (p=0.000 n=48+48) GoTypes 560ms ± 2% 398ms ± 2% -28.96% (p=0.000 n=49+49) Compiler 2.46s ± 3% 1.76s ± 2% -28.61% (p=0.000 n=48+46) SSA 6.17s ± 2% 4.04s ± 1% -34.52% (p=0.000 n=49+49) Flate 126ms ± 3% 92ms ± 2% -26.81% (p=0.000 n=49+48) GoParser 148ms ± 4% 107ms ± 2% -27.78% (p=0.000 n=49+48) Reflect 361ms ± 3% 281ms ± 3% -22.10% (p=0.000 n=49+49) Tar 109ms ± 4% 86ms ± 3% -20.81% (p=0.000 n=49+47) XML 204ms ± 3% 144ms ± 2% -29.53% (p=0.000 n=48+45) name old user-time/op new user-time/op delta Template 246ms ± 9% 246ms ± 4% ~ (p=0.401 n=50+48) Unicode 109ms ± 4% 111ms ± 4% +1.47% (p=0.000 n=44+50) GoTypes 728ms ± 3% 765ms ± 3% +5.04% (p=0.000 n=46+50) Compiler 3.33s ± 3% 3.41s ± 2% +2.31% (p=0.000 n=49+48) SSA 8.52s ± 2% 9.11s ± 2% +6.93% (p=0.000 n=49+47) Flate 149ms ± 4% 161ms ± 3% +8.13% (p=0.000 n=50+47) GoParser 181ms ± 5% 192ms ± 2% +6.40% (p=0.000 n=49+46) Reflect 452ms ± 9% 474ms ± 2% +4.99% (p=0.000 n=50+48) Tar 126ms ± 6% 136ms ± 4% +7.95% (p=0.000 n=50+49) XML 247ms ± 5% 264ms ± 3% +6.94% (p=0.000 n=48+50) name old alloc/op new alloc/op delta Template 38.8MB ± 0% 39.3MB ± 0% +1.48% (p=0.008 n=5+5) Unicode 29.8MB ± 0% 30.2MB ± 0% +1.19% (p=0.008 n=5+5) GoTypes 113MB ± 0% 114MB ± 0% +0.69% (p=0.008 n=5+5) Compiler 443MB ± 0% 447MB ± 0% +0.95% (p=0.008 n=5+5) SSA 1.25GB ± 0% 1.26GB ± 0% +0.89% (p=0.008 n=5+5) Flate 25.3MB ± 0% 25.9MB ± 1% +2.35% (p=0.008 n=5+5) GoParser 31.7MB ± 0% 32.2MB ± 0% +1.59% (p=0.008 n=5+5) Reflect 78.2MB ± 0% 78.9MB ± 0% +0.91% (p=0.008 n=5+5) Tar 26.6MB ± 0% 27.0MB ± 0% +1.80% (p=0.008 n=5+5) XML 42.4MB ± 0% 43.4MB ± 0% +2.35% (p=0.008 n=5+5) name old allocs/op new allocs/op delta Template 379k ± 0% 378k ± 0% ~ (p=0.421 n=5+5) Unicode 322k ± 0% 321k ± 0% ~ (p=0.222 n=5+5) GoTypes 1.14M ± 0% 1.14M ± 0% ~ (p=0.548 n=5+5) Compiler 4.12M ± 0% 4.11M ± 0% -0.14% (p=0.032 n=5+5) SSA 9.72M ± 0% 9.72M ± 0% ~ (p=0.421 n=5+5) Flate 234k ± 1% 234k ± 0% ~ (p=0.421 n=5+5) GoParser 316k ± 1% 315k ± 0% ~ (p=0.222 n=5+5) Reflect 980k ± 0% 979k ± 0% ~ (p=0.095 n=5+5) Tar 249k ± 1% 249k ± 1% ~ (p=0.841 n=5+5) XML 392k ± 0% 391k ± 0% ~ (p=0.095 n=5+5) From c=1 to c=4, real time is down ~40%, CPU usage up 10-20%, alloc up ~5%: name old time/op new time/op delta Template 203ms ± 3% 131ms ± 5% -35.45% (p=0.000 n=50+50) Unicode 87.2ms ± 4% 84.1ms ± 2% -3.61% (p=0.000 n=48+47) GoTypes 560ms ± 4% 310ms ± 2% -44.65% (p=0.000 n=50+49) Compiler 2.47s ± 3% 1.41s ± 2% -43.10% (p=0.000 n=50+46) SSA 6.17s ± 2% 3.20s ± 2% -48.06% (p=0.000 n=49+49) Flate 126ms ± 4% 74ms ± 2% -41.06% (p=0.000 n=49+48) GoParser 148ms ± 4% 89ms ± 3% -39.97% (p=0.000 n=49+50) Reflect 360ms ± 3% 242ms ± 3% -32.81% (p=0.000 n=49+49) Tar 108ms ± 4% 73ms ± 4% -32.48% (p=0.000 n=50+49) XML 203ms ± 3% 119ms ± 3% -41.56% (p=0.000 n=49+48) name old user-time/op new user-time/op delta Template 246ms ± 9% 287ms ± 9% +16.98% (p=0.000 n=50+50) Unicode 109ms ± 4% 118ms ± 5% +7.56% (p=0.000 n=46+50) GoTypes 735ms ± 4% 806ms ± 2% +9.62% (p=0.000 n=50+50) Compiler 3.34s ± 4% 3.56s ± 2% +6.78% (p=0.000 n=49+49) SSA 8.54s ± 3% 10.04s ± 3% +17.55% (p=0.000 n=50+50) Flate 149ms ± 6% 176ms ± 3% +17.82% (p=0.000 n=50+48) GoParser 181ms ± 5% 213ms ± 3% +17.47% (p=0.000 n=50+50) Reflect 453ms ± 6% 499ms ± 2% +10.11% (p=0.000 n=50+48) Tar 126ms ± 5% 149ms ±11% +18.76% (p=0.000 n=50+50) XML 246ms ± 5% 287ms ± 4% +16.53% (p=0.000 n=49+50) name old alloc/op new alloc/op delta Template 38.8MB ± 0% 40.4MB ± 0% +4.21% (p=0.008 n=5+5) Unicode 29.8MB ± 0% 30.9MB ± 0% +3.68% (p=0.008 n=5+5) GoTypes 113MB ± 0% 116MB ± 0% +2.71% (p=0.008 n=5+5) Compiler 443MB ± 0% 455MB ± 0% +2.75% (p=0.008 n=5+5) SSA 1.25GB ± 0% 1.27GB ± 0% +1.84% (p=0.008 n=5+5) Flate 25.3MB ± 0% 26.9MB ± 1% +6.31% (p=0.008 n=5+5) GoParser 31.7MB ± 0% 33.2MB ± 0% +4.61% (p=0.008 n=5+5) Reflect 78.2MB ± 0% 80.2MB ± 0% +2.53% (p=0.008 n=5+5) Tar 26.6MB ± 0% 27.9MB ± 0% +5.19% (p=0.008 n=5+5) XML 42.4MB ± 0% 44.6MB ± 0% +5.20% (p=0.008 n=5+5) name old allocs/op new allocs/op delta Template 380k ± 0% 379k ± 0% -0.39% (p=0.032 n=5+5) Unicode 321k ± 0% 321k ± 0% ~ (p=0.841 n=5+5) GoTypes 1.14M ± 0% 1.14M ± 0% ~ (p=0.421 n=5+5) Compiler 4.12M ± 0% 4.14M ± 0% +0.52% (p=0.008 n=5+5) SSA 9.72M ± 0% 9.76M ± 0% +0.37% (p=0.008 n=5+5) Flate 234k ± 1% 234k ± 1% ~ (p=0.690 n=5+5) GoParser 316k ± 0% 317k ± 1% ~ (p=0.841 n=5+5) Reflect 981k ± 0% 981k ± 0% ~ (p=1.000 n=5+5) Tar 250k ± 0% 249k ± 1% ~ (p=0.151 n=5+5) XML 393k ± 0% 392k ± 0% ~ (p=0.056 n=5+5) Going beyond c=4 on my machine tends to increase CPU time and allocs without impacting real time. The CPU time numbers matter, because when there are many concurrent compilation processes, that will impact the overall throughput. The numbers above are in many ways the best case scenario; we can take full advantage of all cores. Fortunately, the most common compilation scenario is incremental re-compilation of a single package during a build/test cycle. Updates #15756 Change-Id: I6725558ca2069edec0ac5b0d1683105a9fff6bea Reviewed-on: https://go-review.googlesource.com/40693 Reviewed-by: Matthew Dempsky <mdempsky@google.com> Reviewed-by: Robert Griesemer <gri@golang.org> Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
2017-03-19 08:27:26 -07:00
var (
largeStackFramesMu sync.Mutex // protects largeStackFrames
largeStackFrames []largeStack
cmd/compile: add initial backend concurrency support This CL adds initial support for concurrent backend compilation. BACKGROUND The compiler currently consists (very roughly) of the following phases: 1. Initialization. 2. Lexing and parsing into the cmd/compile/internal/syntax AST. 3. Translation into the cmd/compile/internal/gc AST. 4. Some gc AST passes: typechecking, escape analysis, inlining, closure handling, expression evaluation ordering (order.go), and some lowering and optimization (walk.go). 5. Translation into the cmd/compile/internal/ssa SSA form. 6. Optimization and lowering of SSA form. 7. Translation from SSA form to assembler instructions. 8. Translation from assembler instructions to machine code. 9. Writing lots of output: machine code, DWARF symbols, type and reflection info, export data. Phase 2 was already concurrent as of Go 1.8. Phase 3 is planned for eventual removal; we hope to go straight from syntax AST to SSA. Phases 5–8 are per-function; this CL adds support for processing multiple functions concurrently. The slowest phases in the compiler are 5 and 6, so this offers the opportunity for some good speed-ups. Unfortunately, it's not quite that straightforward. In the current compiler, the latter parts of phase 4 (order, walk) are done function-at-a-time as needed. Making order and walk concurrency-safe proved hard, and they're not particularly slow, so there wasn't much reward. To enable phases 5–8 to be done concurrently, when concurrent backend compilation is requested, we complete phase 4 for all functions before starting later phases for any functions. Also, in reality, we automatically generate new functions in phase 9, such as method wrappers and equality and has routines. Those new functions then go through phases 4–8. This CL disables concurrent backend compilation after the first, big, user-provided batch of functions has been compiled. This is done to keep things simple, and because the autogenerated functions tend to be small, few, simple, and fast to compile. USAGE Concurrent backend compilation still defaults to off. To set the number of functions that may be backend-compiled concurrently, use the compiler flag -c. In future work, cmd/go will automatically set -c. Furthermore, this CL has been intentionally written so that the c=1 path has no backend concurrency whatsoever, not even spawning any goroutines. This helps ensure that, should problems arise late in the development cycle, we can simply have cmd/go set c=1 always, and revert to the original compiler behavior. MUTEXES Most of the work required to make concurrent backend compilation safe has occurred over the past month. This CL adds a handful of mutexes to get the rest of the way there; they are the mutexes that I didn't see a clean way to avoid. Some of them may still be eliminable in future work. In no particular order: * gc.funcsymsmu. The global funcsyms slice is populated lazily when we need function symbols for closures. This occurs during gc AST to SSA translation. The function funcsym also does a package lookup, which is a source of races on types.Pkg.Syms; funcsymsmu also covers that package lookup. This mutex is low priority: it adds a single global, it is in an infrequently used code path, and it is low contention. Since funcsyms may now be added in any order, we must sort them to preserve reproducible builds. * gc.largeStackFramesMu. We don't discover until after SSA compilation that a function's stack frame is gigantic. Recording that error happens basically never, but it does happen concurrently. Fix with a low priority mutex and sorting. * obj.Link.hashmu. ctxt.hash stores the mapping from types.Syms (compiler symbols) to obj.LSyms (linker symbols). It is accessed fairly heavily through all the phases. This is the only heavily contended mutex. * gc.signatlistmu. The global signatlist map is populated with types through several of the concurrent phases, including notably via ngotype during DWARF generation. It is low priority for removal. * gc.typepkgmu. Looking up symbols in the types package happens a fair amount during backend compilation and DWARF generation, particularly via ngotype. This mutex helps us to avoid a broader mutex on types.Pkg.Syms. It has low-to-moderate contention. * types.internedStringsmu. gc AST to SSA conversion and some SSA work introduce new autotmps. Those autotmps have their names interned to reduce allocations. That interning requires protecting types.internedStrings. The autotmp names are heavily re-used, and the mutex overhead and contention here are low, so it is probably a worthwhile performance optimization to keep this mutex. TESTING I have been testing this code locally by running 'go install -race cmd/compile' and then doing 'go build -a -gcflags=-c=128 std cmd' for all architectures and a variety of compiler flags. This obviously needs to be made part of the builders, but it is too expensive to make part of all.bash. I have filed #19962 for this. REPRODUCIBLE BUILDS This version of the compiler generates reproducible builds. Testing reproducible builds also needs automation, however, and is also too expensive for all.bash. This is #19961. Also of note is that some of the compiler flags used by 'toolstash -cmp' are currently incompatible with concurrent backend compilation. They still work fine with c=1. Time will tell whether this is a problem. NEXT STEPS * Continue to find and fix races and bugs, using a combination of code inspection, fuzzing, and hopefully some community experimentation. I do not know of any outstanding races, but there probably are some. * Improve testing. * Improve performance, for many values of c. * Integrate with cmd/go and fine tune. * Support concurrent compilation with the -race flag. It is a sad irony that it does not yet work. * Minor code cleanup that has been deferred during the last month due to uncertainty about the ultimate shape of this CL. PERFORMANCE Here's the buried lede, at last. :) All benchmarks are from my 8 core 2.9 GHz Intel Core i7 darwin/amd64 laptop. First, going from tip to this CL with c=1 has almost no impact. name old time/op new time/op delta Template 195ms ± 3% 194ms ± 5% ~ (p=0.370 n=30+29) Unicode 86.6ms ± 3% 87.0ms ± 7% ~ (p=0.958 n=29+30) GoTypes 548ms ± 3% 555ms ± 4% +1.35% (p=0.001 n=30+28) Compiler 2.51s ± 2% 2.54s ± 2% +1.17% (p=0.000 n=28+30) SSA 5.16s ± 3% 5.16s ± 2% ~ (p=0.910 n=30+29) Flate 124ms ± 5% 124ms ± 4% ~ (p=0.947 n=30+30) GoParser 146ms ± 3% 146ms ± 3% ~ (p=0.150 n=29+28) Reflect 354ms ± 3% 352ms ± 4% ~ (p=0.096 n=29+29) Tar 107ms ± 5% 106ms ± 3% ~ (p=0.370 n=30+29) XML 200ms ± 4% 201ms ± 4% ~ (p=0.313 n=29+28) [Geo mean] 332ms 333ms +0.10% name old user-time/op new user-time/op delta Template 227ms ± 5% 225ms ± 5% ~ (p=0.457 n=28+27) Unicode 109ms ± 4% 109ms ± 5% ~ (p=0.758 n=29+29) GoTypes 713ms ± 4% 721ms ± 5% ~ (p=0.051 n=30+29) Compiler 3.36s ± 2% 3.38s ± 3% ~ (p=0.146 n=30+30) SSA 7.46s ± 3% 7.47s ± 3% ~ (p=0.804 n=30+29) Flate 146ms ± 7% 147ms ± 3% ~ (p=0.833 n=29+27) GoParser 179ms ± 5% 179ms ± 5% ~ (p=0.866 n=30+30) Reflect 431ms ± 4% 429ms ± 4% ~ (p=0.593 n=29+30) Tar 124ms ± 5% 123ms ± 5% ~ (p=0.140 n=29+29) XML 243ms ± 4% 242ms ± 7% ~ (p=0.404 n=29+29) [Geo mean] 415ms 415ms +0.02% name old obj-bytes new obj-bytes delta Template 382k ± 0% 382k ± 0% ~ (all equal) Unicode 203k ± 0% 203k ± 0% ~ (all equal) GoTypes 1.18M ± 0% 1.18M ± 0% ~ (all equal) Compiler 3.98M ± 0% 3.98M ± 0% ~ (all equal) SSA 8.28M ± 0% 8.28M ± 0% ~ (all equal) Flate 230k ± 0% 230k ± 0% ~ (all equal) GoParser 287k ± 0% 287k ± 0% ~ (all equal) Reflect 1.00M ± 0% 1.00M ± 0% ~ (all equal) Tar 190k ± 0% 190k ± 0% ~ (all equal) XML 416k ± 0% 416k ± 0% ~ (all equal) [Geo mean] 660k 660k +0.00% Comparing this CL to itself, from c=1 to c=2 improves real times 20-30%, costs 5-10% more CPU time, and adds about 2% alloc. The allocation increase comes from allocating more ssa.Caches. name old time/op new time/op delta Template 202ms ± 3% 149ms ± 3% -26.15% (p=0.000 n=49+49) Unicode 87.4ms ± 4% 84.2ms ± 3% -3.68% (p=0.000 n=48+48) GoTypes 560ms ± 2% 398ms ± 2% -28.96% (p=0.000 n=49+49) Compiler 2.46s ± 3% 1.76s ± 2% -28.61% (p=0.000 n=48+46) SSA 6.17s ± 2% 4.04s ± 1% -34.52% (p=0.000 n=49+49) Flate 126ms ± 3% 92ms ± 2% -26.81% (p=0.000 n=49+48) GoParser 148ms ± 4% 107ms ± 2% -27.78% (p=0.000 n=49+48) Reflect 361ms ± 3% 281ms ± 3% -22.10% (p=0.000 n=49+49) Tar 109ms ± 4% 86ms ± 3% -20.81% (p=0.000 n=49+47) XML 204ms ± 3% 144ms ± 2% -29.53% (p=0.000 n=48+45) name old user-time/op new user-time/op delta Template 246ms ± 9% 246ms ± 4% ~ (p=0.401 n=50+48) Unicode 109ms ± 4% 111ms ± 4% +1.47% (p=0.000 n=44+50) GoTypes 728ms ± 3% 765ms ± 3% +5.04% (p=0.000 n=46+50) Compiler 3.33s ± 3% 3.41s ± 2% +2.31% (p=0.000 n=49+48) SSA 8.52s ± 2% 9.11s ± 2% +6.93% (p=0.000 n=49+47) Flate 149ms ± 4% 161ms ± 3% +8.13% (p=0.000 n=50+47) GoParser 181ms ± 5% 192ms ± 2% +6.40% (p=0.000 n=49+46) Reflect 452ms ± 9% 474ms ± 2% +4.99% (p=0.000 n=50+48) Tar 126ms ± 6% 136ms ± 4% +7.95% (p=0.000 n=50+49) XML 247ms ± 5% 264ms ± 3% +6.94% (p=0.000 n=48+50) name old alloc/op new alloc/op delta Template 38.8MB ± 0% 39.3MB ± 0% +1.48% (p=0.008 n=5+5) Unicode 29.8MB ± 0% 30.2MB ± 0% +1.19% (p=0.008 n=5+5) GoTypes 113MB ± 0% 114MB ± 0% +0.69% (p=0.008 n=5+5) Compiler 443MB ± 0% 447MB ± 0% +0.95% (p=0.008 n=5+5) SSA 1.25GB ± 0% 1.26GB ± 0% +0.89% (p=0.008 n=5+5) Flate 25.3MB ± 0% 25.9MB ± 1% +2.35% (p=0.008 n=5+5) GoParser 31.7MB ± 0% 32.2MB ± 0% +1.59% (p=0.008 n=5+5) Reflect 78.2MB ± 0% 78.9MB ± 0% +0.91% (p=0.008 n=5+5) Tar 26.6MB ± 0% 27.0MB ± 0% +1.80% (p=0.008 n=5+5) XML 42.4MB ± 0% 43.4MB ± 0% +2.35% (p=0.008 n=5+5) name old allocs/op new allocs/op delta Template 379k ± 0% 378k ± 0% ~ (p=0.421 n=5+5) Unicode 322k ± 0% 321k ± 0% ~ (p=0.222 n=5+5) GoTypes 1.14M ± 0% 1.14M ± 0% ~ (p=0.548 n=5+5) Compiler 4.12M ± 0% 4.11M ± 0% -0.14% (p=0.032 n=5+5) SSA 9.72M ± 0% 9.72M ± 0% ~ (p=0.421 n=5+5) Flate 234k ± 1% 234k ± 0% ~ (p=0.421 n=5+5) GoParser 316k ± 1% 315k ± 0% ~ (p=0.222 n=5+5) Reflect 980k ± 0% 979k ± 0% ~ (p=0.095 n=5+5) Tar 249k ± 1% 249k ± 1% ~ (p=0.841 n=5+5) XML 392k ± 0% 391k ± 0% ~ (p=0.095 n=5+5) From c=1 to c=4, real time is down ~40%, CPU usage up 10-20%, alloc up ~5%: name old time/op new time/op delta Template 203ms ± 3% 131ms ± 5% -35.45% (p=0.000 n=50+50) Unicode 87.2ms ± 4% 84.1ms ± 2% -3.61% (p=0.000 n=48+47) GoTypes 560ms ± 4% 310ms ± 2% -44.65% (p=0.000 n=50+49) Compiler 2.47s ± 3% 1.41s ± 2% -43.10% (p=0.000 n=50+46) SSA 6.17s ± 2% 3.20s ± 2% -48.06% (p=0.000 n=49+49) Flate 126ms ± 4% 74ms ± 2% -41.06% (p=0.000 n=49+48) GoParser 148ms ± 4% 89ms ± 3% -39.97% (p=0.000 n=49+50) Reflect 360ms ± 3% 242ms ± 3% -32.81% (p=0.000 n=49+49) Tar 108ms ± 4% 73ms ± 4% -32.48% (p=0.000 n=50+49) XML 203ms ± 3% 119ms ± 3% -41.56% (p=0.000 n=49+48) name old user-time/op new user-time/op delta Template 246ms ± 9% 287ms ± 9% +16.98% (p=0.000 n=50+50) Unicode 109ms ± 4% 118ms ± 5% +7.56% (p=0.000 n=46+50) GoTypes 735ms ± 4% 806ms ± 2% +9.62% (p=0.000 n=50+50) Compiler 3.34s ± 4% 3.56s ± 2% +6.78% (p=0.000 n=49+49) SSA 8.54s ± 3% 10.04s ± 3% +17.55% (p=0.000 n=50+50) Flate 149ms ± 6% 176ms ± 3% +17.82% (p=0.000 n=50+48) GoParser 181ms ± 5% 213ms ± 3% +17.47% (p=0.000 n=50+50) Reflect 453ms ± 6% 499ms ± 2% +10.11% (p=0.000 n=50+48) Tar 126ms ± 5% 149ms ±11% +18.76% (p=0.000 n=50+50) XML 246ms ± 5% 287ms ± 4% +16.53% (p=0.000 n=49+50) name old alloc/op new alloc/op delta Template 38.8MB ± 0% 40.4MB ± 0% +4.21% (p=0.008 n=5+5) Unicode 29.8MB ± 0% 30.9MB ± 0% +3.68% (p=0.008 n=5+5) GoTypes 113MB ± 0% 116MB ± 0% +2.71% (p=0.008 n=5+5) Compiler 443MB ± 0% 455MB ± 0% +2.75% (p=0.008 n=5+5) SSA 1.25GB ± 0% 1.27GB ± 0% +1.84% (p=0.008 n=5+5) Flate 25.3MB ± 0% 26.9MB ± 1% +6.31% (p=0.008 n=5+5) GoParser 31.7MB ± 0% 33.2MB ± 0% +4.61% (p=0.008 n=5+5) Reflect 78.2MB ± 0% 80.2MB ± 0% +2.53% (p=0.008 n=5+5) Tar 26.6MB ± 0% 27.9MB ± 0% +5.19% (p=0.008 n=5+5) XML 42.4MB ± 0% 44.6MB ± 0% +5.20% (p=0.008 n=5+5) name old allocs/op new allocs/op delta Template 380k ± 0% 379k ± 0% -0.39% (p=0.032 n=5+5) Unicode 321k ± 0% 321k ± 0% ~ (p=0.841 n=5+5) GoTypes 1.14M ± 0% 1.14M ± 0% ~ (p=0.421 n=5+5) Compiler 4.12M ± 0% 4.14M ± 0% +0.52% (p=0.008 n=5+5) SSA 9.72M ± 0% 9.76M ± 0% +0.37% (p=0.008 n=5+5) Flate 234k ± 1% 234k ± 1% ~ (p=0.690 n=5+5) GoParser 316k ± 0% 317k ± 1% ~ (p=0.841 n=5+5) Reflect 981k ± 0% 981k ± 0% ~ (p=1.000 n=5+5) Tar 250k ± 0% 249k ± 1% ~ (p=0.151 n=5+5) XML 393k ± 0% 392k ± 0% ~ (p=0.056 n=5+5) Going beyond c=4 on my machine tends to increase CPU time and allocs without impacting real time. The CPU time numbers matter, because when there are many concurrent compilation processes, that will impact the overall throughput. The numbers above are in many ways the best case scenario; we can take full advantage of all cores. Fortunately, the most common compilation scenario is incremental re-compilation of a single package during a build/test cycle. Updates #15756 Change-Id: I6725558ca2069edec0ac5b0d1683105a9fff6bea Reviewed-on: https://go-review.googlesource.com/40693 Reviewed-by: Matthew Dempsky <mdempsky@google.com> Reviewed-by: Robert Griesemer <gri@golang.org> Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
2017-03-19 08:27:26 -07:00
)
func errorexit() {
flusherrors()
if outfile != "" {
os.Remove(outfile)
}
os.Exit(2)
}
func adderrorname(n *Node) {
if n.Op != ODOT {
return
}
old := fmt.Sprintf("%v: undefined: %v\n", n.Line(), n.Left)
if len(errors) > 0 && errors[len(errors)-1].pos.Line() == n.Pos.Line() && errors[len(errors)-1].msg == old {
errors[len(errors)-1].msg = fmt.Sprintf("%v: undefined: %v in %v\n", n.Line(), n.Left, n)
}
}
2016-12-15 17:17:01 -08:00
func adderr(pos src.XPos, format string, args ...interface{}) {
msg := fmt.Sprintf(format, args...)
// Only add the position if we have a file.
// See issue golang.org/issue/11361.
if !strings.HasSuffix(msg, ": no such file or directory") && !strings.HasSuffix(msg, ": permission denied") {
msg = fmt.Sprintf("%v: %s", linestr(pos), msg)
}
errors = append(errors, Error{
pos: pos,
msg: msg + "\n",
})
}
// byPos sorts errors by source position.
type byPos []Error
func (x byPos) Len() int { return len(x) }
func (x byPos) Less(i, j int) bool { return x[i].pos.Before(x[j].pos) }
func (x byPos) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
// flusherrors sorts errors seen so far by line number, prints them to stdout,
// and empties the errors array.
func flusherrors() {
Ctxt.Bso.Flush()
if len(errors) == 0 {
return
}
sort.Stable(byPos(errors))
for i, err := range errors {
if i == 0 || err.msg != errors[i-1].msg {
fmt.Printf("%s", err.msg)
}
}
errors = errors[:0]
}
func hcrash() {
if Debug['h'] != 0 {
flusherrors()
if outfile != "" {
os.Remove(outfile)
}
var x *int
*x = 0
}
}
2016-12-15 17:17:01 -08:00
func linestr(pos src.XPos) string {
return Ctxt.OutermostPos(pos).Format(Debug['C'] == 0, Debug['L'] == 1)
}
// lasterror keeps track of the most recently issued error.
// It is used to avoid multiple error messages on the same
// line.
var lasterror struct {
2016-12-15 17:17:01 -08:00
syntax src.XPos // source position of last syntax error
other src.XPos // source position of last non-syntax error
msg string // error message of last non-syntax error
}
[dev.inline] cmd/internal/src: replace src.Pos with syntax.Pos This replaces the src.Pos LineHist-based position tracking with the syntax.Pos implementation and updates all uses. The LineHist table is not used anymore - the respective code is still there but should be removed eventually. CL forthcoming. Passes toolstash -cmp when comparing to the master repo (with the exception of a couple of swapped assembly instructions, likely due to different instruction scheduling because the line-based sorting has changed; though this is won't affect correctness). The sizes of various important compiler data structures have increased significantly (see the various sizes_test.go files); this is probably the reason for an increase of compilation times (to be addressed). Here are the results of compilebench -count 5, run on a "quiet" machine (no apps running besides a terminal): name old time/op new time/op delta Template 256ms ± 1% 280ms ±15% +9.54% (p=0.008 n=5+5) Unicode 132ms ± 1% 132ms ± 1% ~ (p=0.690 n=5+5) GoTypes 891ms ± 1% 917ms ± 2% +2.88% (p=0.008 n=5+5) Compiler 3.84s ± 2% 3.99s ± 2% +3.95% (p=0.016 n=5+5) MakeBash 47.1s ± 1% 47.2s ± 2% ~ (p=0.841 n=5+5) name old user-ns/op new user-ns/op delta Template 309M ± 1% 326M ± 2% +5.18% (p=0.008 n=5+5) Unicode 165M ± 1% 168M ± 4% ~ (p=0.421 n=5+5) GoTypes 1.14G ± 2% 1.18G ± 1% +3.47% (p=0.008 n=5+5) Compiler 5.00G ± 1% 5.16G ± 1% +3.12% (p=0.008 n=5+5) Change-Id: I241c4246cdff627d7ecb95cac23060b38f9775ec Reviewed-on: https://go-review.googlesource.com/34273 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2016-12-09 17:15:05 -08:00
// sameline reports whether two positions a, b are on the same line.
2016-12-15 17:17:01 -08:00
func sameline(a, b src.XPos) bool {
p := Ctxt.PosTable.Pos(a)
q := Ctxt.PosTable.Pos(b)
return p.Base() == q.Base() && p.Line() == q.Line()
[dev.inline] cmd/internal/src: replace src.Pos with syntax.Pos This replaces the src.Pos LineHist-based position tracking with the syntax.Pos implementation and updates all uses. The LineHist table is not used anymore - the respective code is still there but should be removed eventually. CL forthcoming. Passes toolstash -cmp when comparing to the master repo (with the exception of a couple of swapped assembly instructions, likely due to different instruction scheduling because the line-based sorting has changed; though this is won't affect correctness). The sizes of various important compiler data structures have increased significantly (see the various sizes_test.go files); this is probably the reason for an increase of compilation times (to be addressed). Here are the results of compilebench -count 5, run on a "quiet" machine (no apps running besides a terminal): name old time/op new time/op delta Template 256ms ± 1% 280ms ±15% +9.54% (p=0.008 n=5+5) Unicode 132ms ± 1% 132ms ± 1% ~ (p=0.690 n=5+5) GoTypes 891ms ± 1% 917ms ± 2% +2.88% (p=0.008 n=5+5) Compiler 3.84s ± 2% 3.99s ± 2% +3.95% (p=0.016 n=5+5) MakeBash 47.1s ± 1% 47.2s ± 2% ~ (p=0.841 n=5+5) name old user-ns/op new user-ns/op delta Template 309M ± 1% 326M ± 2% +5.18% (p=0.008 n=5+5) Unicode 165M ± 1% 168M ± 4% ~ (p=0.421 n=5+5) GoTypes 1.14G ± 2% 1.18G ± 1% +3.47% (p=0.008 n=5+5) Compiler 5.00G ± 1% 5.16G ± 1% +3.12% (p=0.008 n=5+5) Change-Id: I241c4246cdff627d7ecb95cac23060b38f9775ec Reviewed-on: https://go-review.googlesource.com/34273 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2016-12-09 17:15:05 -08:00
}
2016-12-15 17:17:01 -08:00
func yyerrorl(pos src.XPos, format string, args ...interface{}) {
msg := fmt.Sprintf(format, args...)
if strings.HasPrefix(msg, "syntax error") {
nsyntaxerrors++
// only one syntax error per line, no matter what error
[dev.inline] cmd/internal/src: replace src.Pos with syntax.Pos This replaces the src.Pos LineHist-based position tracking with the syntax.Pos implementation and updates all uses. The LineHist table is not used anymore - the respective code is still there but should be removed eventually. CL forthcoming. Passes toolstash -cmp when comparing to the master repo (with the exception of a couple of swapped assembly instructions, likely due to different instruction scheduling because the line-based sorting has changed; though this is won't affect correctness). The sizes of various important compiler data structures have increased significantly (see the various sizes_test.go files); this is probably the reason for an increase of compilation times (to be addressed). Here are the results of compilebench -count 5, run on a "quiet" machine (no apps running besides a terminal): name old time/op new time/op delta Template 256ms ± 1% 280ms ±15% +9.54% (p=0.008 n=5+5) Unicode 132ms ± 1% 132ms ± 1% ~ (p=0.690 n=5+5) GoTypes 891ms ± 1% 917ms ± 2% +2.88% (p=0.008 n=5+5) Compiler 3.84s ± 2% 3.99s ± 2% +3.95% (p=0.016 n=5+5) MakeBash 47.1s ± 1% 47.2s ± 2% ~ (p=0.841 n=5+5) name old user-ns/op new user-ns/op delta Template 309M ± 1% 326M ± 2% +5.18% (p=0.008 n=5+5) Unicode 165M ± 1% 168M ± 4% ~ (p=0.421 n=5+5) GoTypes 1.14G ± 2% 1.18G ± 1% +3.47% (p=0.008 n=5+5) Compiler 5.00G ± 1% 5.16G ± 1% +3.12% (p=0.008 n=5+5) Change-Id: I241c4246cdff627d7ecb95cac23060b38f9775ec Reviewed-on: https://go-review.googlesource.com/34273 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2016-12-09 17:15:05 -08:00
if sameline(lasterror.syntax, pos) {
return
}
[dev.inline] cmd/internal/src: replace src.Pos with syntax.Pos This replaces the src.Pos LineHist-based position tracking with the syntax.Pos implementation and updates all uses. The LineHist table is not used anymore - the respective code is still there but should be removed eventually. CL forthcoming. Passes toolstash -cmp when comparing to the master repo (with the exception of a couple of swapped assembly instructions, likely due to different instruction scheduling because the line-based sorting has changed; though this is won't affect correctness). The sizes of various important compiler data structures have increased significantly (see the various sizes_test.go files); this is probably the reason for an increase of compilation times (to be addressed). Here are the results of compilebench -count 5, run on a "quiet" machine (no apps running besides a terminal): name old time/op new time/op delta Template 256ms ± 1% 280ms ±15% +9.54% (p=0.008 n=5+5) Unicode 132ms ± 1% 132ms ± 1% ~ (p=0.690 n=5+5) GoTypes 891ms ± 1% 917ms ± 2% +2.88% (p=0.008 n=5+5) Compiler 3.84s ± 2% 3.99s ± 2% +3.95% (p=0.016 n=5+5) MakeBash 47.1s ± 1% 47.2s ± 2% ~ (p=0.841 n=5+5) name old user-ns/op new user-ns/op delta Template 309M ± 1% 326M ± 2% +5.18% (p=0.008 n=5+5) Unicode 165M ± 1% 168M ± 4% ~ (p=0.421 n=5+5) GoTypes 1.14G ± 2% 1.18G ± 1% +3.47% (p=0.008 n=5+5) Compiler 5.00G ± 1% 5.16G ± 1% +3.12% (p=0.008 n=5+5) Change-Id: I241c4246cdff627d7ecb95cac23060b38f9775ec Reviewed-on: https://go-review.googlesource.com/34273 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2016-12-09 17:15:05 -08:00
lasterror.syntax = pos
} else {
// only one of multiple equal non-syntax errors per line
// (flusherrors shows only one of them, so we filter them
// here as best as we can (they may not appear in order)
// so that we don't count them here and exit early, and
// then have nothing to show for.)
[dev.inline] cmd/internal/src: replace src.Pos with syntax.Pos This replaces the src.Pos LineHist-based position tracking with the syntax.Pos implementation and updates all uses. The LineHist table is not used anymore - the respective code is still there but should be removed eventually. CL forthcoming. Passes toolstash -cmp when comparing to the master repo (with the exception of a couple of swapped assembly instructions, likely due to different instruction scheduling because the line-based sorting has changed; though this is won't affect correctness). The sizes of various important compiler data structures have increased significantly (see the various sizes_test.go files); this is probably the reason for an increase of compilation times (to be addressed). Here are the results of compilebench -count 5, run on a "quiet" machine (no apps running besides a terminal): name old time/op new time/op delta Template 256ms ± 1% 280ms ±15% +9.54% (p=0.008 n=5+5) Unicode 132ms ± 1% 132ms ± 1% ~ (p=0.690 n=5+5) GoTypes 891ms ± 1% 917ms ± 2% +2.88% (p=0.008 n=5+5) Compiler 3.84s ± 2% 3.99s ± 2% +3.95% (p=0.016 n=5+5) MakeBash 47.1s ± 1% 47.2s ± 2% ~ (p=0.841 n=5+5) name old user-ns/op new user-ns/op delta Template 309M ± 1% 326M ± 2% +5.18% (p=0.008 n=5+5) Unicode 165M ± 1% 168M ± 4% ~ (p=0.421 n=5+5) GoTypes 1.14G ± 2% 1.18G ± 1% +3.47% (p=0.008 n=5+5) Compiler 5.00G ± 1% 5.16G ± 1% +3.12% (p=0.008 n=5+5) Change-Id: I241c4246cdff627d7ecb95cac23060b38f9775ec Reviewed-on: https://go-review.googlesource.com/34273 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2016-12-09 17:15:05 -08:00
if sameline(lasterror.other, pos) && lasterror.msg == msg {
return
}
[dev.inline] cmd/internal/src: replace src.Pos with syntax.Pos This replaces the src.Pos LineHist-based position tracking with the syntax.Pos implementation and updates all uses. The LineHist table is not used anymore - the respective code is still there but should be removed eventually. CL forthcoming. Passes toolstash -cmp when comparing to the master repo (with the exception of a couple of swapped assembly instructions, likely due to different instruction scheduling because the line-based sorting has changed; though this is won't affect correctness). The sizes of various important compiler data structures have increased significantly (see the various sizes_test.go files); this is probably the reason for an increase of compilation times (to be addressed). Here are the results of compilebench -count 5, run on a "quiet" machine (no apps running besides a terminal): name old time/op new time/op delta Template 256ms ± 1% 280ms ±15% +9.54% (p=0.008 n=5+5) Unicode 132ms ± 1% 132ms ± 1% ~ (p=0.690 n=5+5) GoTypes 891ms ± 1% 917ms ± 2% +2.88% (p=0.008 n=5+5) Compiler 3.84s ± 2% 3.99s ± 2% +3.95% (p=0.016 n=5+5) MakeBash 47.1s ± 1% 47.2s ± 2% ~ (p=0.841 n=5+5) name old user-ns/op new user-ns/op delta Template 309M ± 1% 326M ± 2% +5.18% (p=0.008 n=5+5) Unicode 165M ± 1% 168M ± 4% ~ (p=0.421 n=5+5) GoTypes 1.14G ± 2% 1.18G ± 1% +3.47% (p=0.008 n=5+5) Compiler 5.00G ± 1% 5.16G ± 1% +3.12% (p=0.008 n=5+5) Change-Id: I241c4246cdff627d7ecb95cac23060b38f9775ec Reviewed-on: https://go-review.googlesource.com/34273 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2016-12-09 17:15:05 -08:00
lasterror.other = pos
lasterror.msg = msg
}
[dev.inline] cmd/internal/src: replace src.Pos with syntax.Pos This replaces the src.Pos LineHist-based position tracking with the syntax.Pos implementation and updates all uses. The LineHist table is not used anymore - the respective code is still there but should be removed eventually. CL forthcoming. Passes toolstash -cmp when comparing to the master repo (with the exception of a couple of swapped assembly instructions, likely due to different instruction scheduling because the line-based sorting has changed; though this is won't affect correctness). The sizes of various important compiler data structures have increased significantly (see the various sizes_test.go files); this is probably the reason for an increase of compilation times (to be addressed). Here are the results of compilebench -count 5, run on a "quiet" machine (no apps running besides a terminal): name old time/op new time/op delta Template 256ms ± 1% 280ms ±15% +9.54% (p=0.008 n=5+5) Unicode 132ms ± 1% 132ms ± 1% ~ (p=0.690 n=5+5) GoTypes 891ms ± 1% 917ms ± 2% +2.88% (p=0.008 n=5+5) Compiler 3.84s ± 2% 3.99s ± 2% +3.95% (p=0.016 n=5+5) MakeBash 47.1s ± 1% 47.2s ± 2% ~ (p=0.841 n=5+5) name old user-ns/op new user-ns/op delta Template 309M ± 1% 326M ± 2% +5.18% (p=0.008 n=5+5) Unicode 165M ± 1% 168M ± 4% ~ (p=0.421 n=5+5) GoTypes 1.14G ± 2% 1.18G ± 1% +3.47% (p=0.008 n=5+5) Compiler 5.00G ± 1% 5.16G ± 1% +3.12% (p=0.008 n=5+5) Change-Id: I241c4246cdff627d7ecb95cac23060b38f9775ec Reviewed-on: https://go-review.googlesource.com/34273 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2016-12-09 17:15:05 -08:00
adderr(pos, "%s", msg)
hcrash()
nerrors++
if nsavederrors+nerrors >= 10 && Debug['e'] == 0 {
flusherrors()
[dev.inline] cmd/internal/src: replace src.Pos with syntax.Pos This replaces the src.Pos LineHist-based position tracking with the syntax.Pos implementation and updates all uses. The LineHist table is not used anymore - the respective code is still there but should be removed eventually. CL forthcoming. Passes toolstash -cmp when comparing to the master repo (with the exception of a couple of swapped assembly instructions, likely due to different instruction scheduling because the line-based sorting has changed; though this is won't affect correctness). The sizes of various important compiler data structures have increased significantly (see the various sizes_test.go files); this is probably the reason for an increase of compilation times (to be addressed). Here are the results of compilebench -count 5, run on a "quiet" machine (no apps running besides a terminal): name old time/op new time/op delta Template 256ms ± 1% 280ms ±15% +9.54% (p=0.008 n=5+5) Unicode 132ms ± 1% 132ms ± 1% ~ (p=0.690 n=5+5) GoTypes 891ms ± 1% 917ms ± 2% +2.88% (p=0.008 n=5+5) Compiler 3.84s ± 2% 3.99s ± 2% +3.95% (p=0.016 n=5+5) MakeBash 47.1s ± 1% 47.2s ± 2% ~ (p=0.841 n=5+5) name old user-ns/op new user-ns/op delta Template 309M ± 1% 326M ± 2% +5.18% (p=0.008 n=5+5) Unicode 165M ± 1% 168M ± 4% ~ (p=0.421 n=5+5) GoTypes 1.14G ± 2% 1.18G ± 1% +3.47% (p=0.008 n=5+5) Compiler 5.00G ± 1% 5.16G ± 1% +3.12% (p=0.008 n=5+5) Change-Id: I241c4246cdff627d7ecb95cac23060b38f9775ec Reviewed-on: https://go-review.googlesource.com/34273 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2016-12-09 17:15:05 -08:00
fmt.Printf("%v: too many errors\n", linestr(pos))
errorexit()
}
}
func yyerrorv(lang string, format string, args ...interface{}) {
what := fmt.Sprintf(format, args...)
yyerrorl(lineno, "%s requires %s or later (-lang was set to %s; check go.mod)", what, lang, flag_lang)
}
func yyerror(format string, args ...interface{}) {
yyerrorl(lineno, format, args...)
}
func Warn(fmt_ string, args ...interface{}) {
Warnl(lineno, fmt_, args...)
}
2016-12-15 17:17:01 -08:00
func Warnl(line src.XPos, fmt_ string, args ...interface{}) {
adderr(line, fmt_, args...)
if Debug['m'] != 0 {
flusherrors()
}
}
func Fatalf(fmt_ string, args ...interface{}) {
flusherrors()
if Debug_panic != 0 || nsavederrors+nerrors == 0 {
fmt.Printf("%v: internal compiler error: ", linestr(lineno))
fmt.Printf(fmt_, args...)
fmt.Printf("\n")
// If this is a released compiler version, ask for a bug report.
if strings.HasPrefix(objabi.Version, "go") {
fmt.Printf("\n")
fmt.Printf("Please file a bug report including a short program that triggers the error.\n")
fmt.Printf("https://golang.org/issue/new\n")
} else {
// Not a release; dump a stack trace, too.
fmt.Println()
os.Stdout.Write(debug.Stack())
fmt.Println()
}
}
hcrash()
errorexit()
}
// hasUniquePos reports whether n has a unique position that can be
// used for reporting error messages.
//
// It's primarily used to distinguish references to named objects,
// whose Pos will point back to their declaration position rather than
// their usage position.
func hasUniquePos(n *Node) bool {
switch n.Op {
case ONAME, OPACK:
return false
case OLITERAL, OTYPE:
if n.Sym != nil {
return false
}
}
if !n.Pos.IsKnown() {
if Debug['K'] != 0 {
Warn("setlineno: unknown position (line 0)")
}
return false
}
return true
}
func setlineno(n *Node) src.XPos {
lno := lineno
if n != nil && hasUniquePos(n) {
lineno = n.Pos
}
return lno
}
func lookup(name string) *types.Sym {
return localpkg.Lookup(name)
}
// lookupN looks up the symbol starting with prefix and ending with
// the decimal n. If prefix is too long, lookupN panics.
func lookupN(prefix string, n int) *types.Sym {
var buf [20]byte // plenty long enough for all current users
copy(buf[:], prefix)
b := strconv.AppendInt(buf[:len(prefix)], int64(n), 10)
return localpkg.LookupBytes(b)
}
// autolabel generates a new Name node for use with
// an automatically generated label.
// prefix is a short mnemonic (e.g. ".s" for switch)
// to help with debugging.
// It should begin with "." to avoid conflicts with
// user labels.
func autolabel(prefix string) *types.Sym {
if prefix[0] != '.' {
Fatalf("autolabel prefix must start with '.', have %q", prefix)
}
fn := Curfn
if Curfn == nil {
Fatalf("autolabel outside function")
}
n := fn.Func.Label
fn.Func.Label++
return lookupN(prefix, int(n))
}
func restrictlookup(name string, pkg *types.Pkg) *types.Sym {
if !types.IsExported(name) && pkg != localpkg {
yyerror("cannot refer to unexported name %s.%s", pkg.Name, name)
}
return pkg.Lookup(name)
}
// find all the exported symbols in package opkg
// and make them available in the current package
func importdot(opkg *types.Pkg, pack *Node) {
n := 0
for _, s := range opkg.Syms {
if s.Def == nil {
continue
}
if !types.IsExported(s.Name) || strings.ContainsRune(s.Name, 0xb7) { // 0xb7 = center dot
continue
}
s1 := lookup(s.Name)
if s1.Def != nil {
pkgerror := fmt.Sprintf("during import %q", opkg.Path)
redeclare(lineno, s1, pkgerror)
continue
}
s1.Def = s.Def
s1.Block = s.Block
if asNode(s1.Def).Name == nil {
Dump("s1def", asNode(s1.Def))
Fatalf("missing Name")
}
asNode(s1.Def).Name.Pack = pack
s1.Origpkg = opkg
n++
}
if n == 0 {
// can't possibly be used - there were no symbols
yyerrorl(pack.Pos, "imported and not used: %q", opkg.Path)
}
}
func nod(op Op, nleft, nright *Node) *Node {
return nodl(lineno, op, nleft, nright)
}
func nodl(pos src.XPos, op Op, nleft, nright *Node) *Node {
2017-01-31 14:32:11 -08:00
var n *Node
switch op {
case OCLOSURE, ODCLFUNC:
2017-01-31 14:32:11 -08:00
var x struct {
n Node
f Func
2017-01-31 14:32:11 -08:00
}
n = &x.n
n.Func = &x.f
case ONAME:
Fatalf("use newname instead")
case OLABEL, OPACK:
2017-01-31 14:32:11 -08:00
var x struct {
n Node
m Name
2017-01-31 14:32:11 -08:00
}
n = &x.n
n.Name = &x.m
2017-01-31 14:32:11 -08:00
default:
n = new(Node)
}
2017-01-31 14:32:11 -08:00
n.Op = op
n.Left = nleft
n.Right = nright
n.Pos = pos
2017-01-31 14:32:11 -08:00
n.Xoffset = BADWIDTH
n.Orig = n
return n
}
// newname returns a new ONAME Node associated with symbol s.
func newname(s *types.Sym) *Node {
n := newnamel(lineno, s)
n.Name.Curfn = Curfn
return n
}
// newname returns a new ONAME Node associated with symbol s at position pos.
// The caller is responsible for setting n.Name.Curfn.
func newnamel(pos src.XPos, s *types.Sym) *Node {
if s == nil {
Fatalf("newnamel nil")
}
var x struct {
n Node
m Name
p Param
}
n := &x.n
n.Name = &x.m
n.Name.Param = &x.p
n.Op = ONAME
n.Pos = pos
n.Orig = n
n.Sym = s
return n
}
// nodSym makes a Node with Op op and with the Left field set to left
// and the Sym field set to sym. This is for ODOT and friends.
func nodSym(op Op, left *Node, sym *types.Sym) *Node {
return nodlSym(lineno, op, left, sym)
}
// nodlSym makes a Node with position Pos, with Op op, and with the Left field set to left
// and the Sym field set to sym. This is for ODOT and friends.
func nodlSym(pos src.XPos, op Op, left *Node, sym *types.Sym) *Node {
n := nodl(pos, op, left, nil)
n.Sym = sym
return n
}
// rawcopy returns a shallow copy of n.
// Note: copy or sepcopy (rather than rawcopy) is usually the
// correct choice (see comment with Node.copy, below).
func (n *Node) rawcopy() *Node {
copy := *n
return &copy
}
// sepcopy returns a separate shallow copy of n, with the copy's
// Orig pointing to itself.
func (n *Node) sepcopy() *Node {
copy := *n
copy.Orig = &copy
return &copy
}
// copy returns shallow copy of n and adjusts the copy's Orig if
// necessary: In general, if n.Orig points to itself, the copy's
// Orig should point to itself as well. Otherwise, if n is modified,
// the copy's Orig node appears modified, too, and then doesn't
// represent the original node anymore.
// (This caused the wrong complit Op to be used when printing error
// messages; see issues #26855, #27765).
func (n *Node) copy() *Node {
copy := *n
if n.Orig == n {
copy.Orig = &copy
}
return &copy
}
// methcmp sorts methods by symbol.
type methcmp []*types.Field
func (x methcmp) Len() int { return len(x) }
func (x methcmp) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
func (x methcmp) Less(i, j int) bool { return x[i].Sym.Less(x[j].Sym) }
func nodintconst(v int64) *Node {
u := new(Mpint)
u.SetInt64(v)
return nodlit(Val{u})
}
func nodnil() *Node {
return nodlit(Val{new(NilVal)})
}
func nodbool(b bool) *Node {
return nodlit(Val{b})
}
func nodstr(s string) *Node {
return nodlit(Val{s})
}
// treecopy recursively copies n, with the exception of
// ONAME, OLITERAL, OTYPE, and ONONAME leaves.
// If pos.IsKnown(), it sets the source position of newly
// allocated nodes to pos.
2016-12-15 17:17:01 -08:00
func treecopy(n *Node, pos src.XPos) *Node {
if n == nil {
return nil
}
switch n.Op {
default:
m := n.sepcopy()
[dev.inline] cmd/internal/src: replace src.Pos with syntax.Pos This replaces the src.Pos LineHist-based position tracking with the syntax.Pos implementation and updates all uses. The LineHist table is not used anymore - the respective code is still there but should be removed eventually. CL forthcoming. Passes toolstash -cmp when comparing to the master repo (with the exception of a couple of swapped assembly instructions, likely due to different instruction scheduling because the line-based sorting has changed; though this is won't affect correctness). The sizes of various important compiler data structures have increased significantly (see the various sizes_test.go files); this is probably the reason for an increase of compilation times (to be addressed). Here are the results of compilebench -count 5, run on a "quiet" machine (no apps running besides a terminal): name old time/op new time/op delta Template 256ms ± 1% 280ms ±15% +9.54% (p=0.008 n=5+5) Unicode 132ms ± 1% 132ms ± 1% ~ (p=0.690 n=5+5) GoTypes 891ms ± 1% 917ms ± 2% +2.88% (p=0.008 n=5+5) Compiler 3.84s ± 2% 3.99s ± 2% +3.95% (p=0.016 n=5+5) MakeBash 47.1s ± 1% 47.2s ± 2% ~ (p=0.841 n=5+5) name old user-ns/op new user-ns/op delta Template 309M ± 1% 326M ± 2% +5.18% (p=0.008 n=5+5) Unicode 165M ± 1% 168M ± 4% ~ (p=0.421 n=5+5) GoTypes 1.14G ± 2% 1.18G ± 1% +3.47% (p=0.008 n=5+5) Compiler 5.00G ± 1% 5.16G ± 1% +3.12% (p=0.008 n=5+5) Change-Id: I241c4246cdff627d7ecb95cac23060b38f9775ec Reviewed-on: https://go-review.googlesource.com/34273 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2016-12-09 17:15:05 -08:00
m.Left = treecopy(n.Left, pos)
m.Right = treecopy(n.Right, pos)
m.List.Set(listtreecopy(n.List.Slice(), pos))
if pos.IsKnown() {
m.Pos = pos
}
if m.Name != nil && n.Op != ODCLFIELD {
Dump("treecopy", n)
Fatalf("treecopy Name")
}
return m
case OPACK:
// OPACK nodes are never valid in const value declarations,
// but allow them like any other declared symbol to avoid
// crashing (golang.org/issue/11361).
fallthrough
case ONAME, ONONAME, OLITERAL, OTYPE:
return n
}
}
// isNil reports whether n represents the universal untyped zero value "nil".
func (n *Node) isNil() bool {
// Check n.Orig because constant propagation may produce typed nil constants,
// which don't exist in the Go spec.
return Isconst(n.Orig, CTNIL)
}
func isptrto(t *types.Type, et types.EType) bool {
if t == nil {
return false
}
if !t.IsPtr() {
return false
}
t = t.Elem()
if t == nil {
return false
}
if t.Etype != et {
return false
}
return true
}
func (n *Node) isBlank() bool {
if n == nil {
return false
}
return n.Sym.IsBlank()
}
// methtype returns the underlying type, if any,
// that owns methods with receiver parameter t.
// The result is either a named type or an anonymous struct.
func methtype(t *types.Type) *types.Type {
if t == nil {
return nil
}
// Strip away pointer if it's there.
if t.IsPtr() {
if t.Sym != nil {
return nil
}
t = t.Elem()
if t == nil {
return nil
}
}
// Must be a named type or anonymous struct.
if t.Sym == nil && !t.IsStruct() {
return nil
}
// Check types.
if issimple[t.Etype] {
return t
}
switch t.Etype {
case TARRAY, TCHAN, TFUNC, TMAP, TSLICE, TSTRING, TSTRUCT:
return t
}
return nil
}
// Is type src assignment compatible to type dst?
// If so, return op code to use in conversion.
// If not, return OXXX.
func assignop(src, dst *types.Type, why *string) Op {
if why != nil {
*why = ""
}
if src == dst {
return OCONVNOP
}
if src == nil || dst == nil || src.Etype == TFORW || dst.Etype == TFORW || src.Orig == nil || dst.Orig == nil {
return OXXX
}
// 1. src type is identical to dst.
if types.Identical(src, dst) {
return OCONVNOP
}
// 2. src and dst have identical underlying types
// and either src or dst is not a named type or
// both are empty interface types.
// For assignable but different non-empty interface types,
// we want to recompute the itab. Recomputing the itab ensures
// that itabs are unique (thus an interface with a compile-time
// type I has an itab with interface type I).
if types.Identical(src.Orig, dst.Orig) {
if src.IsEmptyInterface() {
// Conversion between two empty interfaces
// requires no code.
return OCONVNOP
}
if (src.Sym == nil || dst.Sym == nil) && !src.IsInterface() {
// Conversion between two types, at least one unnamed,
// needs no conversion. The exception is nonempty interfaces
// which need to have their itab updated.
return OCONVNOP
}
}
// 3. dst is an interface type and src implements dst.
if dst.IsInterface() && src.Etype != TNIL {
var missing, have *types.Field
var ptr int
if implements(src, dst, &missing, &have, &ptr) {
return OCONVIFACE
}
// we'll have complained about this method anyway, suppress spurious messages.
cmd/compile: pack bool fields in Node, Name, Func and Type structs to bitsets This reduces compiler memory usage by up to 4% - see compilebench results below. name old time/op new time/op delta Template 245ms ± 4% 241ms ± 2% -1.88% (p=0.029 n=10+10) Unicode 126ms ± 3% 124ms ± 3% ~ (p=0.105 n=10+10) GoTypes 805ms ± 2% 813ms ± 3% ~ (p=0.515 n=8+10) Compiler 3.95s ± 2% 3.83s ± 1% -2.96% (p=0.000 n=9+10) MakeBash 47.4s ± 4% 46.6s ± 1% -1.59% (p=0.028 n=9+10) name old user-ns/op new user-ns/op delta Template 324M ± 5% 326M ± 3% ~ (p=0.935 n=10+10) Unicode 186M ± 5% 178M ±10% ~ (p=0.067 n=9+10) GoTypes 1.08G ± 7% 1.09G ± 4% ~ (p=0.956 n=10+10) Compiler 5.34G ± 4% 5.31G ± 1% ~ (p=0.501 n=10+8) name old alloc/op new alloc/op delta Template 41.0MB ± 0% 39.8MB ± 0% -3.03% (p=0.000 n=10+10) Unicode 32.3MB ± 0% 31.0MB ± 0% -4.13% (p=0.000 n=10+10) GoTypes 119MB ± 0% 116MB ± 0% -2.39% (p=0.000 n=10+10) Compiler 499MB ± 0% 487MB ± 0% -2.48% (p=0.000 n=10+10) name old allocs/op new allocs/op delta Template 380k ± 1% 379k ± 1% ~ (p=0.436 n=10+10) Unicode 324k ± 1% 324k ± 0% ~ (p=0.853 n=10+10) GoTypes 1.15M ± 0% 1.15M ± 0% ~ (p=0.481 n=10+10) Compiler 4.41M ± 0% 4.41M ± 0% -0.12% (p=0.007 n=10+10) name old text-bytes new text-bytes delta HelloSize 623k ± 0% 623k ± 0% ~ (all equal) CmdGoSize 6.64M ± 0% 6.64M ± 0% ~ (all equal) name old data-bytes new data-bytes delta HelloSize 5.81k ± 0% 5.81k ± 0% ~ (all equal) CmdGoSize 238k ± 0% 238k ± 0% ~ (all equal) name old bss-bytes new bss-bytes delta HelloSize 134k ± 0% 134k ± 0% ~ (all equal) CmdGoSize 152k ± 0% 152k ± 0% ~ (all equal) name old exe-bytes new exe-bytes delta HelloSize 967k ± 0% 967k ± 0% ~ (all equal) CmdGoSize 10.2M ± 0% 10.2M ± 0% ~ (all equal) Change-Id: I1f40af738254892bd6c8ba2eb43390b175753d52 Reviewed-on: https://go-review.googlesource.com/37445 Reviewed-by: Matthew Dempsky <mdempsky@google.com> Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
2017-02-27 19:56:38 +02:00
if have != nil && have.Sym == missing.Sym && (have.Type.Broke() || missing.Type.Broke()) {
return OCONVIFACE
}
if why != nil {
if isptrto(src, TINTER) {
*why = fmt.Sprintf(":\n\t%v is pointer to interface, not interface", src)
cmd/compile: pack bool fields in Node, Name, Func and Type structs to bitsets This reduces compiler memory usage by up to 4% - see compilebench results below. name old time/op new time/op delta Template 245ms ± 4% 241ms ± 2% -1.88% (p=0.029 n=10+10) Unicode 126ms ± 3% 124ms ± 3% ~ (p=0.105 n=10+10) GoTypes 805ms ± 2% 813ms ± 3% ~ (p=0.515 n=8+10) Compiler 3.95s ± 2% 3.83s ± 1% -2.96% (p=0.000 n=9+10) MakeBash 47.4s ± 4% 46.6s ± 1% -1.59% (p=0.028 n=9+10) name old user-ns/op new user-ns/op delta Template 324M ± 5% 326M ± 3% ~ (p=0.935 n=10+10) Unicode 186M ± 5% 178M ±10% ~ (p=0.067 n=9+10) GoTypes 1.08G ± 7% 1.09G ± 4% ~ (p=0.956 n=10+10) Compiler 5.34G ± 4% 5.31G ± 1% ~ (p=0.501 n=10+8) name old alloc/op new alloc/op delta Template 41.0MB ± 0% 39.8MB ± 0% -3.03% (p=0.000 n=10+10) Unicode 32.3MB ± 0% 31.0MB ± 0% -4.13% (p=0.000 n=10+10) GoTypes 119MB ± 0% 116MB ± 0% -2.39% (p=0.000 n=10+10) Compiler 499MB ± 0% 487MB ± 0% -2.48% (p=0.000 n=10+10) name old allocs/op new allocs/op delta Template 380k ± 1% 379k ± 1% ~ (p=0.436 n=10+10) Unicode 324k ± 1% 324k ± 0% ~ (p=0.853 n=10+10) GoTypes 1.15M ± 0% 1.15M ± 0% ~ (p=0.481 n=10+10) Compiler 4.41M ± 0% 4.41M ± 0% -0.12% (p=0.007 n=10+10) name old text-bytes new text-bytes delta HelloSize 623k ± 0% 623k ± 0% ~ (all equal) CmdGoSize 6.64M ± 0% 6.64M ± 0% ~ (all equal) name old data-bytes new data-bytes delta HelloSize 5.81k ± 0% 5.81k ± 0% ~ (all equal) CmdGoSize 238k ± 0% 238k ± 0% ~ (all equal) name old bss-bytes new bss-bytes delta HelloSize 134k ± 0% 134k ± 0% ~ (all equal) CmdGoSize 152k ± 0% 152k ± 0% ~ (all equal) name old exe-bytes new exe-bytes delta HelloSize 967k ± 0% 967k ± 0% ~ (all equal) CmdGoSize 10.2M ± 0% 10.2M ± 0% ~ (all equal) Change-Id: I1f40af738254892bd6c8ba2eb43390b175753d52 Reviewed-on: https://go-review.googlesource.com/37445 Reviewed-by: Matthew Dempsky <mdempsky@google.com> Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
2017-02-27 19:56:38 +02:00
} else if have != nil && have.Sym == missing.Sym && have.Nointerface() {
*why = fmt.Sprintf(":\n\t%v does not implement %v (%v method is marked 'nointerface')", src, dst, missing.Sym)
} else if have != nil && have.Sym == missing.Sym {
*why = fmt.Sprintf(":\n\t%v does not implement %v (wrong type for %v method)\n"+
"\t\thave %v%0S\n\t\twant %v%0S", src, dst, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
} else if ptr != 0 {
*why = fmt.Sprintf(":\n\t%v does not implement %v (%v method has pointer receiver)", src, dst, missing.Sym)
} else if have != nil {
*why = fmt.Sprintf(":\n\t%v does not implement %v (missing %v method)\n"+
"\t\thave %v%0S\n\t\twant %v%0S", src, dst, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
} else {
*why = fmt.Sprintf(":\n\t%v does not implement %v (missing %v method)", src, dst, missing.Sym)
}
}
return OXXX
}
if isptrto(dst, TINTER) {
if why != nil {
*why = fmt.Sprintf(":\n\t%v is pointer to interface, not interface", dst)
}
return OXXX
}
if src.IsInterface() && dst.Etype != TBLANK {
var missing, have *types.Field
var ptr int
if why != nil && implements(dst, src, &missing, &have, &ptr) {
*why = ": need type assertion"
}
return OXXX
}
// 4. src is a bidirectional channel value, dst is a channel type,
// src and dst have identical element types, and
// either src or dst is not a named type.
if src.IsChan() && src.ChanDir() == types.Cboth && dst.IsChan() {
if types.Identical(src.Elem(), dst.Elem()) && (src.Sym == nil || dst.Sym == nil) {
return OCONVNOP
}
}
// 5. src is the predeclared identifier nil and dst is a nillable type.
if src.Etype == TNIL {
switch dst.Etype {
case TPTR,
TFUNC,
TMAP,
TCHAN,
TINTER,
TSLICE:
return OCONVNOP
}
}
// 6. rule about untyped constants - already converted by defaultlit.
// 7. Any typed value can be assigned to the blank identifier.
if dst.Etype == TBLANK {
return OCONVNOP
}
return OXXX
}
// Can we convert a value of type src to a value of type dst?
// If so, return op code to use in conversion (maybe OCONVNOP).
// If not, return OXXX.
// srcConstant indicates whether the value of type src is a constant.
func convertop(srcConstant bool, src, dst *types.Type, why *string) Op {
if why != nil {
*why = ""
}
if src == dst {
return OCONVNOP
}
if src == nil || dst == nil {
return OXXX
}
cmd/compile: add go:notinheap type pragma This adds a //go:notinheap pragma for declarations of types that must not be heap allocated. We ensure these rules by disallowing new(T), make([]T), append([]T), or implicit allocation of T, by disallowing conversions to notinheap types, and by propagating notinheap to any struct or array that contains notinheap elements. The utility of this pragma is that we can eliminate write barriers for writes to pointers to go:notinheap types, since the write barrier is guaranteed to be a no-op. This will let us mark several scheduler and memory allocator structures as go:notinheap, which will let us disallow write barriers in the scheduler and memory allocator much more thoroughly and also eliminate some problematic hybrid write barriers. This also makes go:nowritebarrierrec and go:yeswritebarrierrec much more powerful. Currently we use go:nowritebarrier all over the place, but it's almost never what you actually want: when write barriers are illegal, they're typically illegal for a whole dynamic scope. Partly this is because go:nowritebarrier has been around longer, but it's also because go:nowritebarrierrec couldn't be used in situations that had no-op write barriers or where some nested scope did allow write barriers. go:notinheap eliminates many no-op write barriers and go:yeswritebarrierrec makes it possible to opt back in to write barriers, so these two changes will let us use go:nowritebarrierrec far more liberally. This updates #13386, which is about controlling pointers from non-GC'd memory to GC'd memory. That would require some additional pragma (or pragmas), but could build on this pragma. Change-Id: I6314f8f4181535dd166887c9ec239977b54940bd Reviewed-on: https://go-review.googlesource.com/30939 Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2016-10-11 22:53:27 -04:00
// Conversions from regular to go:notinheap are not allowed
// (unless it's unsafe.Pointer). These are runtime-specific
// rules.
// (a) Disallow (*T) to (*U) where T is go:notinheap but U isn't.
cmd/compile: pack bool fields in Node, Name, Func and Type structs to bitsets This reduces compiler memory usage by up to 4% - see compilebench results below. name old time/op new time/op delta Template 245ms ± 4% 241ms ± 2% -1.88% (p=0.029 n=10+10) Unicode 126ms ± 3% 124ms ± 3% ~ (p=0.105 n=10+10) GoTypes 805ms ± 2% 813ms ± 3% ~ (p=0.515 n=8+10) Compiler 3.95s ± 2% 3.83s ± 1% -2.96% (p=0.000 n=9+10) MakeBash 47.4s ± 4% 46.6s ± 1% -1.59% (p=0.028 n=9+10) name old user-ns/op new user-ns/op delta Template 324M ± 5% 326M ± 3% ~ (p=0.935 n=10+10) Unicode 186M ± 5% 178M ±10% ~ (p=0.067 n=9+10) GoTypes 1.08G ± 7% 1.09G ± 4% ~ (p=0.956 n=10+10) Compiler 5.34G ± 4% 5.31G ± 1% ~ (p=0.501 n=10+8) name old alloc/op new alloc/op delta Template 41.0MB ± 0% 39.8MB ± 0% -3.03% (p=0.000 n=10+10) Unicode 32.3MB ± 0% 31.0MB ± 0% -4.13% (p=0.000 n=10+10) GoTypes 119MB ± 0% 116MB ± 0% -2.39% (p=0.000 n=10+10) Compiler 499MB ± 0% 487MB ± 0% -2.48% (p=0.000 n=10+10) name old allocs/op new allocs/op delta Template 380k ± 1% 379k ± 1% ~ (p=0.436 n=10+10) Unicode 324k ± 1% 324k ± 0% ~ (p=0.853 n=10+10) GoTypes 1.15M ± 0% 1.15M ± 0% ~ (p=0.481 n=10+10) Compiler 4.41M ± 0% 4.41M ± 0% -0.12% (p=0.007 n=10+10) name old text-bytes new text-bytes delta HelloSize 623k ± 0% 623k ± 0% ~ (all equal) CmdGoSize 6.64M ± 0% 6.64M ± 0% ~ (all equal) name old data-bytes new data-bytes delta HelloSize 5.81k ± 0% 5.81k ± 0% ~ (all equal) CmdGoSize 238k ± 0% 238k ± 0% ~ (all equal) name old bss-bytes new bss-bytes delta HelloSize 134k ± 0% 134k ± 0% ~ (all equal) CmdGoSize 152k ± 0% 152k ± 0% ~ (all equal) name old exe-bytes new exe-bytes delta HelloSize 967k ± 0% 967k ± 0% ~ (all equal) CmdGoSize 10.2M ± 0% 10.2M ± 0% ~ (all equal) Change-Id: I1f40af738254892bd6c8ba2eb43390b175753d52 Reviewed-on: https://go-review.googlesource.com/37445 Reviewed-by: Matthew Dempsky <mdempsky@google.com> Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
2017-02-27 19:56:38 +02:00
if src.IsPtr() && dst.IsPtr() && dst.Elem().NotInHeap() && !src.Elem().NotInHeap() {
cmd/compile: add go:notinheap type pragma This adds a //go:notinheap pragma for declarations of types that must not be heap allocated. We ensure these rules by disallowing new(T), make([]T), append([]T), or implicit allocation of T, by disallowing conversions to notinheap types, and by propagating notinheap to any struct or array that contains notinheap elements. The utility of this pragma is that we can eliminate write barriers for writes to pointers to go:notinheap types, since the write barrier is guaranteed to be a no-op. This will let us mark several scheduler and memory allocator structures as go:notinheap, which will let us disallow write barriers in the scheduler and memory allocator much more thoroughly and also eliminate some problematic hybrid write barriers. This also makes go:nowritebarrierrec and go:yeswritebarrierrec much more powerful. Currently we use go:nowritebarrier all over the place, but it's almost never what you actually want: when write barriers are illegal, they're typically illegal for a whole dynamic scope. Partly this is because go:nowritebarrier has been around longer, but it's also because go:nowritebarrierrec couldn't be used in situations that had no-op write barriers or where some nested scope did allow write barriers. go:notinheap eliminates many no-op write barriers and go:yeswritebarrierrec makes it possible to opt back in to write barriers, so these two changes will let us use go:nowritebarrierrec far more liberally. This updates #13386, which is about controlling pointers from non-GC'd memory to GC'd memory. That would require some additional pragma (or pragmas), but could build on this pragma. Change-Id: I6314f8f4181535dd166887c9ec239977b54940bd Reviewed-on: https://go-review.googlesource.com/30939 Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2016-10-11 22:53:27 -04:00
if why != nil {
*why = fmt.Sprintf(":\n\t%v is go:notinheap, but %v is not", dst.Elem(), src.Elem())
}
return OXXX
cmd/compile: add go:notinheap type pragma This adds a //go:notinheap pragma for declarations of types that must not be heap allocated. We ensure these rules by disallowing new(T), make([]T), append([]T), or implicit allocation of T, by disallowing conversions to notinheap types, and by propagating notinheap to any struct or array that contains notinheap elements. The utility of this pragma is that we can eliminate write barriers for writes to pointers to go:notinheap types, since the write barrier is guaranteed to be a no-op. This will let us mark several scheduler and memory allocator structures as go:notinheap, which will let us disallow write barriers in the scheduler and memory allocator much more thoroughly and also eliminate some problematic hybrid write barriers. This also makes go:nowritebarrierrec and go:yeswritebarrierrec much more powerful. Currently we use go:nowritebarrier all over the place, but it's almost never what you actually want: when write barriers are illegal, they're typically illegal for a whole dynamic scope. Partly this is because go:nowritebarrier has been around longer, but it's also because go:nowritebarrierrec couldn't be used in situations that had no-op write barriers or where some nested scope did allow write barriers. go:notinheap eliminates many no-op write barriers and go:yeswritebarrierrec makes it possible to opt back in to write barriers, so these two changes will let us use go:nowritebarrierrec far more liberally. This updates #13386, which is about controlling pointers from non-GC'd memory to GC'd memory. That would require some additional pragma (or pragmas), but could build on this pragma. Change-Id: I6314f8f4181535dd166887c9ec239977b54940bd Reviewed-on: https://go-review.googlesource.com/30939 Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2016-10-11 22:53:27 -04:00
}
// (b) Disallow string to []T where T is go:notinheap.
if src.IsString() && dst.IsSlice() && dst.Elem().NotInHeap() && (dst.Elem().Etype == types.Bytetype.Etype || dst.Elem().Etype == types.Runetype.Etype) {
if why != nil {
*why = fmt.Sprintf(":\n\t%v is go:notinheap", dst.Elem())
}
return OXXX
}
cmd/compile: add go:notinheap type pragma This adds a //go:notinheap pragma for declarations of types that must not be heap allocated. We ensure these rules by disallowing new(T), make([]T), append([]T), or implicit allocation of T, by disallowing conversions to notinheap types, and by propagating notinheap to any struct or array that contains notinheap elements. The utility of this pragma is that we can eliminate write barriers for writes to pointers to go:notinheap types, since the write barrier is guaranteed to be a no-op. This will let us mark several scheduler and memory allocator structures as go:notinheap, which will let us disallow write barriers in the scheduler and memory allocator much more thoroughly and also eliminate some problematic hybrid write barriers. This also makes go:nowritebarrierrec and go:yeswritebarrierrec much more powerful. Currently we use go:nowritebarrier all over the place, but it's almost never what you actually want: when write barriers are illegal, they're typically illegal for a whole dynamic scope. Partly this is because go:nowritebarrier has been around longer, but it's also because go:nowritebarrierrec couldn't be used in situations that had no-op write barriers or where some nested scope did allow write barriers. go:notinheap eliminates many no-op write barriers and go:yeswritebarrierrec makes it possible to opt back in to write barriers, so these two changes will let us use go:nowritebarrierrec far more liberally. This updates #13386, which is about controlling pointers from non-GC'd memory to GC'd memory. That would require some additional pragma (or pragmas), but could build on this pragma. Change-Id: I6314f8f4181535dd166887c9ec239977b54940bd Reviewed-on: https://go-review.googlesource.com/30939 Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2016-10-11 22:53:27 -04:00
// 1. src can be assigned to dst.
op := assignop(src, dst, why)
if op != OXXX {
return op
}
// The rules for interfaces are no different in conversions
// than assignments. If interfaces are involved, stop now
// with the good message from assignop.
// Otherwise clear the error.
if src.IsInterface() || dst.IsInterface() {
return OXXX
}
if why != nil {
*why = ""
}
// 2. Ignoring struct tags, src and dst have identical underlying types.
if types.IdenticalIgnoreTags(src.Orig, dst.Orig) {
return OCONVNOP
}
// 3. src and dst are unnamed pointer types and, ignoring struct tags,
// their base types have identical underlying types.
if src.IsPtr() && dst.IsPtr() && src.Sym == nil && dst.Sym == nil {
if types.IdenticalIgnoreTags(src.Elem().Orig, dst.Elem().Orig) {
return OCONVNOP
}
}
// 4. src and dst are both integer or floating point types.
if (src.IsInteger() || src.IsFloat()) && (dst.IsInteger() || dst.IsFloat()) {
if simtype[src.Etype] == simtype[dst.Etype] {
return OCONVNOP
}
return OCONV
}
// 5. src and dst are both complex types.
if src.IsComplex() && dst.IsComplex() {
if simtype[src.Etype] == simtype[dst.Etype] {
return OCONVNOP
}
return OCONV
}
// Special case for constant conversions: any numeric
// conversion is potentially okay. We'll validate further
// within evconst. See #38117.
if srcConstant && (src.IsInteger() || src.IsFloat() || src.IsComplex()) && (dst.IsInteger() || dst.IsFloat() || dst.IsComplex()) {
return OCONV
}
// 6. src is an integer or has type []byte or []rune
// and dst is a string type.
if src.IsInteger() && dst.IsString() {
return ORUNESTR
}
if src.IsSlice() && dst.IsString() {
if src.Elem().Etype == types.Bytetype.Etype {
cmd/compile: bulk rename This change does a bulk rename of several identifiers in the compiler. See #27167 and https://docs.google.com/document/d/19_ExiylD9MRfeAjKIfEsMU1_RGhuxB9sA0b5Zv7byVI/ for context and for discussion of these particular renames. Commands run to generate this change: gorename -from '"cmd/compile/internal/gc".OPROC' -to OGO gorename -from '"cmd/compile/internal/gc".OCOM' -to OBITNOT gorename -from '"cmd/compile/internal/gc".OMINUS' -to ONEG gorename -from '"cmd/compile/internal/gc".OIND' -to ODEREF gorename -from '"cmd/compile/internal/gc".OARRAYBYTESTR' -to OBYTES2STR gorename -from '"cmd/compile/internal/gc".OARRAYBYTESTRTMP' -to OBYTES2STRTMP gorename -from '"cmd/compile/internal/gc".OARRAYRUNESTR' -to ORUNES2STR gorename -from '"cmd/compile/internal/gc".OSTRARRAYBYTE' -to OSTR2BYTES gorename -from '"cmd/compile/internal/gc".OSTRARRAYBYTETMP' -to OSTR2BYTESTMP gorename -from '"cmd/compile/internal/gc".OSTRARRAYRUNE' -to OSTR2RUNES gorename -from '"cmd/compile/internal/gc".Etop' -to ctxStmt gorename -from '"cmd/compile/internal/gc".Erv' -to ctxExpr gorename -from '"cmd/compile/internal/gc".Ecall' -to ctxCallee gorename -from '"cmd/compile/internal/gc".Efnstruct' -to ctxMultiOK gorename -from '"cmd/compile/internal/gc".Easgn' -to ctxAssign gorename -from '"cmd/compile/internal/gc".Ecomplit' -to ctxCompLit Not altered: parameters and local variables (mostly in typecheck.go) named top, which should probably now be called ctx (and which should probably have a named type). Also not altered: Field called Top in gc.Func. gorename -from '"cmd/compile/internal/gc".Node.Isddd' -to IsDDD gorename -from '"cmd/compile/internal/gc".Node.SetIsddd' -to SetIsDDD gorename -from '"cmd/compile/internal/gc".nodeIsddd' -to nodeIsDDD gorename -from '"cmd/compile/internal/types".Field.Isddd' -to IsDDD gorename -from '"cmd/compile/internal/types".Field.SetIsddd' -to SetIsDDD gorename -from '"cmd/compile/internal/types".fieldIsddd' -to fieldIsDDD Not altered: function gc.hasddd, params and local variables called isddd Also not altered: fmt.go prints nodes using "isddd(%v)". cd cmd/compile/internal/gc; go generate I then manually found impacted comments using exact string match and fixed them up by hand. The comment changes were trivial. Passes toolstash-check. Fixes #27167. If this experiment is deemed a success, we will open a new tracking issue for renames to do at the end of the 1.13 cycles. Change-Id: I2dc541533d2ab0d06cb3d31d65df205ecfb151e8 Reviewed-on: https://go-review.googlesource.com/c/150140 Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2018-11-18 08:34:38 -08:00
return OBYTES2STR
}
if src.Elem().Etype == types.Runetype.Etype {
cmd/compile: bulk rename This change does a bulk rename of several identifiers in the compiler. See #27167 and https://docs.google.com/document/d/19_ExiylD9MRfeAjKIfEsMU1_RGhuxB9sA0b5Zv7byVI/ for context and for discussion of these particular renames. Commands run to generate this change: gorename -from '"cmd/compile/internal/gc".OPROC' -to OGO gorename -from '"cmd/compile/internal/gc".OCOM' -to OBITNOT gorename -from '"cmd/compile/internal/gc".OMINUS' -to ONEG gorename -from '"cmd/compile/internal/gc".OIND' -to ODEREF gorename -from '"cmd/compile/internal/gc".OARRAYBYTESTR' -to OBYTES2STR gorename -from '"cmd/compile/internal/gc".OARRAYBYTESTRTMP' -to OBYTES2STRTMP gorename -from '"cmd/compile/internal/gc".OARRAYRUNESTR' -to ORUNES2STR gorename -from '"cmd/compile/internal/gc".OSTRARRAYBYTE' -to OSTR2BYTES gorename -from '"cmd/compile/internal/gc".OSTRARRAYBYTETMP' -to OSTR2BYTESTMP gorename -from '"cmd/compile/internal/gc".OSTRARRAYRUNE' -to OSTR2RUNES gorename -from '"cmd/compile/internal/gc".Etop' -to ctxStmt gorename -from '"cmd/compile/internal/gc".Erv' -to ctxExpr gorename -from '"cmd/compile/internal/gc".Ecall' -to ctxCallee gorename -from '"cmd/compile/internal/gc".Efnstruct' -to ctxMultiOK gorename -from '"cmd/compile/internal/gc".Easgn' -to ctxAssign gorename -from '"cmd/compile/internal/gc".Ecomplit' -to ctxCompLit Not altered: parameters and local variables (mostly in typecheck.go) named top, which should probably now be called ctx (and which should probably have a named type). Also not altered: Field called Top in gc.Func. gorename -from '"cmd/compile/internal/gc".Node.Isddd' -to IsDDD gorename -from '"cmd/compile/internal/gc".Node.SetIsddd' -to SetIsDDD gorename -from '"cmd/compile/internal/gc".nodeIsddd' -to nodeIsDDD gorename -from '"cmd/compile/internal/types".Field.Isddd' -to IsDDD gorename -from '"cmd/compile/internal/types".Field.SetIsddd' -to SetIsDDD gorename -from '"cmd/compile/internal/types".fieldIsddd' -to fieldIsDDD Not altered: function gc.hasddd, params and local variables called isddd Also not altered: fmt.go prints nodes using "isddd(%v)". cd cmd/compile/internal/gc; go generate I then manually found impacted comments using exact string match and fixed them up by hand. The comment changes were trivial. Passes toolstash-check. Fixes #27167. If this experiment is deemed a success, we will open a new tracking issue for renames to do at the end of the 1.13 cycles. Change-Id: I2dc541533d2ab0d06cb3d31d65df205ecfb151e8 Reviewed-on: https://go-review.googlesource.com/c/150140 Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2018-11-18 08:34:38 -08:00
return ORUNES2STR
}
}
// 7. src is a string and dst is []byte or []rune.
// String to slice.
if src.IsString() && dst.IsSlice() {
if dst.Elem().Etype == types.Bytetype.Etype {
cmd/compile: bulk rename This change does a bulk rename of several identifiers in the compiler. See #27167 and https://docs.google.com/document/d/19_ExiylD9MRfeAjKIfEsMU1_RGhuxB9sA0b5Zv7byVI/ for context and for discussion of these particular renames. Commands run to generate this change: gorename -from '"cmd/compile/internal/gc".OPROC' -to OGO gorename -from '"cmd/compile/internal/gc".OCOM' -to OBITNOT gorename -from '"cmd/compile/internal/gc".OMINUS' -to ONEG gorename -from '"cmd/compile/internal/gc".OIND' -to ODEREF gorename -from '"cmd/compile/internal/gc".OARRAYBYTESTR' -to OBYTES2STR gorename -from '"cmd/compile/internal/gc".OARRAYBYTESTRTMP' -to OBYTES2STRTMP gorename -from '"cmd/compile/internal/gc".OARRAYRUNESTR' -to ORUNES2STR gorename -from '"cmd/compile/internal/gc".OSTRARRAYBYTE' -to OSTR2BYTES gorename -from '"cmd/compile/internal/gc".OSTRARRAYBYTETMP' -to OSTR2BYTESTMP gorename -from '"cmd/compile/internal/gc".OSTRARRAYRUNE' -to OSTR2RUNES gorename -from '"cmd/compile/internal/gc".Etop' -to ctxStmt gorename -from '"cmd/compile/internal/gc".Erv' -to ctxExpr gorename -from '"cmd/compile/internal/gc".Ecall' -to ctxCallee gorename -from '"cmd/compile/internal/gc".Efnstruct' -to ctxMultiOK gorename -from '"cmd/compile/internal/gc".Easgn' -to ctxAssign gorename -from '"cmd/compile/internal/gc".Ecomplit' -to ctxCompLit Not altered: parameters and local variables (mostly in typecheck.go) named top, which should probably now be called ctx (and which should probably have a named type). Also not altered: Field called Top in gc.Func. gorename -from '"cmd/compile/internal/gc".Node.Isddd' -to IsDDD gorename -from '"cmd/compile/internal/gc".Node.SetIsddd' -to SetIsDDD gorename -from '"cmd/compile/internal/gc".nodeIsddd' -to nodeIsDDD gorename -from '"cmd/compile/internal/types".Field.Isddd' -to IsDDD gorename -from '"cmd/compile/internal/types".Field.SetIsddd' -to SetIsDDD gorename -from '"cmd/compile/internal/types".fieldIsddd' -to fieldIsDDD Not altered: function gc.hasddd, params and local variables called isddd Also not altered: fmt.go prints nodes using "isddd(%v)". cd cmd/compile/internal/gc; go generate I then manually found impacted comments using exact string match and fixed them up by hand. The comment changes were trivial. Passes toolstash-check. Fixes #27167. If this experiment is deemed a success, we will open a new tracking issue for renames to do at the end of the 1.13 cycles. Change-Id: I2dc541533d2ab0d06cb3d31d65df205ecfb151e8 Reviewed-on: https://go-review.googlesource.com/c/150140 Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2018-11-18 08:34:38 -08:00
return OSTR2BYTES
}
if dst.Elem().Etype == types.Runetype.Etype {
cmd/compile: bulk rename This change does a bulk rename of several identifiers in the compiler. See #27167 and https://docs.google.com/document/d/19_ExiylD9MRfeAjKIfEsMU1_RGhuxB9sA0b5Zv7byVI/ for context and for discussion of these particular renames. Commands run to generate this change: gorename -from '"cmd/compile/internal/gc".OPROC' -to OGO gorename -from '"cmd/compile/internal/gc".OCOM' -to OBITNOT gorename -from '"cmd/compile/internal/gc".OMINUS' -to ONEG gorename -from '"cmd/compile/internal/gc".OIND' -to ODEREF gorename -from '"cmd/compile/internal/gc".OARRAYBYTESTR' -to OBYTES2STR gorename -from '"cmd/compile/internal/gc".OARRAYBYTESTRTMP' -to OBYTES2STRTMP gorename -from '"cmd/compile/internal/gc".OARRAYRUNESTR' -to ORUNES2STR gorename -from '"cmd/compile/internal/gc".OSTRARRAYBYTE' -to OSTR2BYTES gorename -from '"cmd/compile/internal/gc".OSTRARRAYBYTETMP' -to OSTR2BYTESTMP gorename -from '"cmd/compile/internal/gc".OSTRARRAYRUNE' -to OSTR2RUNES gorename -from '"cmd/compile/internal/gc".Etop' -to ctxStmt gorename -from '"cmd/compile/internal/gc".Erv' -to ctxExpr gorename -from '"cmd/compile/internal/gc".Ecall' -to ctxCallee gorename -from '"cmd/compile/internal/gc".Efnstruct' -to ctxMultiOK gorename -from '"cmd/compile/internal/gc".Easgn' -to ctxAssign gorename -from '"cmd/compile/internal/gc".Ecomplit' -to ctxCompLit Not altered: parameters and local variables (mostly in typecheck.go) named top, which should probably now be called ctx (and which should probably have a named type). Also not altered: Field called Top in gc.Func. gorename -from '"cmd/compile/internal/gc".Node.Isddd' -to IsDDD gorename -from '"cmd/compile/internal/gc".Node.SetIsddd' -to SetIsDDD gorename -from '"cmd/compile/internal/gc".nodeIsddd' -to nodeIsDDD gorename -from '"cmd/compile/internal/types".Field.Isddd' -to IsDDD gorename -from '"cmd/compile/internal/types".Field.SetIsddd' -to SetIsDDD gorename -from '"cmd/compile/internal/types".fieldIsddd' -to fieldIsDDD Not altered: function gc.hasddd, params and local variables called isddd Also not altered: fmt.go prints nodes using "isddd(%v)". cd cmd/compile/internal/gc; go generate I then manually found impacted comments using exact string match and fixed them up by hand. The comment changes were trivial. Passes toolstash-check. Fixes #27167. If this experiment is deemed a success, we will open a new tracking issue for renames to do at the end of the 1.13 cycles. Change-Id: I2dc541533d2ab0d06cb3d31d65df205ecfb151e8 Reviewed-on: https://go-review.googlesource.com/c/150140 Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2018-11-18 08:34:38 -08:00
return OSTR2RUNES
}
}
// 8. src is a pointer or uintptr and dst is unsafe.Pointer.
if (src.IsPtr() || src.Etype == TUINTPTR) && dst.Etype == TUNSAFEPTR {
return OCONVNOP
}
// 9. src is unsafe.Pointer and dst is a pointer or uintptr.
if src.Etype == TUNSAFEPTR && (dst.IsPtr() || dst.Etype == TUINTPTR) {
return OCONVNOP
}
// src is map and dst is a pointer to corresponding hmap.
// This rule is needed for the implementation detail that
// go gc maps are implemented as a pointer to a hmap struct.
if src.Etype == TMAP && dst.IsPtr() &&
src.MapType().Hmap == dst.Elem() {
return OCONVNOP
}
return OXXX
}
func assignconv(n *Node, t *types.Type, context string) *Node {
return assignconvfn(n, t, func() string { return context })
}
// Convert node n for assignment to type t.
func assignconvfn(n *Node, t *types.Type, context func() string) *Node {
cmd/compile: pack bool fields in Node, Name, Func and Type structs to bitsets This reduces compiler memory usage by up to 4% - see compilebench results below. name old time/op new time/op delta Template 245ms ± 4% 241ms ± 2% -1.88% (p=0.029 n=10+10) Unicode 126ms ± 3% 124ms ± 3% ~ (p=0.105 n=10+10) GoTypes 805ms ± 2% 813ms ± 3% ~ (p=0.515 n=8+10) Compiler 3.95s ± 2% 3.83s ± 1% -2.96% (p=0.000 n=9+10) MakeBash 47.4s ± 4% 46.6s ± 1% -1.59% (p=0.028 n=9+10) name old user-ns/op new user-ns/op delta Template 324M ± 5% 326M ± 3% ~ (p=0.935 n=10+10) Unicode 186M ± 5% 178M ±10% ~ (p=0.067 n=9+10) GoTypes 1.08G ± 7% 1.09G ± 4% ~ (p=0.956 n=10+10) Compiler 5.34G ± 4% 5.31G ± 1% ~ (p=0.501 n=10+8) name old alloc/op new alloc/op delta Template 41.0MB ± 0% 39.8MB ± 0% -3.03% (p=0.000 n=10+10) Unicode 32.3MB ± 0% 31.0MB ± 0% -4.13% (p=0.000 n=10+10) GoTypes 119MB ± 0% 116MB ± 0% -2.39% (p=0.000 n=10+10) Compiler 499MB ± 0% 487MB ± 0% -2.48% (p=0.000 n=10+10) name old allocs/op new allocs/op delta Template 380k ± 1% 379k ± 1% ~ (p=0.436 n=10+10) Unicode 324k ± 1% 324k ± 0% ~ (p=0.853 n=10+10) GoTypes 1.15M ± 0% 1.15M ± 0% ~ (p=0.481 n=10+10) Compiler 4.41M ± 0% 4.41M ± 0% -0.12% (p=0.007 n=10+10) name old text-bytes new text-bytes delta HelloSize 623k ± 0% 623k ± 0% ~ (all equal) CmdGoSize 6.64M ± 0% 6.64M ± 0% ~ (all equal) name old data-bytes new data-bytes delta HelloSize 5.81k ± 0% 5.81k ± 0% ~ (all equal) CmdGoSize 238k ± 0% 238k ± 0% ~ (all equal) name old bss-bytes new bss-bytes delta HelloSize 134k ± 0% 134k ± 0% ~ (all equal) CmdGoSize 152k ± 0% 152k ± 0% ~ (all equal) name old exe-bytes new exe-bytes delta HelloSize 967k ± 0% 967k ± 0% ~ (all equal) CmdGoSize 10.2M ± 0% 10.2M ± 0% ~ (all equal) Change-Id: I1f40af738254892bd6c8ba2eb43390b175753d52 Reviewed-on: https://go-review.googlesource.com/37445 Reviewed-by: Matthew Dempsky <mdempsky@google.com> Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
2017-02-27 19:56:38 +02:00
if n == nil || n.Type == nil || n.Type.Broke() {
return n
}
if t.Etype == TBLANK && n.Type.Etype == TNIL {
yyerror("use of untyped nil")
}
cmd/compile: rewrite untyped constant conversion logic This CL detangles the hairy mess that was convlit+defaultlit. In particular, it makes the following changes: 1. convlit1 now follows the standard typecheck behavior of setting "n.Type = nil" if there's an error. Notably, this means for a lot of test cases, we now avoid reporting useless follow-on error messages. For example, after reporting that "1 << s + 1.0" has an invalid shift, we no longer also report that it can't be assigned to string. 2. Previously, assignconvfn had some extra logic for trying to suppress errors from convlit/defaultlit so that it could provide its own errors with better context information. Instead, this extra context information is now passed down into convlit1 directly. 3. Relatedly, this CL also removes redundant calls to defaultlit prior to assignconv. As a consequence, when an expression doesn't make sense for a particular assignment (e.g., assigning an untyped string to an integer), the error messages now say "untyped string" instead of just "string". This is more consistent with go/types behavior. 4. defaultlit2 is now smarter about only trying to convert pairs of untyped constants when it's likely to succeed. This allows us to report better error messages for things like 3+"x"; instead of "cannot convert 3 to string" we now report "mismatched types untyped number and untyped string". Passes toolstash-check. Change-Id: I26822a02dc35855bd0ac774907b1cf5737e91882 Reviewed-on: https://go-review.googlesource.com/c/go/+/187657 Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org>
2019-09-05 13:33:06 -07:00
n = convlit1(n, t, false, context)
if n.Type == nil {
return n
}
if t.Etype == TBLANK {
return n
}
// Convert ideal bool from comparison to plain bool
// if the next step is non-bool (like interface{}).
if n.Type == types.Idealbool && !t.IsBoolean() {
if n.Op == ONAME || n.Op == OLITERAL {
r := nod(OCONVNOP, n, nil)
r.Type = types.Types[TBOOL]
r.SetTypecheck(1)
cmd/compile: pack bool fields in Node, Name, Func and Type structs to bitsets This reduces compiler memory usage by up to 4% - see compilebench results below. name old time/op new time/op delta Template 245ms ± 4% 241ms ± 2% -1.88% (p=0.029 n=10+10) Unicode 126ms ± 3% 124ms ± 3% ~ (p=0.105 n=10+10) GoTypes 805ms ± 2% 813ms ± 3% ~ (p=0.515 n=8+10) Compiler 3.95s ± 2% 3.83s ± 1% -2.96% (p=0.000 n=9+10) MakeBash 47.4s ± 4% 46.6s ± 1% -1.59% (p=0.028 n=9+10) name old user-ns/op new user-ns/op delta Template 324M ± 5% 326M ± 3% ~ (p=0.935 n=10+10) Unicode 186M ± 5% 178M ±10% ~ (p=0.067 n=9+10) GoTypes 1.08G ± 7% 1.09G ± 4% ~ (p=0.956 n=10+10) Compiler 5.34G ± 4% 5.31G ± 1% ~ (p=0.501 n=10+8) name old alloc/op new alloc/op delta Template 41.0MB ± 0% 39.8MB ± 0% -3.03% (p=0.000 n=10+10) Unicode 32.3MB ± 0% 31.0MB ± 0% -4.13% (p=0.000 n=10+10) GoTypes 119MB ± 0% 116MB ± 0% -2.39% (p=0.000 n=10+10) Compiler 499MB ± 0% 487MB ± 0% -2.48% (p=0.000 n=10+10) name old allocs/op new allocs/op delta Template 380k ± 1% 379k ± 1% ~ (p=0.436 n=10+10) Unicode 324k ± 1% 324k ± 0% ~ (p=0.853 n=10+10) GoTypes 1.15M ± 0% 1.15M ± 0% ~ (p=0.481 n=10+10) Compiler 4.41M ± 0% 4.41M ± 0% -0.12% (p=0.007 n=10+10) name old text-bytes new text-bytes delta HelloSize 623k ± 0% 623k ± 0% ~ (all equal) CmdGoSize 6.64M ± 0% 6.64M ± 0% ~ (all equal) name old data-bytes new data-bytes delta HelloSize 5.81k ± 0% 5.81k ± 0% ~ (all equal) CmdGoSize 238k ± 0% 238k ± 0% ~ (all equal) name old bss-bytes new bss-bytes delta HelloSize 134k ± 0% 134k ± 0% ~ (all equal) CmdGoSize 152k ± 0% 152k ± 0% ~ (all equal) name old exe-bytes new exe-bytes delta HelloSize 967k ± 0% 967k ± 0% ~ (all equal) CmdGoSize 10.2M ± 0% 10.2M ± 0% ~ (all equal) Change-Id: I1f40af738254892bd6c8ba2eb43390b175753d52 Reviewed-on: https://go-review.googlesource.com/37445 Reviewed-by: Matthew Dempsky <mdempsky@google.com> Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
2017-02-27 19:56:38 +02:00
r.SetImplicit(true)
n = r
}
}
if types.Identical(n.Type, t) {
return n
}
var why string
op := assignop(n.Type, t, &why)
if op == OXXX {
cmd/compile: rewrite untyped constant conversion logic This CL detangles the hairy mess that was convlit+defaultlit. In particular, it makes the following changes: 1. convlit1 now follows the standard typecheck behavior of setting "n.Type = nil" if there's an error. Notably, this means for a lot of test cases, we now avoid reporting useless follow-on error messages. For example, after reporting that "1 << s + 1.0" has an invalid shift, we no longer also report that it can't be assigned to string. 2. Previously, assignconvfn had some extra logic for trying to suppress errors from convlit/defaultlit so that it could provide its own errors with better context information. Instead, this extra context information is now passed down into convlit1 directly. 3. Relatedly, this CL also removes redundant calls to defaultlit prior to assignconv. As a consequence, when an expression doesn't make sense for a particular assignment (e.g., assigning an untyped string to an integer), the error messages now say "untyped string" instead of just "string". This is more consistent with go/types behavior. 4. defaultlit2 is now smarter about only trying to convert pairs of untyped constants when it's likely to succeed. This allows us to report better error messages for things like 3+"x"; instead of "cannot convert 3 to string" we now report "mismatched types untyped number and untyped string". Passes toolstash-check. Change-Id: I26822a02dc35855bd0ac774907b1cf5737e91882 Reviewed-on: https://go-review.googlesource.com/c/go/+/187657 Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org>
2019-09-05 13:33:06 -07:00
yyerror("cannot use %L as type %v in %s%s", n, t, context(), why)
op = OCONV
}
r := nod(op, n, nil)
r.Type = t
r.SetTypecheck(1)
cmd/compile: pack bool fields in Node, Name, Func and Type structs to bitsets This reduces compiler memory usage by up to 4% - see compilebench results below. name old time/op new time/op delta Template 245ms ± 4% 241ms ± 2% -1.88% (p=0.029 n=10+10) Unicode 126ms ± 3% 124ms ± 3% ~ (p=0.105 n=10+10) GoTypes 805ms ± 2% 813ms ± 3% ~ (p=0.515 n=8+10) Compiler 3.95s ± 2% 3.83s ± 1% -2.96% (p=0.000 n=9+10) MakeBash 47.4s ± 4% 46.6s ± 1% -1.59% (p=0.028 n=9+10) name old user-ns/op new user-ns/op delta Template 324M ± 5% 326M ± 3% ~ (p=0.935 n=10+10) Unicode 186M ± 5% 178M ±10% ~ (p=0.067 n=9+10) GoTypes 1.08G ± 7% 1.09G ± 4% ~ (p=0.956 n=10+10) Compiler 5.34G ± 4% 5.31G ± 1% ~ (p=0.501 n=10+8) name old alloc/op new alloc/op delta Template 41.0MB ± 0% 39.8MB ± 0% -3.03% (p=0.000 n=10+10) Unicode 32.3MB ± 0% 31.0MB ± 0% -4.13% (p=0.000 n=10+10) GoTypes 119MB ± 0% 116MB ± 0% -2.39% (p=0.000 n=10+10) Compiler 499MB ± 0% 487MB ± 0% -2.48% (p=0.000 n=10+10) name old allocs/op new allocs/op delta Template 380k ± 1% 379k ± 1% ~ (p=0.436 n=10+10) Unicode 324k ± 1% 324k ± 0% ~ (p=0.853 n=10+10) GoTypes 1.15M ± 0% 1.15M ± 0% ~ (p=0.481 n=10+10) Compiler 4.41M ± 0% 4.41M ± 0% -0.12% (p=0.007 n=10+10) name old text-bytes new text-bytes delta HelloSize 623k ± 0% 623k ± 0% ~ (all equal) CmdGoSize 6.64M ± 0% 6.64M ± 0% ~ (all equal) name old data-bytes new data-bytes delta HelloSize 5.81k ± 0% 5.81k ± 0% ~ (all equal) CmdGoSize 238k ± 0% 238k ± 0% ~ (all equal) name old bss-bytes new bss-bytes delta HelloSize 134k ± 0% 134k ± 0% ~ (all equal) CmdGoSize 152k ± 0% 152k ± 0% ~ (all equal) name old exe-bytes new exe-bytes delta HelloSize 967k ± 0% 967k ± 0% ~ (all equal) CmdGoSize 10.2M ± 0% 10.2M ± 0% ~ (all equal) Change-Id: I1f40af738254892bd6c8ba2eb43390b175753d52 Reviewed-on: https://go-review.googlesource.com/37445 Reviewed-by: Matthew Dempsky <mdempsky@google.com> Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
2017-02-27 19:56:38 +02:00
r.SetImplicit(true)
r.Orig = n.Orig
return r
}
// IsMethod reports whether n is a method.
// n must be a function or a method.
func (n *Node) IsMethod() bool {
return n.Type.Recv() != nil
}
// SliceBounds returns n's slice bounds: low, high, and max in expr[low:high:max].
// n must be a slice expression. max is nil if n is a simple slice expression.
func (n *Node) SliceBounds() (low, high, max *Node) {
if n.List.Len() == 0 {
return nil, nil, nil
}
switch n.Op {
case OSLICE, OSLICEARR, OSLICESTR:
s := n.List.Slice()
return s[0], s[1], nil
case OSLICE3, OSLICE3ARR:
s := n.List.Slice()
return s[0], s[1], s[2]
}
Fatalf("SliceBounds op %v: %v", n.Op, n)
return nil, nil, nil
}
// SetSliceBounds sets n's slice bounds, where n is a slice expression.
// n must be a slice expression. If max is non-nil, n must be a full slice expression.
func (n *Node) SetSliceBounds(low, high, max *Node) {
switch n.Op {
case OSLICE, OSLICEARR, OSLICESTR:
if max != nil {
Fatalf("SetSliceBounds %v given three bounds", n.Op)
}
s := n.List.Slice()
if s == nil {
if low == nil && high == nil {
return
}
n.List.Set2(low, high)
return
}
s[0] = low
s[1] = high
return
case OSLICE3, OSLICE3ARR:
s := n.List.Slice()
if s == nil {
if low == nil && high == nil && max == nil {
return
}
n.List.Set3(low, high, max)
return
}
s[0] = low
s[1] = high
s[2] = max
return
}
Fatalf("SetSliceBounds op %v: %v", n.Op, n)
}
// IsSlice3 reports whether o is a slice3 op (OSLICE3, OSLICE3ARR).
// o must be a slicing op.
func (o Op) IsSlice3() bool {
switch o {
case OSLICE, OSLICEARR, OSLICESTR:
return false
case OSLICE3, OSLICE3ARR:
return true
}
Fatalf("IsSlice3 op %v", o)
return false
}
// slicePtrLen extracts the pointer and length from a slice.
// This constructs two nodes referring to n, so n must be a cheapexpr.
func (n *Node) slicePtrLen() (ptr, len *Node) {
var init Nodes
c := cheapexpr(n, &init)
if c != n || init.Len() != 0 {
Fatalf("slicePtrLen not cheap: %v", n)
}
ptr = nod(OSPTR, n, nil)
ptr.Type = n.Type.Elem().PtrTo()
len = nod(OLEN, n, nil)
len.Type = types.Types[TINT]
return ptr, len
}
cmd/compile: check labels and gotos before building SSA This CL introduces yet another compiler pass, which checks for correct control flow constructs prior to converting from AST to SSA form. It cannot be integrated with walk, since walk rewrites switch and select statements on the fly. To reduce code duplication, this CL also does some minor refactoring. With this pass in place, the AST to SSA converter can now stop generating SSA for any known-dead code. This minor savings pays for the minor cost of the new pass. Performance is almost a wash: name old time/op new time/op delta Template 206ms ± 4% 205ms ± 4% ~ (p=0.108 n=43+43) Unicode 84.0ms ± 4% 84.0ms ± 4% ~ (p=0.979 n=43+43) GoTypes 550ms ± 3% 553ms ± 3% ~ (p=0.065 n=40+41) Compiler 2.57s ± 4% 2.58s ± 2% ~ (p=0.103 n=44+41) SSA 3.94s ± 3% 3.93s ± 2% ~ (p=0.833 n=44+42) Flate 126ms ± 6% 125ms ± 4% ~ (p=0.941 n=43+39) GoParser 147ms ± 4% 148ms ± 3% ~ (p=0.164 n=42+39) Reflect 359ms ± 3% 357ms ± 5% ~ (p=0.241 n=43+44) Tar 106ms ± 5% 106ms ± 7% ~ (p=0.853 n=40+43) XML 202ms ± 3% 203ms ± 3% ~ (p=0.488 n=42+41) name old user-ns/op new user-ns/op delta Template 240M ± 4% 239M ± 4% ~ (p=0.844 n=42+43) Unicode 107M ± 5% 107M ± 4% ~ (p=0.332 n=40+43) GoTypes 735M ± 3% 731M ± 4% ~ (p=0.141 n=43+44) Compiler 3.51G ± 3% 3.52G ± 3% ~ (p=0.208 n=42+43) SSA 5.72G ± 4% 5.72G ± 3% ~ (p=0.928 n=44+42) Flate 151M ± 7% 150M ± 8% ~ (p=0.662 n=44+43) GoParser 181M ± 5% 181M ± 4% ~ (p=0.379 n=41+44) Reflect 447M ± 4% 445M ± 4% ~ (p=0.344 n=43+43) Tar 125M ± 7% 124M ± 6% ~ (p=0.353 n=43+43) XML 248M ± 4% 250M ± 6% ~ (p=0.158 n=44+44) name old alloc/op new alloc/op delta Template 40.3MB ± 0% 40.2MB ± 0% -0.27% (p=0.000 n=10+10) Unicode 30.3MB ± 0% 30.2MB ± 0% -0.10% (p=0.015 n=10+10) GoTypes 114MB ± 0% 114MB ± 0% -0.06% (p=0.000 n=7+9) Compiler 480MB ± 0% 481MB ± 0% +0.07% (p=0.000 n=10+10) SSA 864MB ± 0% 862MB ± 0% -0.25% (p=0.000 n=9+10) Flate 25.9MB ± 0% 25.9MB ± 0% ~ (p=0.123 n=10+10) GoParser 32.1MB ± 0% 32.1MB ± 0% ~ (p=0.631 n=10+10) Reflect 79.9MB ± 0% 79.6MB ± 0% -0.39% (p=0.000 n=10+9) Tar 27.1MB ± 0% 27.0MB ± 0% -0.18% (p=0.003 n=10+10) XML 42.6MB ± 0% 42.6MB ± 0% ~ (p=0.143 n=10+10) name old allocs/op new allocs/op delta Template 401k ± 0% 401k ± 1% ~ (p=0.353 n=10+10) Unicode 322k ± 0% 322k ± 0% ~ (p=0.739 n=10+10) GoTypes 1.18M ± 0% 1.18M ± 0% +0.25% (p=0.001 n=7+8) Compiler 4.51M ± 0% 4.53M ± 0% +0.37% (p=0.000 n=10+10) SSA 7.91M ± 0% 7.93M ± 0% +0.20% (p=0.000 n=9+10) Flate 244k ± 0% 245k ± 0% ~ (p=0.123 n=10+10) GoParser 323k ± 1% 324k ± 1% +0.40% (p=0.035 n=10+10) Reflect 1.01M ± 0% 1.02M ± 0% +0.37% (p=0.000 n=10+9) Tar 258k ± 1% 258k ± 1% ~ (p=0.661 n=10+9) XML 403k ± 0% 405k ± 0% +0.47% (p=0.004 n=10+10) Updates #15756 Updates #19250 Change-Id: I647bfbb745c35630447eb79dfcaa994b490ce942 Reviewed-on: https://go-review.googlesource.com/38159 Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-03-14 11:05:03 -07:00
// labeledControl returns the control flow Node (for, switch, select)
// associated with the label n, if any.
func (n *Node) labeledControl() *Node {
if n.Op != OLABEL {
Fatalf("labeledControl %v", n.Op)
}
ctl := n.Name.Defn
if ctl == nil {
return nil
}
switch ctl.Op {
case OFOR, OFORUNTIL, OSWITCH, OSELECT:
return ctl
}
return nil
}
func syslook(name string) *Node {
s := Runtimepkg.Lookup(name)
if s == nil || s.Def == nil {
Fatalf("syslook: can't find runtime.%s", name)
}
return asNode(s.Def)
}
// typehash computes a hash value for type t to use in type switch statements.
func typehash(t *types.Type) uint32 {
p := t.LongString()
// Using MD5 is overkill, but reduces accidental collisions.
h := md5.Sum([]byte(p))
return binary.LittleEndian.Uint32(h[:4])
}
// updateHasCall checks whether expression n contains any function
// calls and sets the n.HasCall flag if so.
func updateHasCall(n *Node) {
if n == nil {
return
}
n.SetHasCall(calcHasCall(n))
}
func calcHasCall(n *Node) bool {
if n.Ninit.Len() != 0 {
// TODO(mdempsky): This seems overly conservative.
return true
}
switch n.Op {
case OLITERAL, ONAME, OTYPE:
if n.HasCall() {
Fatalf("OLITERAL/ONAME/OTYPE should never have calls: %+v", n)
}
return false
case OCALL, OCALLFUNC, OCALLMETH, OCALLINTER:
return true
case OANDAND, OOROR:
// hard with instrumented code
if instrumenting {
return true
}
case OINDEX, OSLICE, OSLICEARR, OSLICE3, OSLICE3ARR, OSLICESTR,
cmd/compile: bulk rename This change does a bulk rename of several identifiers in the compiler. See #27167 and https://docs.google.com/document/d/19_ExiylD9MRfeAjKIfEsMU1_RGhuxB9sA0b5Zv7byVI/ for context and for discussion of these particular renames. Commands run to generate this change: gorename -from '"cmd/compile/internal/gc".OPROC' -to OGO gorename -from '"cmd/compile/internal/gc".OCOM' -to OBITNOT gorename -from '"cmd/compile/internal/gc".OMINUS' -to ONEG gorename -from '"cmd/compile/internal/gc".OIND' -to ODEREF gorename -from '"cmd/compile/internal/gc".OARRAYBYTESTR' -to OBYTES2STR gorename -from '"cmd/compile/internal/gc".OARRAYBYTESTRTMP' -to OBYTES2STRTMP gorename -from '"cmd/compile/internal/gc".OARRAYRUNESTR' -to ORUNES2STR gorename -from '"cmd/compile/internal/gc".OSTRARRAYBYTE' -to OSTR2BYTES gorename -from '"cmd/compile/internal/gc".OSTRARRAYBYTETMP' -to OSTR2BYTESTMP gorename -from '"cmd/compile/internal/gc".OSTRARRAYRUNE' -to OSTR2RUNES gorename -from '"cmd/compile/internal/gc".Etop' -to ctxStmt gorename -from '"cmd/compile/internal/gc".Erv' -to ctxExpr gorename -from '"cmd/compile/internal/gc".Ecall' -to ctxCallee gorename -from '"cmd/compile/internal/gc".Efnstruct' -to ctxMultiOK gorename -from '"cmd/compile/internal/gc".Easgn' -to ctxAssign gorename -from '"cmd/compile/internal/gc".Ecomplit' -to ctxCompLit Not altered: parameters and local variables (mostly in typecheck.go) named top, which should probably now be called ctx (and which should probably have a named type). Also not altered: Field called Top in gc.Func. gorename -from '"cmd/compile/internal/gc".Node.Isddd' -to IsDDD gorename -from '"cmd/compile/internal/gc".Node.SetIsddd' -to SetIsDDD gorename -from '"cmd/compile/internal/gc".nodeIsddd' -to nodeIsDDD gorename -from '"cmd/compile/internal/types".Field.Isddd' -to IsDDD gorename -from '"cmd/compile/internal/types".Field.SetIsddd' -to SetIsDDD gorename -from '"cmd/compile/internal/types".fieldIsddd' -to fieldIsDDD Not altered: function gc.hasddd, params and local variables called isddd Also not altered: fmt.go prints nodes using "isddd(%v)". cd cmd/compile/internal/gc; go generate I then manually found impacted comments using exact string match and fixed them up by hand. The comment changes were trivial. Passes toolstash-check. Fixes #27167. If this experiment is deemed a success, we will open a new tracking issue for renames to do at the end of the 1.13 cycles. Change-Id: I2dc541533d2ab0d06cb3d31d65df205ecfb151e8 Reviewed-on: https://go-review.googlesource.com/c/150140 Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2018-11-18 08:34:38 -08:00
ODEREF, ODOTPTR, ODOTTYPE, ODIV, OMOD:
// These ops might panic, make sure they are done
// before we start marshaling args for a call. See issue 16760.
return true
// When using soft-float, these ops might be rewritten to function calls
// so we ensure they are evaluated first.
cmd/compile: bulk rename This change does a bulk rename of several identifiers in the compiler. See #27167 and https://docs.google.com/document/d/19_ExiylD9MRfeAjKIfEsMU1_RGhuxB9sA0b5Zv7byVI/ for context and for discussion of these particular renames. Commands run to generate this change: gorename -from '"cmd/compile/internal/gc".OPROC' -to OGO gorename -from '"cmd/compile/internal/gc".OCOM' -to OBITNOT gorename -from '"cmd/compile/internal/gc".OMINUS' -to ONEG gorename -from '"cmd/compile/internal/gc".OIND' -to ODEREF gorename -from '"cmd/compile/internal/gc".OARRAYBYTESTR' -to OBYTES2STR gorename -from '"cmd/compile/internal/gc".OARRAYBYTESTRTMP' -to OBYTES2STRTMP gorename -from '"cmd/compile/internal/gc".OARRAYRUNESTR' -to ORUNES2STR gorename -from '"cmd/compile/internal/gc".OSTRARRAYBYTE' -to OSTR2BYTES gorename -from '"cmd/compile/internal/gc".OSTRARRAYBYTETMP' -to OSTR2BYTESTMP gorename -from '"cmd/compile/internal/gc".OSTRARRAYRUNE' -to OSTR2RUNES gorename -from '"cmd/compile/internal/gc".Etop' -to ctxStmt gorename -from '"cmd/compile/internal/gc".Erv' -to ctxExpr gorename -from '"cmd/compile/internal/gc".Ecall' -to ctxCallee gorename -from '"cmd/compile/internal/gc".Efnstruct' -to ctxMultiOK gorename -from '"cmd/compile/internal/gc".Easgn' -to ctxAssign gorename -from '"cmd/compile/internal/gc".Ecomplit' -to ctxCompLit Not altered: parameters and local variables (mostly in typecheck.go) named top, which should probably now be called ctx (and which should probably have a named type). Also not altered: Field called Top in gc.Func. gorename -from '"cmd/compile/internal/gc".Node.Isddd' -to IsDDD gorename -from '"cmd/compile/internal/gc".Node.SetIsddd' -to SetIsDDD gorename -from '"cmd/compile/internal/gc".nodeIsddd' -to nodeIsDDD gorename -from '"cmd/compile/internal/types".Field.Isddd' -to IsDDD gorename -from '"cmd/compile/internal/types".Field.SetIsddd' -to SetIsDDD gorename -from '"cmd/compile/internal/types".fieldIsddd' -to fieldIsDDD Not altered: function gc.hasddd, params and local variables called isddd Also not altered: fmt.go prints nodes using "isddd(%v)". cd cmd/compile/internal/gc; go generate I then manually found impacted comments using exact string match and fixed them up by hand. The comment changes were trivial. Passes toolstash-check. Fixes #27167. If this experiment is deemed a success, we will open a new tracking issue for renames to do at the end of the 1.13 cycles. Change-Id: I2dc541533d2ab0d06cb3d31d65df205ecfb151e8 Reviewed-on: https://go-review.googlesource.com/c/150140 Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2018-11-18 08:34:38 -08:00
case OADD, OSUB, ONEG, OMUL:
if thearch.SoftFloat && (isFloat[n.Type.Etype] || isComplex[n.Type.Etype]) {
return true
}
case OLT, OEQ, ONE, OLE, OGE, OGT:
if thearch.SoftFloat && (isFloat[n.Left.Type.Etype] || isComplex[n.Left.Type.Etype]) {
return true
}
case OCONV:
if thearch.SoftFloat && ((isFloat[n.Type.Etype] || isComplex[n.Type.Etype]) || (isFloat[n.Left.Type.Etype] || isComplex[n.Left.Type.Etype])) {
return true
}
}
if n.Left != nil && n.Left.HasCall() {
return true
}
if n.Right != nil && n.Right.HasCall() {
return true
}
return false
}
func badtype(op Op, tl *types.Type, tr *types.Type) {
fmt_ := ""
if tl != nil {
fmt_ += fmt.Sprintf("\n\t%v", tl)
}
if tr != nil {
fmt_ += fmt.Sprintf("\n\t%v", tr)
}
// common mistake: *struct and *interface.
if tl != nil && tr != nil && tl.IsPtr() && tr.IsPtr() {
if tl.Elem().IsStruct() && tr.Elem().IsInterface() {
fmt_ += "\n\t(*struct vs *interface)"
} else if tl.Elem().IsInterface() && tr.Elem().IsStruct() {
fmt_ += "\n\t(*interface vs *struct)"
}
}
s := fmt_
yyerror("illegal types for operand: %v%s", op, s)
}
// brcom returns !(op).
// For example, brcom(==) is !=.
func brcom(op Op) Op {
switch op {
case OEQ:
return ONE
case ONE:
return OEQ
case OLT:
return OGE
case OGT:
return OLE
case OLE:
return OGT
case OGE:
return OLT
}
Fatalf("brcom: no com for %v\n", op)
return op
}
// brrev returns reverse(op).
// For example, Brrev(<) is >.
func brrev(op Op) Op {
switch op {
case OEQ:
return OEQ
case ONE:
return ONE
case OLT:
return OGT
case OGT:
return OLT
case OLE:
return OGE
case OGE:
return OLE
}
Fatalf("brrev: no rev for %v\n", op)
return op
}
// return side effect-free n, appending side effects to init.
// result is assignable if n is.
func safeexpr(n *Node, init *Nodes) *Node {
if n == nil {
return nil
}
if n.Ninit.Len() != 0 {
walkstmtlist(n.Ninit.Slice())
init.AppendNodes(&n.Ninit)
}
switch n.Op {
case ONAME, OLITERAL:
return n
cmd/internal/gc: optimize slice + write barrier The code generated for a slice x[i:j] or x[i:j:k] computes the entire new slice (base, len, cap) and then uses it as the evaluation of the slice expression. If the slice is part of an update x = x[i:j] or x = x[i:j:k], there are opportunities to avoid computing some of these fields. For x = x[0:i], we know that only the len is changing; base can be ignored completely, and cap can be left unmodified. For x = x[0:i:j], we know that only len and cap are changing; base can be ignored completely. For x = x[i:i], we know that the resulting cap is zero, and we don't adjust the base during a slice producing a zero-cap result, so again base can be ignored completely. No write to base, no write barrier. The old slice code was trying to work at a Go syntax level, mainly because that was how you wrote code just once instead of once per architecture. Now the compiler is factored a bit better and we can implement slice during code generation but still have one copy of the code. So the new code is working at that lower level. (It must, to update only parts of the result.) This CL by itself: name old mean new mean delta BinaryTree17 5.81s × (0.98,1.03) 5.71s × (0.96,1.05) ~ (p=0.101) Fannkuch11 4.35s × (1.00,1.00) 4.39s × (1.00,1.00) +0.79% (p=0.000) FmtFprintfEmpty 86.0ns × (0.94,1.11) 82.6ns × (0.98,1.04) -3.86% (p=0.048) FmtFprintfString 276ns × (0.98,1.04) 273ns × (0.98,1.02) ~ (p=0.235) FmtFprintfInt 274ns × (0.98,1.06) 270ns × (0.99,1.01) ~ (p=0.119) FmtFprintfIntInt 506ns × (0.99,1.01) 475ns × (0.99,1.01) -6.02% (p=0.000) FmtFprintfPrefixedInt 391ns × (0.99,1.01) 393ns × (1.00,1.01) ~ (p=0.139) FmtFprintfFloat 566ns × (0.99,1.01) 574ns × (1.00,1.01) +1.33% (p=0.001) FmtManyArgs 1.91µs × (0.99,1.01) 1.87µs × (0.99,1.02) -1.83% (p=0.000) GobDecode 15.3ms × (0.99,1.02) 15.0ms × (0.98,1.05) -1.84% (p=0.042) GobEncode 11.5ms × (0.97,1.03) 11.4ms × (0.99,1.03) ~ (p=0.152) Gzip 645ms × (0.99,1.01) 647ms × (0.99,1.01) ~ (p=0.265) Gunzip 142ms × (1.00,1.00) 143ms × (1.00,1.01) +0.90% (p=0.000) HTTPClientServer 90.5µs × (0.97,1.04) 88.5µs × (0.99,1.03) -2.27% (p=0.014) JSONEncode 32.0ms × (0.98,1.03) 29.6ms × (0.98,1.01) -7.51% (p=0.000) JSONDecode 114ms × (0.99,1.01) 104ms × (1.00,1.01) -8.60% (p=0.000) Mandelbrot200 6.04ms × (1.00,1.01) 6.02ms × (1.00,1.00) ~ (p=0.057) GoParse 6.47ms × (0.97,1.05) 6.37ms × (0.97,1.04) ~ (p=0.105) RegexpMatchEasy0_32 171ns × (0.93,1.07) 152ns × (0.99,1.01) -11.09% (p=0.000) RegexpMatchEasy0_1K 550ns × (0.98,1.01) 530ns × (1.00,1.00) -3.78% (p=0.000) RegexpMatchEasy1_32 135ns × (0.99,1.02) 134ns × (0.99,1.01) -1.33% (p=0.002) RegexpMatchEasy1_1K 879ns × (1.00,1.01) 865ns × (1.00,1.00) -1.58% (p=0.000) RegexpMatchMedium_32 243ns × (1.00,1.00) 233ns × (1.00,1.00) -4.30% (p=0.000) RegexpMatchMedium_1K 70.3µs × (1.00,1.00) 69.5µs × (1.00,1.00) -1.13% (p=0.000) RegexpMatchHard_32 3.82µs × (1.00,1.01) 3.74µs × (1.00,1.00) -1.95% (p=0.000) RegexpMatchHard_1K 117µs × (1.00,1.00) 115µs × (1.00,1.00) -1.69% (p=0.000) Revcomp 917ms × (0.97,1.04) 920ms × (0.97,1.04) ~ (p=0.786) Template 114ms × (0.99,1.01) 117ms × (0.99,1.01) +2.58% (p=0.000) TimeParse 622ns × (0.99,1.01) 615ns × (0.99,1.00) -1.06% (p=0.000) TimeFormat 665ns × (0.99,1.01) 654ns × (0.99,1.00) -1.70% (p=0.000) This CL and previous CL (append) combined: name old mean new mean delta BinaryTree17 5.68s × (0.97,1.04) 5.71s × (0.96,1.05) ~ (p=0.638) Fannkuch11 4.41s × (0.98,1.03) 4.39s × (1.00,1.00) ~ (p=0.474) FmtFprintfEmpty 92.7ns × (0.91,1.16) 82.6ns × (0.98,1.04) -10.89% (p=0.004) FmtFprintfString 281ns × (0.96,1.08) 273ns × (0.98,1.02) ~ (p=0.078) FmtFprintfInt 288ns × (0.97,1.06) 270ns × (0.99,1.01) -6.37% (p=0.000) FmtFprintfIntInt 493ns × (0.97,1.04) 475ns × (0.99,1.01) -3.53% (p=0.002) FmtFprintfPrefixedInt 423ns × (0.97,1.04) 393ns × (1.00,1.01) -7.07% (p=0.000) FmtFprintfFloat 598ns × (0.99,1.01) 574ns × (1.00,1.01) -4.02% (p=0.000) FmtManyArgs 1.89µs × (0.98,1.05) 1.87µs × (0.99,1.02) ~ (p=0.305) GobDecode 14.8ms × (0.98,1.03) 15.0ms × (0.98,1.05) ~ (p=0.237) GobEncode 12.3ms × (0.98,1.01) 11.4ms × (0.99,1.03) -6.95% (p=0.000) Gzip 656ms × (0.99,1.05) 647ms × (0.99,1.01) ~ (p=0.101) Gunzip 142ms × (1.00,1.00) 143ms × (1.00,1.01) +0.58% (p=0.001) HTTPClientServer 91.2µs × (0.97,1.04) 88.5µs × (0.99,1.03) -3.02% (p=0.003) JSONEncode 32.6ms × (0.97,1.08) 29.6ms × (0.98,1.01) -9.10% (p=0.000) JSONDecode 114ms × (0.97,1.05) 104ms × (1.00,1.01) -8.74% (p=0.000) Mandelbrot200 6.11ms × (0.98,1.04) 6.02ms × (1.00,1.00) ~ (p=0.090) GoParse 6.66ms × (0.97,1.04) 6.37ms × (0.97,1.04) -4.41% (p=0.000) RegexpMatchEasy0_32 159ns × (0.99,1.00) 152ns × (0.99,1.01) -4.69% (p=0.000) RegexpMatchEasy0_1K 538ns × (1.00,1.01) 530ns × (1.00,1.00) -1.57% (p=0.000) RegexpMatchEasy1_32 138ns × (1.00,1.00) 134ns × (0.99,1.01) -2.91% (p=0.000) RegexpMatchEasy1_1K 869ns × (0.99,1.01) 865ns × (1.00,1.00) -0.51% (p=0.012) RegexpMatchMedium_32 252ns × (0.99,1.01) 233ns × (1.00,1.00) -7.85% (p=0.000) RegexpMatchMedium_1K 72.7µs × (1.00,1.00) 69.5µs × (1.00,1.00) -4.43% (p=0.000) RegexpMatchHard_32 3.85µs × (1.00,1.00) 3.74µs × (1.00,1.00) -2.74% (p=0.000) RegexpMatchHard_1K 118µs × (1.00,1.00) 115µs × (1.00,1.00) -2.24% (p=0.000) Revcomp 920ms × (0.97,1.07) 920ms × (0.97,1.04) ~ (p=0.998) Template 129ms × (0.98,1.03) 117ms × (0.99,1.01) -9.79% (p=0.000) TimeParse 619ns × (0.99,1.01) 615ns × (0.99,1.00) -0.57% (p=0.011) TimeFormat 661ns × (0.98,1.04) 654ns × (0.99,1.00) ~ (p=0.223) Change-Id: If054d81ab2c71d8d62cf54b5b1fac2af66b387fc Reviewed-on: https://go-review.googlesource.com/9813 Reviewed-by: David Chase <drchase@google.com> Run-TryBot: Russ Cox <rsc@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
2015-05-06 12:35:53 -04:00
case ODOT, OLEN, OCAP:
l := safeexpr(n.Left, init)
if l == n.Left {
return n
}
r := n.copy()
r.Left = l
cmd/compile: bulk rename This change does a bulk rename of several identifiers in the compiler. See #27167 and https://docs.google.com/document/d/19_ExiylD9MRfeAjKIfEsMU1_RGhuxB9sA0b5Zv7byVI/ for context and for discussion of these particular renames. Commands run to generate this change: gorename -from '"cmd/compile/internal/gc".OPROC' -to OGO gorename -from '"cmd/compile/internal/gc".OCOM' -to OBITNOT gorename -from '"cmd/compile/internal/gc".OMINUS' -to ONEG gorename -from '"cmd/compile/internal/gc".OIND' -to ODEREF gorename -from '"cmd/compile/internal/gc".OARRAYBYTESTR' -to OBYTES2STR gorename -from '"cmd/compile/internal/gc".OARRAYBYTESTRTMP' -to OBYTES2STRTMP gorename -from '"cmd/compile/internal/gc".OARRAYRUNESTR' -to ORUNES2STR gorename -from '"cmd/compile/internal/gc".OSTRARRAYBYTE' -to OSTR2BYTES gorename -from '"cmd/compile/internal/gc".OSTRARRAYBYTETMP' -to OSTR2BYTESTMP gorename -from '"cmd/compile/internal/gc".OSTRARRAYRUNE' -to OSTR2RUNES gorename -from '"cmd/compile/internal/gc".Etop' -to ctxStmt gorename -from '"cmd/compile/internal/gc".Erv' -to ctxExpr gorename -from '"cmd/compile/internal/gc".Ecall' -to ctxCallee gorename -from '"cmd/compile/internal/gc".Efnstruct' -to ctxMultiOK gorename -from '"cmd/compile/internal/gc".Easgn' -to ctxAssign gorename -from '"cmd/compile/internal/gc".Ecomplit' -to ctxCompLit Not altered: parameters and local variables (mostly in typecheck.go) named top, which should probably now be called ctx (and which should probably have a named type). Also not altered: Field called Top in gc.Func. gorename -from '"cmd/compile/internal/gc".Node.Isddd' -to IsDDD gorename -from '"cmd/compile/internal/gc".Node.SetIsddd' -to SetIsDDD gorename -from '"cmd/compile/internal/gc".nodeIsddd' -to nodeIsDDD gorename -from '"cmd/compile/internal/types".Field.Isddd' -to IsDDD gorename -from '"cmd/compile/internal/types".Field.SetIsddd' -to SetIsDDD gorename -from '"cmd/compile/internal/types".fieldIsddd' -to fieldIsDDD Not altered: function gc.hasddd, params and local variables called isddd Also not altered: fmt.go prints nodes using "isddd(%v)". cd cmd/compile/internal/gc; go generate I then manually found impacted comments using exact string match and fixed them up by hand. The comment changes were trivial. Passes toolstash-check. Fixes #27167. If this experiment is deemed a success, we will open a new tracking issue for renames to do at the end of the 1.13 cycles. Change-Id: I2dc541533d2ab0d06cb3d31d65df205ecfb151e8 Reviewed-on: https://go-review.googlesource.com/c/150140 Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2018-11-18 08:34:38 -08:00
r = typecheck(r, ctxExpr)
cmd/compile: reduce use of **Node parameters Escape analysis has a hard time with tree-like structures (see #13493 and #14858). This is unlikely to change. As a result, when invoking a function that accepts a **Node parameter, we usually allocate a *Node on the heap. This happens a whole lot. This CL changes functions from taking a **Node to acting more like append: It both modifies the input and returns a replacement for it. Because of the cascading nature of escape analysis, in order to get the benefits, I had to modify almost all such functions. The remaining functions are in racewalk and the backend. I would be happy to update them as well in a separate CL. This CL was created by manually updating the function signatures and the directly impacted bits of code. The callsites were then automatically updated using a bespoke script: https://gist.github.com/josharian/046b1be7aceae244de39 For ease of reviewing and future understanding, this CL is also broken down into four CLs, mailed separately, which show the manual and the automated changes separately. They are CLs 20990, 20991, 20992, and 20993. Passes toolstash -cmp. name old time/op new time/op delta Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24) Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24) GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24) Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24) MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23) name old alloc/op new alloc/op delta Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23) Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25) GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25) Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25) name old allocs/op new allocs/op delta Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25) Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24) GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25) Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25) name old text-bytes new text-bytes delta HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal) CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal) name old data-bytes new data-bytes delta HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal) CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal) name old exe-bytes new exe-bytes delta HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal) CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal) Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475 Reviewed-on: https://go-review.googlesource.com/20959 Reviewed-by: Dave Cheney <dave@cheney.net> Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
r = walkexpr(r, init)
return r
cmd/compile: bulk rename This change does a bulk rename of several identifiers in the compiler. See #27167 and https://docs.google.com/document/d/19_ExiylD9MRfeAjKIfEsMU1_RGhuxB9sA0b5Zv7byVI/ for context and for discussion of these particular renames. Commands run to generate this change: gorename -from '"cmd/compile/internal/gc".OPROC' -to OGO gorename -from '"cmd/compile/internal/gc".OCOM' -to OBITNOT gorename -from '"cmd/compile/internal/gc".OMINUS' -to ONEG gorename -from '"cmd/compile/internal/gc".OIND' -to ODEREF gorename -from '"cmd/compile/internal/gc".OARRAYBYTESTR' -to OBYTES2STR gorename -from '"cmd/compile/internal/gc".OARRAYBYTESTRTMP' -to OBYTES2STRTMP gorename -from '"cmd/compile/internal/gc".OARRAYRUNESTR' -to ORUNES2STR gorename -from '"cmd/compile/internal/gc".OSTRARRAYBYTE' -to OSTR2BYTES gorename -from '"cmd/compile/internal/gc".OSTRARRAYBYTETMP' -to OSTR2BYTESTMP gorename -from '"cmd/compile/internal/gc".OSTRARRAYRUNE' -to OSTR2RUNES gorename -from '"cmd/compile/internal/gc".Etop' -to ctxStmt gorename -from '"cmd/compile/internal/gc".Erv' -to ctxExpr gorename -from '"cmd/compile/internal/gc".Ecall' -to ctxCallee gorename -from '"cmd/compile/internal/gc".Efnstruct' -to ctxMultiOK gorename -from '"cmd/compile/internal/gc".Easgn' -to ctxAssign gorename -from '"cmd/compile/internal/gc".Ecomplit' -to ctxCompLit Not altered: parameters and local variables (mostly in typecheck.go) named top, which should probably now be called ctx (and which should probably have a named type). Also not altered: Field called Top in gc.Func. gorename -from '"cmd/compile/internal/gc".Node.Isddd' -to IsDDD gorename -from '"cmd/compile/internal/gc".Node.SetIsddd' -to SetIsDDD gorename -from '"cmd/compile/internal/gc".nodeIsddd' -to nodeIsDDD gorename -from '"cmd/compile/internal/types".Field.Isddd' -to IsDDD gorename -from '"cmd/compile/internal/types".Field.SetIsddd' -to SetIsDDD gorename -from '"cmd/compile/internal/types".fieldIsddd' -to fieldIsDDD Not altered: function gc.hasddd, params and local variables called isddd Also not altered: fmt.go prints nodes using "isddd(%v)". cd cmd/compile/internal/gc; go generate I then manually found impacted comments using exact string match and fixed them up by hand. The comment changes were trivial. Passes toolstash-check. Fixes #27167. If this experiment is deemed a success, we will open a new tracking issue for renames to do at the end of the 1.13 cycles. Change-Id: I2dc541533d2ab0d06cb3d31d65df205ecfb151e8 Reviewed-on: https://go-review.googlesource.com/c/150140 Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2018-11-18 08:34:38 -08:00
case ODOTPTR, ODEREF:
l := safeexpr(n.Left, init)
if l == n.Left {
return n
}
a := n.copy()
a.Left = l
cmd/compile: reduce use of **Node parameters Escape analysis has a hard time with tree-like structures (see #13493 and #14858). This is unlikely to change. As a result, when invoking a function that accepts a **Node parameter, we usually allocate a *Node on the heap. This happens a whole lot. This CL changes functions from taking a **Node to acting more like append: It both modifies the input and returns a replacement for it. Because of the cascading nature of escape analysis, in order to get the benefits, I had to modify almost all such functions. The remaining functions are in racewalk and the backend. I would be happy to update them as well in a separate CL. This CL was created by manually updating the function signatures and the directly impacted bits of code. The callsites were then automatically updated using a bespoke script: https://gist.github.com/josharian/046b1be7aceae244de39 For ease of reviewing and future understanding, this CL is also broken down into four CLs, mailed separately, which show the manual and the automated changes separately. They are CLs 20990, 20991, 20992, and 20993. Passes toolstash -cmp. name old time/op new time/op delta Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24) Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24) GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24) Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24) MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23) name old alloc/op new alloc/op delta Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23) Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25) GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25) Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25) name old allocs/op new allocs/op delta Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25) Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24) GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25) Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25) name old text-bytes new text-bytes delta HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal) CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal) name old data-bytes new data-bytes delta HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal) CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal) name old exe-bytes new exe-bytes delta HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal) CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal) Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475 Reviewed-on: https://go-review.googlesource.com/20959 Reviewed-by: Dave Cheney <dave@cheney.net> Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
a = walkexpr(a, init)
return a
case OINDEX, OINDEXMAP:
l := safeexpr(n.Left, init)
r := safeexpr(n.Right, init)
if l == n.Left && r == n.Right {
return n
}
a := n.copy()
a.Left = l
a.Right = r
cmd/compile: reduce use of **Node parameters Escape analysis has a hard time with tree-like structures (see #13493 and #14858). This is unlikely to change. As a result, when invoking a function that accepts a **Node parameter, we usually allocate a *Node on the heap. This happens a whole lot. This CL changes functions from taking a **Node to acting more like append: It both modifies the input and returns a replacement for it. Because of the cascading nature of escape analysis, in order to get the benefits, I had to modify almost all such functions. The remaining functions are in racewalk and the backend. I would be happy to update them as well in a separate CL. This CL was created by manually updating the function signatures and the directly impacted bits of code. The callsites were then automatically updated using a bespoke script: https://gist.github.com/josharian/046b1be7aceae244de39 For ease of reviewing and future understanding, this CL is also broken down into four CLs, mailed separately, which show the manual and the automated changes separately. They are CLs 20990, 20991, 20992, and 20993. Passes toolstash -cmp. name old time/op new time/op delta Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24) Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24) GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24) Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24) MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23) name old alloc/op new alloc/op delta Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23) Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25) GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25) Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25) name old allocs/op new allocs/op delta Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25) Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24) GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25) Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25) name old text-bytes new text-bytes delta HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal) CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal) name old data-bytes new data-bytes delta HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal) CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal) name old exe-bytes new exe-bytes delta HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal) CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal) Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475 Reviewed-on: https://go-review.googlesource.com/20959 Reviewed-by: Dave Cheney <dave@cheney.net> Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
a = walkexpr(a, init)
return a
case OSTRUCTLIT, OARRAYLIT, OSLICELIT:
if isStaticCompositeLiteral(n) {
return n
}
}
// make a copy; must not be used as an lvalue
if islvalue(n) {
Fatalf("missing lvalue case in safeexpr: %v", n)
}
return cheapexpr(n, init)
}
func copyexpr(n *Node, t *types.Type, init *Nodes) *Node {
l := temp(t)
a := nod(OAS, l, n)
cmd/compile: bulk rename This change does a bulk rename of several identifiers in the compiler. See #27167 and https://docs.google.com/document/d/19_ExiylD9MRfeAjKIfEsMU1_RGhuxB9sA0b5Zv7byVI/ for context and for discussion of these particular renames. Commands run to generate this change: gorename -from '"cmd/compile/internal/gc".OPROC' -to OGO gorename -from '"cmd/compile/internal/gc".OCOM' -to OBITNOT gorename -from '"cmd/compile/internal/gc".OMINUS' -to ONEG gorename -from '"cmd/compile/internal/gc".OIND' -to ODEREF gorename -from '"cmd/compile/internal/gc".OARRAYBYTESTR' -to OBYTES2STR gorename -from '"cmd/compile/internal/gc".OARRAYBYTESTRTMP' -to OBYTES2STRTMP gorename -from '"cmd/compile/internal/gc".OARRAYRUNESTR' -to ORUNES2STR gorename -from '"cmd/compile/internal/gc".OSTRARRAYBYTE' -to OSTR2BYTES gorename -from '"cmd/compile/internal/gc".OSTRARRAYBYTETMP' -to OSTR2BYTESTMP gorename -from '"cmd/compile/internal/gc".OSTRARRAYRUNE' -to OSTR2RUNES gorename -from '"cmd/compile/internal/gc".Etop' -to ctxStmt gorename -from '"cmd/compile/internal/gc".Erv' -to ctxExpr gorename -from '"cmd/compile/internal/gc".Ecall' -to ctxCallee gorename -from '"cmd/compile/internal/gc".Efnstruct' -to ctxMultiOK gorename -from '"cmd/compile/internal/gc".Easgn' -to ctxAssign gorename -from '"cmd/compile/internal/gc".Ecomplit' -to ctxCompLit Not altered: parameters and local variables (mostly in typecheck.go) named top, which should probably now be called ctx (and which should probably have a named type). Also not altered: Field called Top in gc.Func. gorename -from '"cmd/compile/internal/gc".Node.Isddd' -to IsDDD gorename -from '"cmd/compile/internal/gc".Node.SetIsddd' -to SetIsDDD gorename -from '"cmd/compile/internal/gc".nodeIsddd' -to nodeIsDDD gorename -from '"cmd/compile/internal/types".Field.Isddd' -to IsDDD gorename -from '"cmd/compile/internal/types".Field.SetIsddd' -to SetIsDDD gorename -from '"cmd/compile/internal/types".fieldIsddd' -to fieldIsDDD Not altered: function gc.hasddd, params and local variables called isddd Also not altered: fmt.go prints nodes using "isddd(%v)". cd cmd/compile/internal/gc; go generate I then manually found impacted comments using exact string match and fixed them up by hand. The comment changes were trivial. Passes toolstash-check. Fixes #27167. If this experiment is deemed a success, we will open a new tracking issue for renames to do at the end of the 1.13 cycles. Change-Id: I2dc541533d2ab0d06cb3d31d65df205ecfb151e8 Reviewed-on: https://go-review.googlesource.com/c/150140 Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2018-11-18 08:34:38 -08:00
a = typecheck(a, ctxStmt)
cmd/compile: reduce use of **Node parameters Escape analysis has a hard time with tree-like structures (see #13493 and #14858). This is unlikely to change. As a result, when invoking a function that accepts a **Node parameter, we usually allocate a *Node on the heap. This happens a whole lot. This CL changes functions from taking a **Node to acting more like append: It both modifies the input and returns a replacement for it. Because of the cascading nature of escape analysis, in order to get the benefits, I had to modify almost all such functions. The remaining functions are in racewalk and the backend. I would be happy to update them as well in a separate CL. This CL was created by manually updating the function signatures and the directly impacted bits of code. The callsites were then automatically updated using a bespoke script: https://gist.github.com/josharian/046b1be7aceae244de39 For ease of reviewing and future understanding, this CL is also broken down into four CLs, mailed separately, which show the manual and the automated changes separately. They are CLs 20990, 20991, 20992, and 20993. Passes toolstash -cmp. name old time/op new time/op delta Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24) Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24) GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24) Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24) MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23) name old alloc/op new alloc/op delta Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23) Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25) GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25) Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25) name old allocs/op new allocs/op delta Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25) Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24) GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25) Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25) name old text-bytes new text-bytes delta HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal) CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal) name old data-bytes new data-bytes delta HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal) CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal) name old exe-bytes new exe-bytes delta HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal) CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal) Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475 Reviewed-on: https://go-review.googlesource.com/20959 Reviewed-by: Dave Cheney <dave@cheney.net> Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
a = walkexpr(a, init)
init.Append(a)
return l
}
// return side-effect free and cheap n, appending side effects to init.
// result may not be assignable.
func cheapexpr(n *Node, init *Nodes) *Node {
switch n.Op {
case ONAME, OLITERAL:
return n
}
return copyexpr(n, n.Type, init)
}
// Code to resolve elided DOTs in embedded types.
// A Dlist stores a pointer to a TFIELD Type embedded within
// a TSTRUCT or TINTER Type.
type Dlist struct {
field *types.Field
}
// dotlist is used by adddot1 to record the path of embedded fields
// used to access a target field or method.
// Must be non-nil so that dotpath returns a non-nil slice even if d is zero.
var dotlist = make([]Dlist, 10)
// lookdot0 returns the number of fields or methods named s associated
// with Type t. If exactly one exists, it will be returned in *save
// (if save is not nil).
func lookdot0(s *types.Sym, t *types.Type, save **types.Field, ignorecase bool) int {
u := t
if u.IsPtr() {
u = u.Elem()
}
c := 0
if u.IsStruct() || u.IsInterface() {
for _, f := range u.Fields().Slice() {
if f.Sym == s || (ignorecase && f.IsMethod() && strings.EqualFold(f.Sym.Name, s.Name)) {
if save != nil {
*save = f
}
c++
}
}
}
u = t
if t.Sym != nil && t.IsPtr() && !t.Elem().IsPtr() {
// If t is a defined pointer type, then x.m is shorthand for (*x).m.
u = t.Elem()
}
u = methtype(u)
if u != nil {
for _, f := range u.Methods().Slice() {
if f.Embedded == 0 && (f.Sym == s || (ignorecase && strings.EqualFold(f.Sym.Name, s.Name))) {
if save != nil {
*save = f
}
c++
}
}
}
return c
}
// adddot1 returns the number of fields or methods named s at depth d in Type t.
// If exactly one exists, it will be returned in *save (if save is not nil),
// and dotlist will contain the path of embedded fields traversed to find it,
// in reverse order. If none exist, more will indicate whether t contains any
// embedded fields at depth d, so callers can decide whether to retry at
// a greater depth.
func adddot1(s *types.Sym, t *types.Type, d int, save **types.Field, ignorecase bool) (c int, more bool) {
if t.Recur() {
return
}
t.SetRecur(true)
defer t.SetRecur(false)
var u *types.Type
d--
if d < 0 {
// We've reached our target depth. If t has any fields/methods
// named s, then we're done. Otherwise, we still need to check
// below for embedded fields.
c = lookdot0(s, t, save, ignorecase)
if c != 0 {
return c, false
}
}
u = t
if u.IsPtr() {
u = u.Elem()
}
if !u.IsStruct() && !u.IsInterface() {
return c, false
}
for _, f := range u.Fields().Slice() {
if f.Embedded == 0 || f.Sym == nil {
continue
}
if d < 0 {
// Found an embedded field at target depth.
return c, true
}
a, more1 := adddot1(s, f.Type, d, save, ignorecase)
if a != 0 && c == 0 {
dotlist[d].field = f
}
c += a
if more1 {
more = true
}
}
return c, more
}
// dotpath computes the unique shortest explicit selector path to fully qualify
// a selection expression x.f, where x is of type t and f is the symbol s.
// If no such path exists, dotpath returns nil.
// If there are multiple shortest paths to the same depth, ambig is true.
func dotpath(s *types.Sym, t *types.Type, save **types.Field, ignorecase bool) (path []Dlist, ambig bool) {
// The embedding of types within structs imposes a tree structure onto
// types: structs parent the types they embed, and types parent their
// fields or methods. Our goal here is to find the shortest path to
// a field or method named s in the subtree rooted at t. To accomplish
// that, we iteratively perform depth-first searches of increasing depth
// until we either find the named field/method or exhaust the tree.
for d := 0; ; d++ {
if d > len(dotlist) {
dotlist = append(dotlist, Dlist{})
}
if c, more := adddot1(s, t, d, save, ignorecase); c == 1 {
return dotlist[:d], false
} else if c > 1 {
return nil, true
} else if !more {
return nil, false
}
}
}
// in T.field
// find missing fields that
// will give shortest unique addressing.
// modify the tree with missing type names.
func adddot(n *Node) *Node {
n.Left = typecheck(n.Left, ctxType|ctxExpr)
cmd/compile: pack bool fields in Node, Name, Func and Type structs to bitsets This reduces compiler memory usage by up to 4% - see compilebench results below. name old time/op new time/op delta Template 245ms ± 4% 241ms ± 2% -1.88% (p=0.029 n=10+10) Unicode 126ms ± 3% 124ms ± 3% ~ (p=0.105 n=10+10) GoTypes 805ms ± 2% 813ms ± 3% ~ (p=0.515 n=8+10) Compiler 3.95s ± 2% 3.83s ± 1% -2.96% (p=0.000 n=9+10) MakeBash 47.4s ± 4% 46.6s ± 1% -1.59% (p=0.028 n=9+10) name old user-ns/op new user-ns/op delta Template 324M ± 5% 326M ± 3% ~ (p=0.935 n=10+10) Unicode 186M ± 5% 178M ±10% ~ (p=0.067 n=9+10) GoTypes 1.08G ± 7% 1.09G ± 4% ~ (p=0.956 n=10+10) Compiler 5.34G ± 4% 5.31G ± 1% ~ (p=0.501 n=10+8) name old alloc/op new alloc/op delta Template 41.0MB ± 0% 39.8MB ± 0% -3.03% (p=0.000 n=10+10) Unicode 32.3MB ± 0% 31.0MB ± 0% -4.13% (p=0.000 n=10+10) GoTypes 119MB ± 0% 116MB ± 0% -2.39% (p=0.000 n=10+10) Compiler 499MB ± 0% 487MB ± 0% -2.48% (p=0.000 n=10+10) name old allocs/op new allocs/op delta Template 380k ± 1% 379k ± 1% ~ (p=0.436 n=10+10) Unicode 324k ± 1% 324k ± 0% ~ (p=0.853 n=10+10) GoTypes 1.15M ± 0% 1.15M ± 0% ~ (p=0.481 n=10+10) Compiler 4.41M ± 0% 4.41M ± 0% -0.12% (p=0.007 n=10+10) name old text-bytes new text-bytes delta HelloSize 623k ± 0% 623k ± 0% ~ (all equal) CmdGoSize 6.64M ± 0% 6.64M ± 0% ~ (all equal) name old data-bytes new data-bytes delta HelloSize 5.81k ± 0% 5.81k ± 0% ~ (all equal) CmdGoSize 238k ± 0% 238k ± 0% ~ (all equal) name old bss-bytes new bss-bytes delta HelloSize 134k ± 0% 134k ± 0% ~ (all equal) CmdGoSize 152k ± 0% 152k ± 0% ~ (all equal) name old exe-bytes new exe-bytes delta HelloSize 967k ± 0% 967k ± 0% ~ (all equal) CmdGoSize 10.2M ± 0% 10.2M ± 0% ~ (all equal) Change-Id: I1f40af738254892bd6c8ba2eb43390b175753d52 Reviewed-on: https://go-review.googlesource.com/37445 Reviewed-by: Matthew Dempsky <mdempsky@google.com> Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
2017-02-27 19:56:38 +02:00
if n.Left.Diag() {
n.SetDiag(true)
}
t := n.Left.Type
if t == nil {
return n
}
if n.Left.Op == OTYPE {
return n
}
s := n.Sym
if s == nil {
return n
}
switch path, ambig := dotpath(s, t, nil, false); {
case path != nil:
// rebuild elided dots
for c := len(path) - 1; c >= 0; c-- {
n.Left = nodSym(ODOT, n.Left, path[c].field.Sym)
cmd/compile: pack bool fields in Node, Name, Func and Type structs to bitsets This reduces compiler memory usage by up to 4% - see compilebench results below. name old time/op new time/op delta Template 245ms ± 4% 241ms ± 2% -1.88% (p=0.029 n=10+10) Unicode 126ms ± 3% 124ms ± 3% ~ (p=0.105 n=10+10) GoTypes 805ms ± 2% 813ms ± 3% ~ (p=0.515 n=8+10) Compiler 3.95s ± 2% 3.83s ± 1% -2.96% (p=0.000 n=9+10) MakeBash 47.4s ± 4% 46.6s ± 1% -1.59% (p=0.028 n=9+10) name old user-ns/op new user-ns/op delta Template 324M ± 5% 326M ± 3% ~ (p=0.935 n=10+10) Unicode 186M ± 5% 178M ±10% ~ (p=0.067 n=9+10) GoTypes 1.08G ± 7% 1.09G ± 4% ~ (p=0.956 n=10+10) Compiler 5.34G ± 4% 5.31G ± 1% ~ (p=0.501 n=10+8) name old alloc/op new alloc/op delta Template 41.0MB ± 0% 39.8MB ± 0% -3.03% (p=0.000 n=10+10) Unicode 32.3MB ± 0% 31.0MB ± 0% -4.13% (p=0.000 n=10+10) GoTypes 119MB ± 0% 116MB ± 0% -2.39% (p=0.000 n=10+10) Compiler 499MB ± 0% 487MB ± 0% -2.48% (p=0.000 n=10+10) name old allocs/op new allocs/op delta Template 380k ± 1% 379k ± 1% ~ (p=0.436 n=10+10) Unicode 324k ± 1% 324k ± 0% ~ (p=0.853 n=10+10) GoTypes 1.15M ± 0% 1.15M ± 0% ~ (p=0.481 n=10+10) Compiler 4.41M ± 0% 4.41M ± 0% -0.12% (p=0.007 n=10+10) name old text-bytes new text-bytes delta HelloSize 623k ± 0% 623k ± 0% ~ (all equal) CmdGoSize 6.64M ± 0% 6.64M ± 0% ~ (all equal) name old data-bytes new data-bytes delta HelloSize 5.81k ± 0% 5.81k ± 0% ~ (all equal) CmdGoSize 238k ± 0% 238k ± 0% ~ (all equal) name old bss-bytes new bss-bytes delta HelloSize 134k ± 0% 134k ± 0% ~ (all equal) CmdGoSize 152k ± 0% 152k ± 0% ~ (all equal) name old exe-bytes new exe-bytes delta HelloSize 967k ± 0% 967k ± 0% ~ (all equal) CmdGoSize 10.2M ± 0% 10.2M ± 0% ~ (all equal) Change-Id: I1f40af738254892bd6c8ba2eb43390b175753d52 Reviewed-on: https://go-review.googlesource.com/37445 Reviewed-by: Matthew Dempsky <mdempsky@google.com> Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
2017-02-27 19:56:38 +02:00
n.Left.SetImplicit(true)
}
case ambig:
yyerror("ambiguous selector %v", n)
n.Left = nil
}
return n
}
// Code to help generate trampoline functions for methods on embedded
// types. These are approx the same as the corresponding adddot
// routines except that they expect to be called with unique tasks and
// they return the actual methods.
type Symlink struct {
field *types.Field
}
var slist []Symlink
func expand0(t *types.Type) {
u := t
if u.IsPtr() {
u = u.Elem()
}
if u.IsInterface() {
for _, f := range u.Fields().Slice() {
if f.Sym.Uniq() {
continue
}
f.Sym.SetUniq(true)
slist = append(slist, Symlink{field: f})
}
return
}
u = methtype(t)
if u != nil {
for _, f := range u.Methods().Slice() {
if f.Sym.Uniq() {
continue
}
f.Sym.SetUniq(true)
slist = append(slist, Symlink{field: f})
}
}
}
func expand1(t *types.Type, top bool) {
if t.Recur() {
return
}
t.SetRecur(true)
if !top {
expand0(t)
}
u := t
if u.IsPtr() {
u = u.Elem()
}
if u.IsStruct() || u.IsInterface() {
for _, f := range u.Fields().Slice() {
if f.Embedded == 0 {
continue
}
if f.Sym == nil {
continue
}
expand1(f.Type, false)
}
}
t.SetRecur(false)
}
func expandmeth(t *types.Type) {
if t == nil || t.AllMethods().Len() != 0 {
return
}
// mark top-level method symbols
// so that expand1 doesn't consider them.
for _, f := range t.Methods().Slice() {
f.Sym.SetUniq(true)
}
// generate all reachable methods
slist = slist[:0]
expand1(t, true)
// check each method to be uniquely reachable
var ms []*types.Field
for i, sl := range slist {
slist[i].field = nil
sl.field.Sym.SetUniq(false)
var f *types.Field
path, _ := dotpath(sl.field.Sym, t, &f, false)
if path == nil {
continue
}
// dotpath may have dug out arbitrary fields, we only want methods.
if !f.IsMethod() {
continue
}
// add it to the base type method list
f = f.Copy()
f.Embedded = 1 // needs a trampoline
for _, d := range path {
if d.field.Type.IsPtr() {
f.Embedded = 2
break
}
}
ms = append(ms, f)
}
for _, f := range t.Methods().Slice() {
f.Sym.SetUniq(false)
}
ms = append(ms, t.Methods().Slice()...)
sort.Sort(methcmp(ms))
t.AllMethods().Set(ms)
}
// Given funarg struct list, return list of ODCLFIELD Node fn args.
func structargs(tl *types.Type, mustname bool) []*Node {
var args []*Node
gen := 0
for _, t := range tl.Fields().Slice() {
cmd/compile: replace Field.Nname.Pos with Field.Pos For struct fields and methods, Field.Nname was only used to store position information, which means we're allocating an entire ONAME Node+Name+Param structure just for one field. We can optimize away these ONAME allocations by instead adding a Field.Pos field. Unfortunately, we can't get rid of Field.Nname, because it's needed for function parameters, so Field grows a little bit and now has more redundant information in those cases. However, that was already the case (e.g., Field.Sym and Field.Nname.Sym), and it's still a net win for allocations as demonstrated by the benchmarks below. Additionally, by moving the ONAME allocation for function parameters to funcargs, we can avoid allocating them for function parameters that aren't used in corresponding function bodies (e.g., interface methods, function-typed variables, and imported functions/methods without inline bodies). name old time/op new time/op delta Template 254ms ± 6% 251ms ± 6% -1.04% (p=0.000 n=487+488) Unicode 128ms ± 7% 128ms ± 7% ~ (p=0.294 n=482+467) GoTypes 862ms ± 5% 860ms ± 4% ~ (p=0.075 n=488+471) Compiler 3.91s ± 4% 3.90s ± 4% -0.39% (p=0.000 n=468+473) name old user-time/op new user-time/op delta Template 339ms ±14% 336ms ±14% -1.02% (p=0.001 n=498+494) Unicode 176ms ±18% 176ms ±25% ~ (p=0.940 n=491+499) GoTypes 1.13s ± 8% 1.13s ± 9% ~ (p=0.157 n=496+493) Compiler 5.24s ± 6% 5.21s ± 6% -0.57% (p=0.000 n=485+489) name old alloc/op new alloc/op delta Template 38.3MB ± 0% 37.3MB ± 0% -2.58% (p=0.000 n=499+497) Unicode 29.1MB ± 0% 29.1MB ± 0% -0.03% (p=0.000 n=500+493) GoTypes 116MB ± 0% 115MB ± 0% -0.65% (p=0.000 n=498+499) Compiler 492MB ± 0% 487MB ± 0% -1.00% (p=0.000 n=497+498) name old allocs/op new allocs/op delta Template 364k ± 0% 360k ± 0% -1.15% (p=0.000 n=499+499) Unicode 336k ± 0% 336k ± 0% -0.01% (p=0.000 n=500+493) GoTypes 1.16M ± 0% 1.16M ± 0% -0.30% (p=0.000 n=499+499) Compiler 4.54M ± 0% 4.51M ± 0% -0.58% (p=0.000 n=494+495) Passes toolstash-check -gcflags=-dwarf=false. Changes DWARF output because position information is now tracked more precisely for function parameters. Change-Id: Ib8077d70d564cc448c5e4290baceab3a4396d712 Reviewed-on: https://go-review.googlesource.com/108217 Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org>
2018-04-18 22:57:10 -07:00
s := t.Sym
if mustname && (s == nil || s.Name == "_") {
// invent a name so that we can refer to it in the trampoline
cmd/compile: replace Field.Nname.Pos with Field.Pos For struct fields and methods, Field.Nname was only used to store position information, which means we're allocating an entire ONAME Node+Name+Param structure just for one field. We can optimize away these ONAME allocations by instead adding a Field.Pos field. Unfortunately, we can't get rid of Field.Nname, because it's needed for function parameters, so Field grows a little bit and now has more redundant information in those cases. However, that was already the case (e.g., Field.Sym and Field.Nname.Sym), and it's still a net win for allocations as demonstrated by the benchmarks below. Additionally, by moving the ONAME allocation for function parameters to funcargs, we can avoid allocating them for function parameters that aren't used in corresponding function bodies (e.g., interface methods, function-typed variables, and imported functions/methods without inline bodies). name old time/op new time/op delta Template 254ms ± 6% 251ms ± 6% -1.04% (p=0.000 n=487+488) Unicode 128ms ± 7% 128ms ± 7% ~ (p=0.294 n=482+467) GoTypes 862ms ± 5% 860ms ± 4% ~ (p=0.075 n=488+471) Compiler 3.91s ± 4% 3.90s ± 4% -0.39% (p=0.000 n=468+473) name old user-time/op new user-time/op delta Template 339ms ±14% 336ms ±14% -1.02% (p=0.001 n=498+494) Unicode 176ms ±18% 176ms ±25% ~ (p=0.940 n=491+499) GoTypes 1.13s ± 8% 1.13s ± 9% ~ (p=0.157 n=496+493) Compiler 5.24s ± 6% 5.21s ± 6% -0.57% (p=0.000 n=485+489) name old alloc/op new alloc/op delta Template 38.3MB ± 0% 37.3MB ± 0% -2.58% (p=0.000 n=499+497) Unicode 29.1MB ± 0% 29.1MB ± 0% -0.03% (p=0.000 n=500+493) GoTypes 116MB ± 0% 115MB ± 0% -0.65% (p=0.000 n=498+499) Compiler 492MB ± 0% 487MB ± 0% -1.00% (p=0.000 n=497+498) name old allocs/op new allocs/op delta Template 364k ± 0% 360k ± 0% -1.15% (p=0.000 n=499+499) Unicode 336k ± 0% 336k ± 0% -0.01% (p=0.000 n=500+493) GoTypes 1.16M ± 0% 1.16M ± 0% -0.30% (p=0.000 n=499+499) Compiler 4.54M ± 0% 4.51M ± 0% -0.58% (p=0.000 n=494+495) Passes toolstash-check -gcflags=-dwarf=false. Changes DWARF output because position information is now tracked more precisely for function parameters. Change-Id: Ib8077d70d564cc448c5e4290baceab3a4396d712 Reviewed-on: https://go-review.googlesource.com/108217 Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org>
2018-04-18 22:57:10 -07:00
s = lookupN(".anon", gen)
gen++
}
cmd/compile: replace Field.Nname.Pos with Field.Pos For struct fields and methods, Field.Nname was only used to store position information, which means we're allocating an entire ONAME Node+Name+Param structure just for one field. We can optimize away these ONAME allocations by instead adding a Field.Pos field. Unfortunately, we can't get rid of Field.Nname, because it's needed for function parameters, so Field grows a little bit and now has more redundant information in those cases. However, that was already the case (e.g., Field.Sym and Field.Nname.Sym), and it's still a net win for allocations as demonstrated by the benchmarks below. Additionally, by moving the ONAME allocation for function parameters to funcargs, we can avoid allocating them for function parameters that aren't used in corresponding function bodies (e.g., interface methods, function-typed variables, and imported functions/methods without inline bodies). name old time/op new time/op delta Template 254ms ± 6% 251ms ± 6% -1.04% (p=0.000 n=487+488) Unicode 128ms ± 7% 128ms ± 7% ~ (p=0.294 n=482+467) GoTypes 862ms ± 5% 860ms ± 4% ~ (p=0.075 n=488+471) Compiler 3.91s ± 4% 3.90s ± 4% -0.39% (p=0.000 n=468+473) name old user-time/op new user-time/op delta Template 339ms ±14% 336ms ±14% -1.02% (p=0.001 n=498+494) Unicode 176ms ±18% 176ms ±25% ~ (p=0.940 n=491+499) GoTypes 1.13s ± 8% 1.13s ± 9% ~ (p=0.157 n=496+493) Compiler 5.24s ± 6% 5.21s ± 6% -0.57% (p=0.000 n=485+489) name old alloc/op new alloc/op delta Template 38.3MB ± 0% 37.3MB ± 0% -2.58% (p=0.000 n=499+497) Unicode 29.1MB ± 0% 29.1MB ± 0% -0.03% (p=0.000 n=500+493) GoTypes 116MB ± 0% 115MB ± 0% -0.65% (p=0.000 n=498+499) Compiler 492MB ± 0% 487MB ± 0% -1.00% (p=0.000 n=497+498) name old allocs/op new allocs/op delta Template 364k ± 0% 360k ± 0% -1.15% (p=0.000 n=499+499) Unicode 336k ± 0% 336k ± 0% -0.01% (p=0.000 n=500+493) GoTypes 1.16M ± 0% 1.16M ± 0% -0.30% (p=0.000 n=499+499) Compiler 4.54M ± 0% 4.51M ± 0% -0.58% (p=0.000 n=494+495) Passes toolstash-check -gcflags=-dwarf=false. Changes DWARF output because position information is now tracked more precisely for function parameters. Change-Id: Ib8077d70d564cc448c5e4290baceab3a4396d712 Reviewed-on: https://go-review.googlesource.com/108217 Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org>
2018-04-18 22:57:10 -07:00
a := symfield(s, t.Type)
cmd/compile: add indexed export format This CL introduces a new indexed data format for package export data. This improves on the previous (sequential) binary format by allowing the compiler to selectively (and lazily) load only the data that's actually needed for compilation. In large Go projects, the package export data can become very large due to transitive type declaration dependencies and inline function/method bodies. By lazily loading these declarations and bodies as needed, we avoid wasting time and memory processing unnecessary and/or redundant data. In the benchmarks below, "old" is -iexport=false and "new" is -iexport=true. The suffixes indicate the compiler concurrency (-c) and inlining (-l) settings used for the build (using -gcflags=all=-foo). Benchmarks were run on an HP Z620. Juju is "go build -a github.com/juju/juju/cmd/...": name old real-time/op new real-time/op delta Juju/c=1/l=0 44.0s ± 1% 38.7s ± 9% -11.97% (p=0.001 n=7+7) Juju/c=1/l=4 53.7s ± 3% 45.3s ± 4% -15.53% (p=0.001 n=7+7) Juju/c=4/l=0 39.7s ± 8% 32.0s ± 4% -19.38% (p=0.001 n=7+7) Juju/c=4/l=4 46.3s ± 4% 38.0s ± 4% -18.06% (p=0.001 n=7+7) name old user-time/op new user-time/op delta Juju/c=1/l=0 371s ± 1% 300s ± 0% -19.07% (p=0.001 n=7+6) Juju/c=1/l=4 482s ± 0% 374s ± 1% -22.37% (p=0.001 n=7+7) Juju/c=4/l=0 410s ± 1% 340s ± 1% -17.19% (p=0.001 n=7+7) Juju/c=4/l=4 532s ± 1% 424s ± 1% -20.26% (p=0.001 n=7+7) name old sys-time/op new sys-time/op delta Juju/c=1/l=0 33.4s ± 1% 28.4s ± 2% -15.02% (p=0.001 n=7+7) Juju/c=1/l=4 40.7s ± 2% 32.8s ± 3% -19.51% (p=0.001 n=7+7) Juju/c=4/l=0 39.8s ± 2% 34.4s ± 2% -13.74% (p=0.001 n=7+7) Juju/c=4/l=4 48.4s ± 2% 40.4s ± 2% -16.50% (p=0.001 n=7+7) Kubelet is "go build -a k8s.io/kubernetes/cmd/kubelet": name old real-time/op new real-time/op delta Kubelet/c=1/l=0 42.0s ± 1% 34.8s ± 1% -17.27% (p=0.008 n=5+5) Kubelet/c=1/l=4 55.4s ± 3% 45.4s ± 3% -18.06% (p=0.002 n=6+6) Kubelet/c=4/l=0 37.4s ± 3% 29.9s ± 1% -20.25% (p=0.004 n=6+5) Kubelet/c=4/l=4 48.1s ± 2% 39.0s ± 5% -18.93% (p=0.002 n=6+6) name old user-time/op new user-time/op delta Kubelet/c=1/l=0 291s ± 1% 233s ± 1% -19.96% (p=0.002 n=6+6) Kubelet/c=1/l=4 385s ± 1% 298s ± 1% -22.51% (p=0.002 n=6+6) Kubelet/c=4/l=0 325s ± 0% 268s ± 1% -17.48% (p=0.004 n=5+6) Kubelet/c=4/l=4 429s ± 1% 343s ± 1% -20.08% (p=0.002 n=6+6) name old sys-time/op new sys-time/op delta Kubelet/c=1/l=0 25.1s ± 2% 20.9s ± 4% -16.69% (p=0.002 n=6+6) Kubelet/c=1/l=4 31.2s ± 3% 24.4s ± 0% -21.67% (p=0.010 n=6+4) Kubelet/c=4/l=0 30.2s ± 2% 25.6s ± 1% -15.34% (p=0.002 n=6+6) Kubelet/c=4/l=4 37.3s ± 1% 30.9s ± 2% -17.11% (p=0.002 n=6+6) Change-Id: Ie43eb3bbe1392cbb61c86792a17a57b33b9561f0 Reviewed-on: https://go-review.googlesource.com/106796 Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org>
2018-04-01 01:55:55 -07:00
a.Pos = t.Pos
cmd/compile: bulk rename This change does a bulk rename of several identifiers in the compiler. See #27167 and https://docs.google.com/document/d/19_ExiylD9MRfeAjKIfEsMU1_RGhuxB9sA0b5Zv7byVI/ for context and for discussion of these particular renames. Commands run to generate this change: gorename -from '"cmd/compile/internal/gc".OPROC' -to OGO gorename -from '"cmd/compile/internal/gc".OCOM' -to OBITNOT gorename -from '"cmd/compile/internal/gc".OMINUS' -to ONEG gorename -from '"cmd/compile/internal/gc".OIND' -to ODEREF gorename -from '"cmd/compile/internal/gc".OARRAYBYTESTR' -to OBYTES2STR gorename -from '"cmd/compile/internal/gc".OARRAYBYTESTRTMP' -to OBYTES2STRTMP gorename -from '"cmd/compile/internal/gc".OARRAYRUNESTR' -to ORUNES2STR gorename -from '"cmd/compile/internal/gc".OSTRARRAYBYTE' -to OSTR2BYTES gorename -from '"cmd/compile/internal/gc".OSTRARRAYBYTETMP' -to OSTR2BYTESTMP gorename -from '"cmd/compile/internal/gc".OSTRARRAYRUNE' -to OSTR2RUNES gorename -from '"cmd/compile/internal/gc".Etop' -to ctxStmt gorename -from '"cmd/compile/internal/gc".Erv' -to ctxExpr gorename -from '"cmd/compile/internal/gc".Ecall' -to ctxCallee gorename -from '"cmd/compile/internal/gc".Efnstruct' -to ctxMultiOK gorename -from '"cmd/compile/internal/gc".Easgn' -to ctxAssign gorename -from '"cmd/compile/internal/gc".Ecomplit' -to ctxCompLit Not altered: parameters and local variables (mostly in typecheck.go) named top, which should probably now be called ctx (and which should probably have a named type). Also not altered: Field called Top in gc.Func. gorename -from '"cmd/compile/internal/gc".Node.Isddd' -to IsDDD gorename -from '"cmd/compile/internal/gc".Node.SetIsddd' -to SetIsDDD gorename -from '"cmd/compile/internal/gc".nodeIsddd' -to nodeIsDDD gorename -from '"cmd/compile/internal/types".Field.Isddd' -to IsDDD gorename -from '"cmd/compile/internal/types".Field.SetIsddd' -to SetIsDDD gorename -from '"cmd/compile/internal/types".fieldIsddd' -to fieldIsDDD Not altered: function gc.hasddd, params and local variables called isddd Also not altered: fmt.go prints nodes using "isddd(%v)". cd cmd/compile/internal/gc; go generate I then manually found impacted comments using exact string match and fixed them up by hand. The comment changes were trivial. Passes toolstash-check. Fixes #27167. If this experiment is deemed a success, we will open a new tracking issue for renames to do at the end of the 1.13 cycles. Change-Id: I2dc541533d2ab0d06cb3d31d65df205ecfb151e8 Reviewed-on: https://go-review.googlesource.com/c/150140 Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2018-11-18 08:34:38 -08:00
a.SetIsDDD(t.IsDDD())
args = append(args, a)
}
return args
}
// Generate a wrapper function to convert from
// a receiver of type T to a receiver of type U.
// That is,
//
// func (t T) M() {
// ...
// }
//
// already exists; this function generates
//
// func (u U) M() {
// u.M()
// }
//
// where the types T and U are such that u.M() is valid
// and calls the T.M method.
// The resulting function is for use in method tables.
//
// rcvr - U
// method - M func (t T)(), a TFIELD type struct
// newnam - the eventual mangled name of this function
func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym) {
if false && Debug['r'] != 0 {
fmt.Printf("genwrapper rcvrtype=%v method=%v newnam=%v\n", rcvr, method, newnam)
}
// Only generate (*T).M wrappers for T.M in T's own package.
if rcvr.IsPtr() && rcvr.Elem() == method.Type.Recv().Type &&
rcvr.Elem().Sym != nil && rcvr.Elem().Sym.Pkg != localpkg {
return
}
// Only generate I.M wrappers for I in I's own package
// but keep doing it for error.Error (was issue #29304).
if rcvr.IsInterface() && rcvr.Sym != nil && rcvr.Sym.Pkg != localpkg && rcvr != types.Errortype {
return
}
lineno = autogeneratedPos
dclcontext = PEXTERN
tfn := nod(OTFUNC, nil, nil)
tfn.Left = namedfield(".this", rcvr)
tfn.List.Set(structargs(method.Type.Params(), true))
tfn.Rlist.Set(structargs(method.Type.Results(), false))
disableExport(newnam)
fn := dclfunc(newnam, tfn)
fn.Func.SetDupok(true)
nthis := asNode(tfn.Type.Recv().Nname)
methodrcvr := method.Type.Recv().Type
// generate nil pointer check for better error
if rcvr.IsPtr() && rcvr.Elem() == methodrcvr {
// generating wrapper from *T to T.
n := nod(OIF, nil, nil)
n.Left = nod(OEQ, nthis, nodnil())
call := nod(OCALL, syslook("panicwrap"), nil)
n.Nbody.Set1(call)
fn.Nbody.Append(n)
}
dot := adddot(nodSym(OXDOT, nthis, method.Sym))
// generate call
// It's not possible to use a tail call when dynamic linking on ppc64le. The
// bad scenario is when a local call is made to the wrapper: the wrapper will
// call the implementation, which might be in a different module and so set
// the TOC to the appropriate value for that module. But if it returns
// directly to the wrapper's caller, nothing will reset it to the correct
// value for that function.
if !instrumenting && rcvr.IsPtr() && methodrcvr.IsPtr() && method.Embedded != 0 && !isifacemethod(method.Type) && !(thearch.LinkArch.Name == "ppc64le" && Ctxt.Flag_dynlink) {
// generate tail call: adjust pointer receiver and jump to embedded method.
dot = dot.Left // skip final .M
// TODO(mdempsky): Remove dependency on dotlist.
if !dotlist[0].field.Type.IsPtr() {
dot = nod(OADDR, dot, nil)
}
as := nod(OAS, nthis, convnop(dot, rcvr))
fn.Nbody.Append(as)
fn.Nbody.Append(nodSym(ORETJMP, nil, methodSym(methodrcvr, method.Sym)))
} else {
cmd/compile: pack bool fields in Node, Name, Func and Type structs to bitsets This reduces compiler memory usage by up to 4% - see compilebench results below. name old time/op new time/op delta Template 245ms ± 4% 241ms ± 2% -1.88% (p=0.029 n=10+10) Unicode 126ms ± 3% 124ms ± 3% ~ (p=0.105 n=10+10) GoTypes 805ms ± 2% 813ms ± 3% ~ (p=0.515 n=8+10) Compiler 3.95s ± 2% 3.83s ± 1% -2.96% (p=0.000 n=9+10) MakeBash 47.4s ± 4% 46.6s ± 1% -1.59% (p=0.028 n=9+10) name old user-ns/op new user-ns/op delta Template 324M ± 5% 326M ± 3% ~ (p=0.935 n=10+10) Unicode 186M ± 5% 178M ±10% ~ (p=0.067 n=9+10) GoTypes 1.08G ± 7% 1.09G ± 4% ~ (p=0.956 n=10+10) Compiler 5.34G ± 4% 5.31G ± 1% ~ (p=0.501 n=10+8) name old alloc/op new alloc/op delta Template 41.0MB ± 0% 39.8MB ± 0% -3.03% (p=0.000 n=10+10) Unicode 32.3MB ± 0% 31.0MB ± 0% -4.13% (p=0.000 n=10+10) GoTypes 119MB ± 0% 116MB ± 0% -2.39% (p=0.000 n=10+10) Compiler 499MB ± 0% 487MB ± 0% -2.48% (p=0.000 n=10+10) name old allocs/op new allocs/op delta Template 380k ± 1% 379k ± 1% ~ (p=0.436 n=10+10) Unicode 324k ± 1% 324k ± 0% ~ (p=0.853 n=10+10) GoTypes 1.15M ± 0% 1.15M ± 0% ~ (p=0.481 n=10+10) Compiler 4.41M ± 0% 4.41M ± 0% -0.12% (p=0.007 n=10+10) name old text-bytes new text-bytes delta HelloSize 623k ± 0% 623k ± 0% ~ (all equal) CmdGoSize 6.64M ± 0% 6.64M ± 0% ~ (all equal) name old data-bytes new data-bytes delta HelloSize 5.81k ± 0% 5.81k ± 0% ~ (all equal) CmdGoSize 238k ± 0% 238k ± 0% ~ (all equal) name old bss-bytes new bss-bytes delta HelloSize 134k ± 0% 134k ± 0% ~ (all equal) CmdGoSize 152k ± 0% 152k ± 0% ~ (all equal) name old exe-bytes new exe-bytes delta HelloSize 967k ± 0% 967k ± 0% ~ (all equal) CmdGoSize 10.2M ± 0% 10.2M ± 0% ~ (all equal) Change-Id: I1f40af738254892bd6c8ba2eb43390b175753d52 Reviewed-on: https://go-review.googlesource.com/37445 Reviewed-by: Matthew Dempsky <mdempsky@google.com> Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
2017-02-27 19:56:38 +02:00
fn.Func.SetWrapper(true) // ignore frame for panic+recover matching
call := nod(OCALL, dot, nil)
call.List.Set(paramNnames(tfn.Type))
cmd/compile: bulk rename This change does a bulk rename of several identifiers in the compiler. See #27167 and https://docs.google.com/document/d/19_ExiylD9MRfeAjKIfEsMU1_RGhuxB9sA0b5Zv7byVI/ for context and for discussion of these particular renames. Commands run to generate this change: gorename -from '"cmd/compile/internal/gc".OPROC' -to OGO gorename -from '"cmd/compile/internal/gc".OCOM' -to OBITNOT gorename -from '"cmd/compile/internal/gc".OMINUS' -to ONEG gorename -from '"cmd/compile/internal/gc".OIND' -to ODEREF gorename -from '"cmd/compile/internal/gc".OARRAYBYTESTR' -to OBYTES2STR gorename -from '"cmd/compile/internal/gc".OARRAYBYTESTRTMP' -to OBYTES2STRTMP gorename -from '"cmd/compile/internal/gc".OARRAYRUNESTR' -to ORUNES2STR gorename -from '"cmd/compile/internal/gc".OSTRARRAYBYTE' -to OSTR2BYTES gorename -from '"cmd/compile/internal/gc".OSTRARRAYBYTETMP' -to OSTR2BYTESTMP gorename -from '"cmd/compile/internal/gc".OSTRARRAYRUNE' -to OSTR2RUNES gorename -from '"cmd/compile/internal/gc".Etop' -to ctxStmt gorename -from '"cmd/compile/internal/gc".Erv' -to ctxExpr gorename -from '"cmd/compile/internal/gc".Ecall' -to ctxCallee gorename -from '"cmd/compile/internal/gc".Efnstruct' -to ctxMultiOK gorename -from '"cmd/compile/internal/gc".Easgn' -to ctxAssign gorename -from '"cmd/compile/internal/gc".Ecomplit' -to ctxCompLit Not altered: parameters and local variables (mostly in typecheck.go) named top, which should probably now be called ctx (and which should probably have a named type). Also not altered: Field called Top in gc.Func. gorename -from '"cmd/compile/internal/gc".Node.Isddd' -to IsDDD gorename -from '"cmd/compile/internal/gc".Node.SetIsddd' -to SetIsDDD gorename -from '"cmd/compile/internal/gc".nodeIsddd' -to nodeIsDDD gorename -from '"cmd/compile/internal/types".Field.Isddd' -to IsDDD gorename -from '"cmd/compile/internal/types".Field.SetIsddd' -to SetIsDDD gorename -from '"cmd/compile/internal/types".fieldIsddd' -to fieldIsDDD Not altered: function gc.hasddd, params and local variables called isddd Also not altered: fmt.go prints nodes using "isddd(%v)". cd cmd/compile/internal/gc; go generate I then manually found impacted comments using exact string match and fixed them up by hand. The comment changes were trivial. Passes toolstash-check. Fixes #27167. If this experiment is deemed a success, we will open a new tracking issue for renames to do at the end of the 1.13 cycles. Change-Id: I2dc541533d2ab0d06cb3d31d65df205ecfb151e8 Reviewed-on: https://go-review.googlesource.com/c/150140 Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2018-11-18 08:34:38 -08:00
call.SetIsDDD(tfn.Type.IsVariadic())
if method.Type.NumResults() > 0 {
n := nod(ORETURN, nil, nil)
n.List.Set1(call)
call = n
}
fn.Nbody.Append(call)
}
if false && Debug['r'] != 0 {
dumplist("genwrapper body", fn.Nbody)
}
funcbody()
if debug_dclstack != 0 {
testdclstack()
}
cmd/compile: bulk rename This change does a bulk rename of several identifiers in the compiler. See #27167 and https://docs.google.com/document/d/19_ExiylD9MRfeAjKIfEsMU1_RGhuxB9sA0b5Zv7byVI/ for context and for discussion of these particular renames. Commands run to generate this change: gorename -from '"cmd/compile/internal/gc".OPROC' -to OGO gorename -from '"cmd/compile/internal/gc".OCOM' -to OBITNOT gorename -from '"cmd/compile/internal/gc".OMINUS' -to ONEG gorename -from '"cmd/compile/internal/gc".OIND' -to ODEREF gorename -from '"cmd/compile/internal/gc".OARRAYBYTESTR' -to OBYTES2STR gorename -from '"cmd/compile/internal/gc".OARRAYBYTESTRTMP' -to OBYTES2STRTMP gorename -from '"cmd/compile/internal/gc".OARRAYRUNESTR' -to ORUNES2STR gorename -from '"cmd/compile/internal/gc".OSTRARRAYBYTE' -to OSTR2BYTES gorename -from '"cmd/compile/internal/gc".OSTRARRAYBYTETMP' -to OSTR2BYTESTMP gorename -from '"cmd/compile/internal/gc".OSTRARRAYRUNE' -to OSTR2RUNES gorename -from '"cmd/compile/internal/gc".Etop' -to ctxStmt gorename -from '"cmd/compile/internal/gc".Erv' -to ctxExpr gorename -from '"cmd/compile/internal/gc".Ecall' -to ctxCallee gorename -from '"cmd/compile/internal/gc".Efnstruct' -to ctxMultiOK gorename -from '"cmd/compile/internal/gc".Easgn' -to ctxAssign gorename -from '"cmd/compile/internal/gc".Ecomplit' -to ctxCompLit Not altered: parameters and local variables (mostly in typecheck.go) named top, which should probably now be called ctx (and which should probably have a named type). Also not altered: Field called Top in gc.Func. gorename -from '"cmd/compile/internal/gc".Node.Isddd' -to IsDDD gorename -from '"cmd/compile/internal/gc".Node.SetIsddd' -to SetIsDDD gorename -from '"cmd/compile/internal/gc".nodeIsddd' -to nodeIsDDD gorename -from '"cmd/compile/internal/types".Field.Isddd' -to IsDDD gorename -from '"cmd/compile/internal/types".Field.SetIsddd' -to SetIsDDD gorename -from '"cmd/compile/internal/types".fieldIsddd' -to fieldIsDDD Not altered: function gc.hasddd, params and local variables called isddd Also not altered: fmt.go prints nodes using "isddd(%v)". cd cmd/compile/internal/gc; go generate I then manually found impacted comments using exact string match and fixed them up by hand. The comment changes were trivial. Passes toolstash-check. Fixes #27167. If this experiment is deemed a success, we will open a new tracking issue for renames to do at the end of the 1.13 cycles. Change-Id: I2dc541533d2ab0d06cb3d31d65df205ecfb151e8 Reviewed-on: https://go-review.googlesource.com/c/150140 Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2018-11-18 08:34:38 -08:00
fn = typecheck(fn, ctxStmt)
Curfn = fn
cmd/compile: bulk rename This change does a bulk rename of several identifiers in the compiler. See #27167 and https://docs.google.com/document/d/19_ExiylD9MRfeAjKIfEsMU1_RGhuxB9sA0b5Zv7byVI/ for context and for discussion of these particular renames. Commands run to generate this change: gorename -from '"cmd/compile/internal/gc".OPROC' -to OGO gorename -from '"cmd/compile/internal/gc".OCOM' -to OBITNOT gorename -from '"cmd/compile/internal/gc".OMINUS' -to ONEG gorename -from '"cmd/compile/internal/gc".OIND' -to ODEREF gorename -from '"cmd/compile/internal/gc".OARRAYBYTESTR' -to OBYTES2STR gorename -from '"cmd/compile/internal/gc".OARRAYBYTESTRTMP' -to OBYTES2STRTMP gorename -from '"cmd/compile/internal/gc".OARRAYRUNESTR' -to ORUNES2STR gorename -from '"cmd/compile/internal/gc".OSTRARRAYBYTE' -to OSTR2BYTES gorename -from '"cmd/compile/internal/gc".OSTRARRAYBYTETMP' -to OSTR2BYTESTMP gorename -from '"cmd/compile/internal/gc".OSTRARRAYRUNE' -to OSTR2RUNES gorename -from '"cmd/compile/internal/gc".Etop' -to ctxStmt gorename -from '"cmd/compile/internal/gc".Erv' -to ctxExpr gorename -from '"cmd/compile/internal/gc".Ecall' -to ctxCallee gorename -from '"cmd/compile/internal/gc".Efnstruct' -to ctxMultiOK gorename -from '"cmd/compile/internal/gc".Easgn' -to ctxAssign gorename -from '"cmd/compile/internal/gc".Ecomplit' -to ctxCompLit Not altered: parameters and local variables (mostly in typecheck.go) named top, which should probably now be called ctx (and which should probably have a named type). Also not altered: Field called Top in gc.Func. gorename -from '"cmd/compile/internal/gc".Node.Isddd' -to IsDDD gorename -from '"cmd/compile/internal/gc".Node.SetIsddd' -to SetIsDDD gorename -from '"cmd/compile/internal/gc".nodeIsddd' -to nodeIsDDD gorename -from '"cmd/compile/internal/types".Field.Isddd' -to IsDDD gorename -from '"cmd/compile/internal/types".Field.SetIsddd' -to SetIsDDD gorename -from '"cmd/compile/internal/types".fieldIsddd' -to fieldIsDDD Not altered: function gc.hasddd, params and local variables called isddd Also not altered: fmt.go prints nodes using "isddd(%v)". cd cmd/compile/internal/gc; go generate I then manually found impacted comments using exact string match and fixed them up by hand. The comment changes were trivial. Passes toolstash-check. Fixes #27167. If this experiment is deemed a success, we will open a new tracking issue for renames to do at the end of the 1.13 cycles. Change-Id: I2dc541533d2ab0d06cb3d31d65df205ecfb151e8 Reviewed-on: https://go-review.googlesource.com/c/150140 Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2018-11-18 08:34:38 -08:00
typecheckslice(fn.Nbody.Slice(), ctxStmt)
cmd/compile/internal/gc: inline autogenerated (*T).M wrappers Currently all inlining of autogenerated wrappers is disabled, because it causes build failures, when indexed export format is enabled. Turns out we can reenable it for common case of (*T).M wrappers. This fixes most performance degradation of 1.11 vs 1.10. encoding/binary: name old time/op new time/op delta ReadSlice1000Int32s-6 14.8µs ± 2% 11.5µs ± 2% -22.01% (p=0.000 n=10+10) WriteSlice1000Int32s-6 14.8µs ± 2% 11.7µs ± 2% -20.95% (p=0.000 n=10+10) bufio: name old time/op new time/op delta WriterFlush-6 32.4ns ± 1% 28.8ns ± 0% -11.17% (p=0.000 n=9+10) sort: SearchWrappers-6 231ns ± 1% 231ns ± 0% ~ (p=0.129 n=9+10) SortString1K-6 365µs ± 1% 298µs ± 1% -18.43% (p=0.000 n=9+10) SortString1K_Slice-6 274µs ± 2% 276µs ± 1% ~ (p=0.105 n=10+10) StableString1K-6 490µs ± 1% 373µs ± 1% -23.73% (p=0.000 n=10+10) SortInt1K-6 210µs ± 1% 142µs ± 1% -32.69% (p=0.000 n=10+10) StableInt1K-6 243µs ± 0% 151µs ± 1% -37.75% (p=0.000 n=10+10) StableInt1K_Slice-6 130µs ± 1% 130µs ± 0% ~ (p=0.237 n=10+8) SortInt64K-6 19.9ms ± 1% 13.5ms ± 1% -32.32% (p=0.000 n=10+10) SortInt64K_Slice-6 11.5ms ± 1% 11.5ms ± 1% ~ (p=0.912 n=10+10) StableInt64K-6 21.5ms ± 0% 13.5ms ± 1% -37.30% (p=0.000 n=9+10) Sort1e2-6 108µs ± 2% 83µs ± 3% -23.26% (p=0.000 n=10+10) Stable1e2-6 218µs ± 0% 161µs ± 1% -25.99% (p=0.000 n=8+9) Sort1e4-6 22.6ms ± 1% 16.8ms ± 0% -25.45% (p=0.000 n=10+7) Stable1e4-6 67.6ms ± 1% 49.7ms ± 0% -26.48% (p=0.000 n=10+10) Sort1e6-6 3.44s ± 0% 2.55s ± 1% -26.05% (p=0.000 n=8+9) Stable1e6-6 13.7s ± 0% 9.9s ± 1% -27.68% (p=0.000 n=8+10) Fixes #27621 Updates #25338 Change-Id: I6fe633202f63fa829a6ab849c44d7e45f8835dff Reviewed-on: https://go-review.googlesource.com/c/135697 Run-TryBot: Ilya Tocar <ilya.tocar@intel.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2018-09-17 14:08:03 -05:00
// Inline calls within (*T).M wrappers. This is safe because we only
// generate those wrappers within the same compilation unit as (T).M.
// TODO(mdempsky): Investigate why we can't enable this more generally.
if rcvr.IsPtr() && rcvr.Elem() == method.Type.Recv().Type && rcvr.Elem().Sym != nil {
cmd/compile: add indexed export format This CL introduces a new indexed data format for package export data. This improves on the previous (sequential) binary format by allowing the compiler to selectively (and lazily) load only the data that's actually needed for compilation. In large Go projects, the package export data can become very large due to transitive type declaration dependencies and inline function/method bodies. By lazily loading these declarations and bodies as needed, we avoid wasting time and memory processing unnecessary and/or redundant data. In the benchmarks below, "old" is -iexport=false and "new" is -iexport=true. The suffixes indicate the compiler concurrency (-c) and inlining (-l) settings used for the build (using -gcflags=all=-foo). Benchmarks were run on an HP Z620. Juju is "go build -a github.com/juju/juju/cmd/...": name old real-time/op new real-time/op delta Juju/c=1/l=0 44.0s ± 1% 38.7s ± 9% -11.97% (p=0.001 n=7+7) Juju/c=1/l=4 53.7s ± 3% 45.3s ± 4% -15.53% (p=0.001 n=7+7) Juju/c=4/l=0 39.7s ± 8% 32.0s ± 4% -19.38% (p=0.001 n=7+7) Juju/c=4/l=4 46.3s ± 4% 38.0s ± 4% -18.06% (p=0.001 n=7+7) name old user-time/op new user-time/op delta Juju/c=1/l=0 371s ± 1% 300s ± 0% -19.07% (p=0.001 n=7+6) Juju/c=1/l=4 482s ± 0% 374s ± 1% -22.37% (p=0.001 n=7+7) Juju/c=4/l=0 410s ± 1% 340s ± 1% -17.19% (p=0.001 n=7+7) Juju/c=4/l=4 532s ± 1% 424s ± 1% -20.26% (p=0.001 n=7+7) name old sys-time/op new sys-time/op delta Juju/c=1/l=0 33.4s ± 1% 28.4s ± 2% -15.02% (p=0.001 n=7+7) Juju/c=1/l=4 40.7s ± 2% 32.8s ± 3% -19.51% (p=0.001 n=7+7) Juju/c=4/l=0 39.8s ± 2% 34.4s ± 2% -13.74% (p=0.001 n=7+7) Juju/c=4/l=4 48.4s ± 2% 40.4s ± 2% -16.50% (p=0.001 n=7+7) Kubelet is "go build -a k8s.io/kubernetes/cmd/kubelet": name old real-time/op new real-time/op delta Kubelet/c=1/l=0 42.0s ± 1% 34.8s ± 1% -17.27% (p=0.008 n=5+5) Kubelet/c=1/l=4 55.4s ± 3% 45.4s ± 3% -18.06% (p=0.002 n=6+6) Kubelet/c=4/l=0 37.4s ± 3% 29.9s ± 1% -20.25% (p=0.004 n=6+5) Kubelet/c=4/l=4 48.1s ± 2% 39.0s ± 5% -18.93% (p=0.002 n=6+6) name old user-time/op new user-time/op delta Kubelet/c=1/l=0 291s ± 1% 233s ± 1% -19.96% (p=0.002 n=6+6) Kubelet/c=1/l=4 385s ± 1% 298s ± 1% -22.51% (p=0.002 n=6+6) Kubelet/c=4/l=0 325s ± 0% 268s ± 1% -17.48% (p=0.004 n=5+6) Kubelet/c=4/l=4 429s ± 1% 343s ± 1% -20.08% (p=0.002 n=6+6) name old sys-time/op new sys-time/op delta Kubelet/c=1/l=0 25.1s ± 2% 20.9s ± 4% -16.69% (p=0.002 n=6+6) Kubelet/c=1/l=4 31.2s ± 3% 24.4s ± 0% -21.67% (p=0.010 n=6+4) Kubelet/c=4/l=0 30.2s ± 2% 25.6s ± 1% -15.34% (p=0.002 n=6+6) Kubelet/c=4/l=4 37.3s ± 1% 30.9s ± 2% -17.11% (p=0.002 n=6+6) Change-Id: Ie43eb3bbe1392cbb61c86792a17a57b33b9561f0 Reviewed-on: https://go-review.googlesource.com/106796 Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org>
2018-04-01 01:55:55 -07:00
inlcalls(fn)
}
escapeFuncs([]*Node{fn}, false)
Curfn = nil
funccompile(fn)
}
func paramNnames(ft *types.Type) []*Node {
args := make([]*Node, ft.NumParams())
for i, f := range ft.Params().FieldSlice() {
args[i] = asNode(f.Nname)
}
return args
}
func hashmem(t *types.Type) *Node {
sym := Runtimepkg.Lookup("memhash")
n := newname(sym)
cmd/compile: move Node.Class to flags Put it at position zero, since it is fairly hot. This shrinks gc.Node into a smaller size class on 64 bit systems. name old time/op new time/op delta Template 193ms ± 5% 192ms ± 3% ~ (p=0.353 n=94+93) Unicode 86.1ms ± 5% 85.0ms ± 4% -1.23% (p=0.000 n=95+98) GoTypes 546ms ± 3% 544ms ± 4% -0.40% (p=0.007 n=94+97) Compiler 2.56s ± 3% 2.54s ± 3% -0.67% (p=0.000 n=99+97) SSA 5.13s ± 2% 5.10s ± 3% -0.55% (p=0.000 n=94+98) Flate 122ms ± 6% 121ms ± 4% -0.75% (p=0.002 n=97+95) GoParser 144ms ± 5% 144ms ± 4% ~ (p=0.298 n=98+97) Reflect 348ms ± 4% 349ms ± 4% ~ (p=0.350 n=98+97) Tar 105ms ± 5% 104ms ± 5% ~ (p=0.154 n=96+98) XML 200ms ± 5% 198ms ± 4% -0.71% (p=0.015 n=97+98) [Geo mean] 330ms 328ms -0.52% name old user-time/op new user-time/op delta Template 229ms ±11% 224ms ± 7% -2.16% (p=0.001 n=100+87) Unicode 109ms ± 5% 109ms ± 6% ~ (p=0.897 n=96+91) GoTypes 712ms ± 4% 709ms ± 4% ~ (p=0.085 n=96+98) Compiler 3.41s ± 3% 3.36s ± 3% -1.43% (p=0.000 n=98+98) SSA 7.46s ± 3% 7.31s ± 3% -2.02% (p=0.000 n=100+99) Flate 145ms ± 6% 143ms ± 6% -1.11% (p=0.001 n=99+97) GoParser 177ms ± 5% 176ms ± 5% -0.78% (p=0.018 n=95+95) Reflect 432ms ± 7% 435ms ± 9% ~ (p=0.296 n=100+100) Tar 121ms ± 7% 121ms ± 5% ~ (p=0.072 n=100+95) XML 241ms ± 4% 239ms ± 5% ~ (p=0.085 n=97+99) [Geo mean] 413ms 410ms -0.73% name old alloc/op new alloc/op delta Template 38.4MB ± 0% 37.7MB ± 0% -1.85% (p=0.008 n=5+5) Unicode 30.1MB ± 0% 28.8MB ± 0% -4.09% (p=0.008 n=5+5) GoTypes 112MB ± 0% 110MB ± 0% -1.69% (p=0.008 n=5+5) Compiler 470MB ± 0% 461MB ± 0% -1.91% (p=0.008 n=5+5) SSA 1.13GB ± 0% 1.11GB ± 0% -1.70% (p=0.008 n=5+5) Flate 25.0MB ± 0% 24.6MB ± 0% -1.67% (p=0.008 n=5+5) GoParser 31.6MB ± 0% 31.1MB ± 0% -1.66% (p=0.008 n=5+5) Reflect 77.1MB ± 0% 75.8MB ± 0% -1.69% (p=0.008 n=5+5) Tar 26.3MB ± 0% 25.7MB ± 0% -2.06% (p=0.008 n=5+5) XML 41.9MB ± 0% 41.1MB ± 0% -1.93% (p=0.008 n=5+5) [Geo mean] 73.5MB 72.0MB -2.03% name old allocs/op new allocs/op delta Template 383k ± 0% 383k ± 0% ~ (p=0.690 n=5+5) Unicode 343k ± 0% 343k ± 0% ~ (p=0.841 n=5+5) GoTypes 1.16M ± 0% 1.16M ± 0% ~ (p=0.310 n=5+5) Compiler 4.43M ± 0% 4.42M ± 0% -0.17% (p=0.008 n=5+5) SSA 9.85M ± 0% 9.85M ± 0% ~ (p=0.310 n=5+5) Flate 236k ± 0% 236k ± 1% ~ (p=0.841 n=5+5) GoParser 320k ± 0% 320k ± 0% ~ (p=0.421 n=5+5) Reflect 988k ± 0% 987k ± 0% ~ (p=0.690 n=5+5) Tar 252k ± 0% 251k ± 0% ~ (p=0.095 n=5+5) XML 399k ± 0% 399k ± 0% ~ (p=1.000 n=5+5) [Geo mean] 741k 740k -0.07% Change-Id: I9e952b58a98e30a12494304db9ce50d0a85e459c Reviewed-on: https://go-review.googlesource.com/41797 Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Reviewed-by: Marvin Stenger <marvin.stenger94@gmail.com>
2017-04-25 18:14:12 -07:00
n.SetClass(PFUNC)
n.Sym.SetFunc(true)
n.Type = functype(nil, []*Node{
anonfield(types.NewPtr(t)),
anonfield(types.Types[TUINTPTR]),
anonfield(types.Types[TUINTPTR]),
}, []*Node{
anonfield(types.Types[TUINTPTR]),
})
return n
}
func ifacelookdot(s *types.Sym, t *types.Type, ignorecase bool) (m *types.Field, followptr bool) {
if t == nil {
return nil, false
}
path, ambig := dotpath(s, t, &m, ignorecase)
if path == nil {
if ambig {
yyerror("%v.%v is ambiguous", t, s)
}
return nil, false
}
for _, d := range path {
if d.field.Type.IsPtr() {
followptr = true
break
}
}
if !m.IsMethod() {
yyerror("%v.%v is a field, not a method", t, s)
return nil, followptr
}
return m, followptr
}
func implements(t, iface *types.Type, m, samename **types.Field, ptr *int) bool {
t0 := t
if t == nil {
return false
}
if t.IsInterface() {
i := 0
tms := t.Fields().Slice()
for _, im := range iface.Fields().Slice() {
for i < len(tms) && tms[i].Sym != im.Sym {
i++
}
if i == len(tms) {
*m = im
*samename = nil
*ptr = 0
return false
}
tm := tms[i]
if !types.Identical(tm.Type, im.Type) {
*m = im
*samename = tm
*ptr = 0
return false
}
}
return true
}
t = methtype(t)
var tms []*types.Field
if t != nil {
expandmeth(t)
tms = t.AllMethods().Slice()
}
i := 0
for _, im := range iface.Fields().Slice() {
cmd/compile: pack bool fields in Node, Name, Func and Type structs to bitsets This reduces compiler memory usage by up to 4% - see compilebench results below. name old time/op new time/op delta Template 245ms ± 4% 241ms ± 2% -1.88% (p=0.029 n=10+10) Unicode 126ms ± 3% 124ms ± 3% ~ (p=0.105 n=10+10) GoTypes 805ms ± 2% 813ms ± 3% ~ (p=0.515 n=8+10) Compiler 3.95s ± 2% 3.83s ± 1% -2.96% (p=0.000 n=9+10) MakeBash 47.4s ± 4% 46.6s ± 1% -1.59% (p=0.028 n=9+10) name old user-ns/op new user-ns/op delta Template 324M ± 5% 326M ± 3% ~ (p=0.935 n=10+10) Unicode 186M ± 5% 178M ±10% ~ (p=0.067 n=9+10) GoTypes 1.08G ± 7% 1.09G ± 4% ~ (p=0.956 n=10+10) Compiler 5.34G ± 4% 5.31G ± 1% ~ (p=0.501 n=10+8) name old alloc/op new alloc/op delta Template 41.0MB ± 0% 39.8MB ± 0% -3.03% (p=0.000 n=10+10) Unicode 32.3MB ± 0% 31.0MB ± 0% -4.13% (p=0.000 n=10+10) GoTypes 119MB ± 0% 116MB ± 0% -2.39% (p=0.000 n=10+10) Compiler 499MB ± 0% 487MB ± 0% -2.48% (p=0.000 n=10+10) name old allocs/op new allocs/op delta Template 380k ± 1% 379k ± 1% ~ (p=0.436 n=10+10) Unicode 324k ± 1% 324k ± 0% ~ (p=0.853 n=10+10) GoTypes 1.15M ± 0% 1.15M ± 0% ~ (p=0.481 n=10+10) Compiler 4.41M ± 0% 4.41M ± 0% -0.12% (p=0.007 n=10+10) name old text-bytes new text-bytes delta HelloSize 623k ± 0% 623k ± 0% ~ (all equal) CmdGoSize 6.64M ± 0% 6.64M ± 0% ~ (all equal) name old data-bytes new data-bytes delta HelloSize 5.81k ± 0% 5.81k ± 0% ~ (all equal) CmdGoSize 238k ± 0% 238k ± 0% ~ (all equal) name old bss-bytes new bss-bytes delta HelloSize 134k ± 0% 134k ± 0% ~ (all equal) CmdGoSize 152k ± 0% 152k ± 0% ~ (all equal) name old exe-bytes new exe-bytes delta HelloSize 967k ± 0% 967k ± 0% ~ (all equal) CmdGoSize 10.2M ± 0% 10.2M ± 0% ~ (all equal) Change-Id: I1f40af738254892bd6c8ba2eb43390b175753d52 Reviewed-on: https://go-review.googlesource.com/37445 Reviewed-by: Matthew Dempsky <mdempsky@google.com> Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
2017-02-27 19:56:38 +02:00
if im.Broke() {
continue
}
for i < len(tms) && tms[i].Sym != im.Sym {
i++
}
if i == len(tms) {
*m = im
*samename, _ = ifacelookdot(im.Sym, t, true)
*ptr = 0
return false
}
tm := tms[i]
if tm.Nointerface() || !types.Identical(tm.Type, im.Type) {
*m = im
*samename = tm
*ptr = 0
return false
}
followptr := tm.Embedded == 2
// if pointer receiver in method,
// the method does not exist for value types.
rcvr := tm.Type.Recv().Type
if rcvr.IsPtr() && !t0.IsPtr() && !followptr && !isifacemethod(tm.Type) {
if false && Debug['r'] != 0 {
yyerror("interface pointer mismatch")
}
*m = im
*samename = nil
*ptr = 1
return false
}
}
// We're going to emit an OCONVIFACE.
// Call itabname so that (t, iface)
// gets added to itabs early, which allows
// us to de-virtualize calls through this
// type/interface pair later. See peekitabs in reflect.go
if isdirectiface(t0) && !iface.IsEmptyInterface() {
itabname(t0, iface)
}
return true
}
2016-12-15 17:17:01 -08:00
func listtreecopy(l []*Node, pos src.XPos) []*Node {
var out []*Node
for _, n := range l {
[dev.inline] cmd/internal/src: replace src.Pos with syntax.Pos This replaces the src.Pos LineHist-based position tracking with the syntax.Pos implementation and updates all uses. The LineHist table is not used anymore - the respective code is still there but should be removed eventually. CL forthcoming. Passes toolstash -cmp when comparing to the master repo (with the exception of a couple of swapped assembly instructions, likely due to different instruction scheduling because the line-based sorting has changed; though this is won't affect correctness). The sizes of various important compiler data structures have increased significantly (see the various sizes_test.go files); this is probably the reason for an increase of compilation times (to be addressed). Here are the results of compilebench -count 5, run on a "quiet" machine (no apps running besides a terminal): name old time/op new time/op delta Template 256ms ± 1% 280ms ±15% +9.54% (p=0.008 n=5+5) Unicode 132ms ± 1% 132ms ± 1% ~ (p=0.690 n=5+5) GoTypes 891ms ± 1% 917ms ± 2% +2.88% (p=0.008 n=5+5) Compiler 3.84s ± 2% 3.99s ± 2% +3.95% (p=0.016 n=5+5) MakeBash 47.1s ± 1% 47.2s ± 2% ~ (p=0.841 n=5+5) name old user-ns/op new user-ns/op delta Template 309M ± 1% 326M ± 2% +5.18% (p=0.008 n=5+5) Unicode 165M ± 1% 168M ± 4% ~ (p=0.421 n=5+5) GoTypes 1.14G ± 2% 1.18G ± 1% +3.47% (p=0.008 n=5+5) Compiler 5.00G ± 1% 5.16G ± 1% +3.12% (p=0.008 n=5+5) Change-Id: I241c4246cdff627d7ecb95cac23060b38f9775ec Reviewed-on: https://go-review.googlesource.com/34273 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2016-12-09 17:15:05 -08:00
out = append(out, treecopy(n, pos))
}
return out
}
func liststmt(l []*Node) *Node {
n := nod(OBLOCK, nil, nil)
n.List.Set(l)
if len(l) != 0 {
n.Pos = l[0].Pos
}
return n
}
func (l Nodes) asblock() *Node {
n := nod(OBLOCK, nil, nil)
n.List = l
if l.Len() != 0 {
n.Pos = l.First().Pos
}
return n
}
func ngotype(n *Node) *types.Sym {
if n.Type != nil {
return typenamesym(n.Type)
}
return nil
}
cmd/compile: reduce use of **Node parameters Escape analysis has a hard time with tree-like structures (see #13493 and #14858). This is unlikely to change. As a result, when invoking a function that accepts a **Node parameter, we usually allocate a *Node on the heap. This happens a whole lot. This CL changes functions from taking a **Node to acting more like append: It both modifies the input and returns a replacement for it. Because of the cascading nature of escape analysis, in order to get the benefits, I had to modify almost all such functions. The remaining functions are in racewalk and the backend. I would be happy to update them as well in a separate CL. This CL was created by manually updating the function signatures and the directly impacted bits of code. The callsites were then automatically updated using a bespoke script: https://gist.github.com/josharian/046b1be7aceae244de39 For ease of reviewing and future understanding, this CL is also broken down into four CLs, mailed separately, which show the manual and the automated changes separately. They are CLs 20990, 20991, 20992, and 20993. Passes toolstash -cmp. name old time/op new time/op delta Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24) Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24) GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24) Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24) MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23) name old alloc/op new alloc/op delta Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23) Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25) GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25) Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25) name old allocs/op new allocs/op delta Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25) Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24) GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25) Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25) name old text-bytes new text-bytes delta HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal) CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal) name old data-bytes new data-bytes delta HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal) CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal) name old exe-bytes new exe-bytes delta HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal) CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal) Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475 Reviewed-on: https://go-review.googlesource.com/20959 Reviewed-by: Dave Cheney <dave@cheney.net> Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
// The result of addinit MUST be assigned back to n, e.g.
// n.Left = addinit(n.Left, init)
func addinit(n *Node, init []*Node) *Node {
if len(init) == 0 {
cmd/compile: reduce use of **Node parameters Escape analysis has a hard time with tree-like structures (see #13493 and #14858). This is unlikely to change. As a result, when invoking a function that accepts a **Node parameter, we usually allocate a *Node on the heap. This happens a whole lot. This CL changes functions from taking a **Node to acting more like append: It both modifies the input and returns a replacement for it. Because of the cascading nature of escape analysis, in order to get the benefits, I had to modify almost all such functions. The remaining functions are in racewalk and the backend. I would be happy to update them as well in a separate CL. This CL was created by manually updating the function signatures and the directly impacted bits of code. The callsites were then automatically updated using a bespoke script: https://gist.github.com/josharian/046b1be7aceae244de39 For ease of reviewing and future understanding, this CL is also broken down into four CLs, mailed separately, which show the manual and the automated changes separately. They are CLs 20990, 20991, 20992, and 20993. Passes toolstash -cmp. name old time/op new time/op delta Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24) Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24) GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24) Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24) MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23) name old alloc/op new alloc/op delta Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23) Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25) GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25) Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25) name old allocs/op new allocs/op delta Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25) Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24) GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25) Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25) name old text-bytes new text-bytes delta HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal) CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal) name old data-bytes new data-bytes delta HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal) CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal) name old exe-bytes new exe-bytes delta HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal) CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal) Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475 Reviewed-on: https://go-review.googlesource.com/20959 Reviewed-by: Dave Cheney <dave@cheney.net> Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
return n
}
if n.mayBeShared() {
// Introduce OCONVNOP to hold init list.
n = nod(OCONVNOP, n, nil)
n.Type = n.Left.Type
n.SetTypecheck(1)
}
n.Ninit.Prepend(init...)
n.SetHasCall(true)
cmd/compile: reduce use of **Node parameters Escape analysis has a hard time with tree-like structures (see #13493 and #14858). This is unlikely to change. As a result, when invoking a function that accepts a **Node parameter, we usually allocate a *Node on the heap. This happens a whole lot. This CL changes functions from taking a **Node to acting more like append: It both modifies the input and returns a replacement for it. Because of the cascading nature of escape analysis, in order to get the benefits, I had to modify almost all such functions. The remaining functions are in racewalk and the backend. I would be happy to update them as well in a separate CL. This CL was created by manually updating the function signatures and the directly impacted bits of code. The callsites were then automatically updated using a bespoke script: https://gist.github.com/josharian/046b1be7aceae244de39 For ease of reviewing and future understanding, this CL is also broken down into four CLs, mailed separately, which show the manual and the automated changes separately. They are CLs 20990, 20991, 20992, and 20993. Passes toolstash -cmp. name old time/op new time/op delta Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24) Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24) GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24) Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24) MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23) name old alloc/op new alloc/op delta Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23) Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25) GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25) Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25) name old allocs/op new allocs/op delta Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25) Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24) GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25) Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25) name old text-bytes new text-bytes delta HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal) CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal) name old data-bytes new data-bytes delta HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal) CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal) name old exe-bytes new exe-bytes delta HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal) CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal) Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475 Reviewed-on: https://go-review.googlesource.com/20959 Reviewed-by: Dave Cheney <dave@cheney.net> Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
return n
}
// The linker uses the magic symbol prefixes "go." and "type."
// Avoid potential confusion between import paths and symbols
// by rejecting these reserved imports for now. Also, people
// "can do weird things in GOPATH and we'd prefer they didn't
// do _that_ weird thing" (per rsc). See also #4257.
var reservedimports = []string{
"go",
"type",
}
func isbadimport(path string, allowSpace bool) bool {
if strings.Contains(path, "\x00") {
yyerror("import path contains NUL")
return true
}
for _, ri := range reservedimports {
if path == ri {
yyerror("import path %q is reserved and cannot be used", path)
return true
}
}
for _, r := range path {
if r == utf8.RuneError {
yyerror("import path contains invalid UTF-8 sequence: %q", path)
return true
}
if r < 0x20 || r == 0x7f {
yyerror("import path contains control character: %q", path)
return true
}
if r == '\\' {
yyerror("import path contains backslash; use slash: %q", path)
return true
}
if !allowSpace && unicode.IsSpace(r) {
yyerror("import path contains space character: %q", path)
return true
}
if strings.ContainsRune("!\"#$%&'()*,:;<=>?[]^`{|}", r) {
yyerror("import path contains invalid character '%c': %q", r, path)
return true
}
}
return false
}
// Can this type be stored directly in an interface word?
// Yes, if the representation is a single pointer.
func isdirectiface(t *types.Type) bool {
if t.Broke() {
return false
}
switch t.Etype {
case TPTR,
TCHAN,
TMAP,
TFUNC,
TUNSAFEPTR:
return true
case TARRAY:
// Array of 1 direct iface type can be direct.
return t.NumElem() == 1 && isdirectiface(t.Elem())
case TSTRUCT:
// Struct with 1 field of direct iface type can be direct.
return t.NumFields() == 1 && isdirectiface(t.Field(0).Type)
}
return false
}
// itabType loads the _type field from a runtime.itab struct.
func itabType(itab *Node) *Node {
typ := nodSym(ODOTPTR, itab, nil)
typ.Type = types.NewPtr(types.Types[TUINT8])
typ.SetTypecheck(1)
typ.Xoffset = int64(Widthptr) // offset of _type in runtime.itab
cmd/compile: pack bool fields in Node, Name, Func and Type structs to bitsets This reduces compiler memory usage by up to 4% - see compilebench results below. name old time/op new time/op delta Template 245ms ± 4% 241ms ± 2% -1.88% (p=0.029 n=10+10) Unicode 126ms ± 3% 124ms ± 3% ~ (p=0.105 n=10+10) GoTypes 805ms ± 2% 813ms ± 3% ~ (p=0.515 n=8+10) Compiler 3.95s ± 2% 3.83s ± 1% -2.96% (p=0.000 n=9+10) MakeBash 47.4s ± 4% 46.6s ± 1% -1.59% (p=0.028 n=9+10) name old user-ns/op new user-ns/op delta Template 324M ± 5% 326M ± 3% ~ (p=0.935 n=10+10) Unicode 186M ± 5% 178M ±10% ~ (p=0.067 n=9+10) GoTypes 1.08G ± 7% 1.09G ± 4% ~ (p=0.956 n=10+10) Compiler 5.34G ± 4% 5.31G ± 1% ~ (p=0.501 n=10+8) name old alloc/op new alloc/op delta Template 41.0MB ± 0% 39.8MB ± 0% -3.03% (p=0.000 n=10+10) Unicode 32.3MB ± 0% 31.0MB ± 0% -4.13% (p=0.000 n=10+10) GoTypes 119MB ± 0% 116MB ± 0% -2.39% (p=0.000 n=10+10) Compiler 499MB ± 0% 487MB ± 0% -2.48% (p=0.000 n=10+10) name old allocs/op new allocs/op delta Template 380k ± 1% 379k ± 1% ~ (p=0.436 n=10+10) Unicode 324k ± 1% 324k ± 0% ~ (p=0.853 n=10+10) GoTypes 1.15M ± 0% 1.15M ± 0% ~ (p=0.481 n=10+10) Compiler 4.41M ± 0% 4.41M ± 0% -0.12% (p=0.007 n=10+10) name old text-bytes new text-bytes delta HelloSize 623k ± 0% 623k ± 0% ~ (all equal) CmdGoSize 6.64M ± 0% 6.64M ± 0% ~ (all equal) name old data-bytes new data-bytes delta HelloSize 5.81k ± 0% 5.81k ± 0% ~ (all equal) CmdGoSize 238k ± 0% 238k ± 0% ~ (all equal) name old bss-bytes new bss-bytes delta HelloSize 134k ± 0% 134k ± 0% ~ (all equal) CmdGoSize 152k ± 0% 152k ± 0% ~ (all equal) name old exe-bytes new exe-bytes delta HelloSize 967k ± 0% 967k ± 0% ~ (all equal) CmdGoSize 10.2M ± 0% 10.2M ± 0% ~ (all equal) Change-Id: I1f40af738254892bd6c8ba2eb43390b175753d52 Reviewed-on: https://go-review.googlesource.com/37445 Reviewed-by: Matthew Dempsky <mdempsky@google.com> Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
2017-02-27 19:56:38 +02:00
typ.SetBounded(true) // guaranteed not to fault
return typ
}
// ifaceData loads the data field from an interface.
// The concrete type must be known to have type t.
// It follows the pointer if !isdirectiface(t).
func ifaceData(pos src.XPos, n *Node, t *types.Type) *Node {
cmd/compile: improve generated code for concrete cases in type switches Consider switch x:= x.(type) { case int: // int stmts case error: // error stmts } Prior to this change, we lowered this roughly as: if x, ok := x.(int); ok { // int stmts } else if x, ok := x.(error); ok { // error stmts } x, ok := x.(error) is implemented with a call to runtime.assertE2I2 or runtime.assertI2I2. x, ok := x.(int) generates inline code that checks whether x has type int, and populates x and ok as appropriate. We then immediately branch again on ok. The shortcircuit pass in the SSA backend is designed to recognize situations like this, in which we are immediately branching on a bool value that we just calculated with a branch. However, the shortcircuit pass has limitations when the intermediate state has phis. In this case, the phi value is x (the int). CL 222923 improved the situation, but many cases are still unhandled. I have further improvements in progress, which is how I found this particular problem, but they are expensive, and may or may not see the light of day. In the common case of a lone concrete type in a type switch case, it is easier and cheaper to simply lower a different way, roughly: if _, ok := x.(int); ok { x := x.(int) // int stmts } Instead of using a type assertion, though, we extract the value of x from the interface directly. This removes the need to track x (the int) across the branch on ok, which removes the phi, which lets the shortcircuit pass do its job. Benchmarks for encoding/binary show improvements, as well as some wild swings on the super fast benchmarks (alignment effects?): name old time/op new time/op delta ReadSlice1000Int32s-8 5.25µs ± 2% 4.87µs ± 3% -7.11% (p=0.000 n=44+49) ReadStruct-8 451ns ± 2% 417ns ± 2% -7.39% (p=0.000 n=45+46) WriteStruct-8 412ns ± 2% 405ns ± 3% -1.58% (p=0.000 n=46+48) ReadInts-8 296ns ± 8% 275ns ± 3% -7.23% (p=0.000 n=48+50) WriteInts-8 324ns ± 1% 318ns ± 2% -1.67% (p=0.000 n=44+49) WriteSlice1000Int32s-8 5.21µs ± 2% 4.92µs ± 1% -5.67% (p=0.000 n=46+44) PutUint16-8 0.58ns ± 2% 0.59ns ± 2% +0.63% (p=0.000 n=49+49) PutUint32-8 0.87ns ± 1% 0.58ns ± 1% -33.10% (p=0.000 n=46+44) PutUint64-8 0.66ns ± 2% 0.87ns ± 2% +33.07% (p=0.000 n=47+48) LittleEndianPutUint16-8 0.86ns ± 2% 0.87ns ± 2% +0.55% (p=0.003 n=47+50) LittleEndianPutUint32-8 0.87ns ± 1% 0.87ns ± 1% ~ (p=0.547 n=45+47) LittleEndianPutUint64-8 0.87ns ± 2% 0.87ns ± 1% ~ (p=0.451 n=46+47) ReadFloats-8 79.8ns ± 5% 75.9ns ± 2% -4.83% (p=0.000 n=50+47) WriteFloats-8 89.3ns ± 1% 88.9ns ± 1% -0.48% (p=0.000 n=46+44) ReadSlice1000Float32s-8 5.51µs ± 1% 4.87µs ± 2% -11.74% (p=0.000 n=47+46) WriteSlice1000Float32s-8 5.51µs ± 1% 4.93µs ± 1% -10.60% (p=0.000 n=48+47) PutUvarint32-8 25.9ns ± 2% 24.0ns ± 2% -7.02% (p=0.000 n=48+50) PutUvarint64-8 75.1ns ± 1% 61.5ns ± 2% -18.12% (p=0.000 n=45+47) [Geo mean] 57.3ns 54.3ns -5.33% Despite the rarity of type switches, this generates noticeably smaller binaries. file before after Δ % addr2line 4413296 4409200 -4096 -0.093% api 5982648 5962168 -20480 -0.342% cgo 4854168 4833688 -20480 -0.422% compile 19694784 19682560 -12224 -0.062% cover 5278008 5265720 -12288 -0.233% doc 4694824 4682536 -12288 -0.262% fix 3411336 3394952 -16384 -0.480% link 6721496 6717400 -4096 -0.061% nm 4371152 4358864 -12288 -0.281% objdump 4760960 4752768 -8192 -0.172% pprof 14810820 14790340 -20480 -0.138% trace 11681076 11668788 -12288 -0.105% vet 8285464 8244504 -40960 -0.494% total 115824120 115627576 -196544 -0.170% Compiler performance is marginally improved (note that go/types has many type switches): name old alloc/op new alloc/op delta Template 35.0MB ± 0% 35.0MB ± 0% +0.09% (p=0.008 n=5+5) Unicode 28.5MB ± 0% 28.5MB ± 0% ~ (p=0.548 n=5+5) GoTypes 114MB ± 0% 114MB ± 0% -0.76% (p=0.008 n=5+5) Compiler 541MB ± 0% 541MB ± 0% -0.03% (p=0.008 n=5+5) SSA 1.17GB ± 0% 1.17GB ± 0% ~ (p=0.841 n=5+5) Flate 21.9MB ± 0% 21.9MB ± 0% ~ (p=0.421 n=5+5) GoParser 26.9MB ± 0% 26.9MB ± 0% ~ (p=0.222 n=5+5) Reflect 74.6MB ± 0% 74.6MB ± 0% ~ (p=1.000 n=5+5) Tar 32.9MB ± 0% 32.8MB ± 0% ~ (p=0.056 n=5+5) XML 42.4MB ± 0% 42.1MB ± 0% -0.77% (p=0.008 n=5+5) [Geo mean] 73.2MB 73.1MB -0.15% name old allocs/op new allocs/op delta Template 377k ± 0% 377k ± 0% +0.06% (p=0.008 n=5+5) Unicode 354k ± 0% 354k ± 0% ~ (p=0.095 n=5+5) GoTypes 1.31M ± 0% 1.30M ± 0% -0.73% (p=0.008 n=5+5) Compiler 5.44M ± 0% 5.44M ± 0% -0.04% (p=0.008 n=5+5) SSA 11.7M ± 0% 11.7M ± 0% ~ (p=1.000 n=5+5) Flate 239k ± 0% 239k ± 0% ~ (p=1.000 n=5+5) GoParser 302k ± 0% 302k ± 0% -0.04% (p=0.008 n=5+5) Reflect 977k ± 0% 977k ± 0% ~ (p=0.690 n=5+5) Tar 346k ± 0% 346k ± 0% ~ (p=0.889 n=5+5) XML 431k ± 0% 430k ± 0% -0.25% (p=0.008 n=5+5) [Geo mean] 806k 806k -0.10% For packages with many type switches, this considerably shrinks function text size. Some examples: file before after Δ % encoding/binary.s 30726 29504 -1222 -3.977% go/printer.s 77597 76005 -1592 -2.052% cmd/vendor/golang.org/x/tools/go/ast/astutil.s 65704 63318 -2386 -3.631% cmd/vendor/golang.org/x/tools/go/analysis/passes/unreachable.s 8047 7714 -333 -4.138% Text size regressions are rare. Change-Id: Ic10982bbb04876250eaa5bfee97990141ae5fc28 Reviewed-on: https://go-review.googlesource.com/c/go/+/228106 Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com> Reviewed-by: Keith Randall <khr@golang.org>
2020-04-12 17:34:33 -07:00
if t.IsInterface() {
Fatalf("ifaceData interface: %v", t)
}
ptr := nodlSym(pos, OIDATA, n, nil)
if isdirectiface(t) {
ptr.Type = t
ptr.SetTypecheck(1)
return ptr
}
ptr.Type = types.NewPtr(t)
ptr.SetTypecheck(1)
ind := nodl(pos, ODEREF, ptr, nil)
ind.Type = t
ind.SetTypecheck(1)
ind.SetBounded(true)
return ind
}