mirror of
				https://github.com/golang/go.git
				synced 2025-10-31 00:30:57 +00:00 
			
		
		
		
	 295307ae78
			
		
	
	
		295307ae78
		
	
	
	
	
		
			
			With this change, code like
    h := sha1.New()
    h.Write(buf)
    sum := h.Sum()
gets compiled into static calls rather than
interface calls, because the compiler is able
to prove that 'h' is really a *sha1.digest.
The InterCall re-write rule hits a few dozen times
during make.bash, and hundreds of times during all.bash.
The most common pattern identified by the compiler
is a constructor like
    func New() Interface { return &impl{...} }
where the constructor gets inlined into the caller,
and the result is used immediately. Examples include
{sha1,md5,crc32,crc64,...}.New, base64.NewEncoder,
base64.NewDecoder, errors.New, net.Pipe, and so on.
Some existing benchmarks that change on darwin/amd64:
Crc64/ISO4KB-8        2.67µs ± 1%    2.66µs ± 0%  -0.36%  (p=0.015 n=10+10)
Crc64/ISO1KB-8         694ns ± 0%     690ns ± 1%  -0.59%  (p=0.001 n=10+10)
Adler32KB-8            473ns ± 1%     471ns ± 0%  -0.39%  (p=0.010 n=10+9)
On architectures like amd64, the reduction in code size
appears to contribute more to benchmark improvements than just
removing the indirect call, since that branch gets predicted
accurately when called in a loop.
Updates #19361
Change-Id: I57d4dc21ef40a05ec0fbd55a9bb0eb74cdc67a3d
Reviewed-on: https://go-review.googlesource.com/38139
Run-TryBot: Philip Hofer <phofer@umich.edu>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
		
	
			
		
			
				
	
	
		
			39 lines
		
	
	
	
		
			599 B
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			39 lines
		
	
	
	
		
			599 B
		
	
	
	
		
			Go
		
	
	
	
	
	
| // errorcheck -0 -d=ssa/opt/debug=3
 | |
| 
 | |
| package main
 | |
| 
 | |
| // Trivial interface call devirtualization test.
 | |
| 
 | |
| type real struct {
 | |
| 	value int
 | |
| }
 | |
| 
 | |
| func (r *real) Value() int { return r.value }
 | |
| 
 | |
| type Valuer interface {
 | |
| 	Value() int
 | |
| }
 | |
| 
 | |
| type indirectiface struct {
 | |
| 	a, b, c int
 | |
| }
 | |
| 
 | |
| func (i indirectiface) Value() int {
 | |
| 	return i.a + i.b + i.c
 | |
| }
 | |
| 
 | |
| func main() {
 | |
| 	var r Valuer
 | |
| 	rptr := &real{value: 3}
 | |
| 	r = rptr
 | |
| 
 | |
| 	if r.Value() != 3 { // ERROR "de-virtualizing call$"
 | |
| 		panic("not 3")
 | |
| 	}
 | |
| 
 | |
| 	// Can't do types that aren't "direct" interfaces (yet).
 | |
| 	r = indirectiface{3, 4, 5}
 | |
| 	if r.Value() != 12 {
 | |
| 		panic("not 12")
 | |
| 	}
 | |
| }
 |