2015-02-13 14:40:36 -05:00
|
|
|
// 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/internal/obj"
|
|
|
|
|
"fmt"
|
|
|
|
|
)
|
|
|
|
|
|
2015-10-22 09:51:12 +09:00
|
|
|
// portable half of code generator.
|
|
|
|
|
// mainly statements and control flow.
|
2015-02-13 14:40:36 -05:00
|
|
|
var labellist *Label
|
|
|
|
|
|
|
|
|
|
var lastlabel *Label
|
|
|
|
|
|
|
|
|
|
func Sysfunc(name string) *Node {
|
2015-02-23 16:07:24 -05:00
|
|
|
n := newname(Pkglookup(name, Runtimepkg))
|
2015-02-13 14:40:36 -05:00
|
|
|
n.Class = PFUNC
|
|
|
|
|
return n
|
|
|
|
|
}
|
|
|
|
|
|
cmd/internal/gc: improve flow of input params to output params
This includes the following information in the per-function summary:
outK = paramJ encoded in outK bits for paramJ
outK = *paramJ encoded in outK bits for paramJ
heap = paramJ EscHeap
heap = *paramJ EscContentEscapes
Note that (currently) if the address of a parameter is taken and
returned, necessarily a heap allocation occurred to contain that
reference, and the heap can never refer to stack, therefore the
parameter and everything downstream from it escapes to the heap.
The per-function summary information now has a tuneable number of bits
(2 is probably noticeably better than 1, 3 is likely overkill, but it
is now easy to check and the -m debugging output includes information
that allows you to figure out if more would be better.)
A new test was added to check pointer flow through struct-typed and
*struct-typed parameters and returns; some of these are sensitive to
the number of summary bits, and ought to yield better results with a
more competent escape analysis algorithm. Another new test checks
(some) correctness with array parameters, results, and operations.
The old analysis inferred a piece of plan9 runtime was non-escaping by
counteracting overconservative analysis with buggy analysis; with the
bug fixed, the result was too conservative (and it's not easy to fix
in this framework) so the source code was tweaked to get the desired
result. A test was added against the discovered bug.
The escape analysis was further improved splitting the "level" into
3 parts, one tracking the conventional "level" and the other two
computing the highest-level-suffix-from-copy, which is used to
generally model the cancelling effect of indirection applied to
address-of.
With the improved escape analysis enabled, it was necessary to
modify one of the runtime tests because it now attempts to allocate
too much on the (small, fixed-size) G0 (system) stack and this
failed the test.
Compiling src/std after touching src/runtime/*.go with -m logging
turned on shows 420 fewer heap allocation sites (10538 vs 10968).
Profiling allocations in src/html/template with
for i in {1..5} ;
do go tool 6g -memprofile=mastx.${i}.prof -memprofilerate=1 *.go;
go tool pprof -alloc_objects -text mastx.${i}.prof ;
done
showed a 15% reduction in allocations performed by the compiler.
Update #3753
Update #4720
Fixes #10466
Change-Id: I0fd97d5f5ac527b45f49e2218d158a6e89951432
Reviewed-on: https://go-review.googlesource.com/8202
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
2015-03-26 16:36:15 -04:00
|
|
|
// addrescapes tags node n as having had its address taken
|
|
|
|
|
// by "increasing" the "value" of n.Esc to EscHeap.
|
|
|
|
|
// Storage is allocated as necessary to allow the address
|
|
|
|
|
// to be taken.
|
2015-02-13 14:40:36 -05:00
|
|
|
func addrescapes(n *Node) {
|
|
|
|
|
switch n.Op {
|
|
|
|
|
// probably a type error already.
|
|
|
|
|
// dump("addrescapes", n);
|
|
|
|
|
default:
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
case ONAME:
|
|
|
|
|
if n == nodfp {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if this is a tmpname (PAUTO), it was tagged by tmpname as not escaping.
|
|
|
|
|
// on PPARAM it means something different.
|
|
|
|
|
if n.Class == PAUTO && n.Esc == EscNever {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch n.Class {
|
|
|
|
|
case PPARAMREF:
|
2015-05-26 22:19:27 -04:00
|
|
|
addrescapes(n.Name.Defn)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
cmd/internal/gc: improve flow of input params to output params
This includes the following information in the per-function summary:
outK = paramJ encoded in outK bits for paramJ
outK = *paramJ encoded in outK bits for paramJ
heap = paramJ EscHeap
heap = *paramJ EscContentEscapes
Note that (currently) if the address of a parameter is taken and
returned, necessarily a heap allocation occurred to contain that
reference, and the heap can never refer to stack, therefore the
parameter and everything downstream from it escapes to the heap.
The per-function summary information now has a tuneable number of bits
(2 is probably noticeably better than 1, 3 is likely overkill, but it
is now easy to check and the -m debugging output includes information
that allows you to figure out if more would be better.)
A new test was added to check pointer flow through struct-typed and
*struct-typed parameters and returns; some of these are sensitive to
the number of summary bits, and ought to yield better results with a
more competent escape analysis algorithm. Another new test checks
(some) correctness with array parameters, results, and operations.
The old analysis inferred a piece of plan9 runtime was non-escaping by
counteracting overconservative analysis with buggy analysis; with the
bug fixed, the result was too conservative (and it's not easy to fix
in this framework) so the source code was tweaked to get the desired
result. A test was added against the discovered bug.
The escape analysis was further improved splitting the "level" into
3 parts, one tracking the conventional "level" and the other two
computing the highest-level-suffix-from-copy, which is used to
generally model the cancelling effect of indirection applied to
address-of.
With the improved escape analysis enabled, it was necessary to
modify one of the runtime tests because it now attempts to allocate
too much on the (small, fixed-size) G0 (system) stack and this
failed the test.
Compiling src/std after touching src/runtime/*.go with -m logging
turned on shows 420 fewer heap allocation sites (10538 vs 10968).
Profiling allocations in src/html/template with
for i in {1..5} ;
do go tool 6g -memprofile=mastx.${i}.prof -memprofilerate=1 *.go;
go tool pprof -alloc_objects -text mastx.${i}.prof ;
done
showed a 15% reduction in allocations performed by the compiler.
Update #3753
Update #4720
Fixes #10466
Change-Id: I0fd97d5f5ac527b45f49e2218d158a6e89951432
Reviewed-on: https://go-review.googlesource.com/8202
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
2015-03-26 16:36:15 -04:00
|
|
|
// if func param, need separate temporary
|
2015-02-13 14:40:36 -05:00
|
|
|
// to hold heap pointer.
|
|
|
|
|
// the function type has already been checked
|
|
|
|
|
// (we're in the function body)
|
|
|
|
|
// so the param already has a valid xoffset.
|
|
|
|
|
|
|
|
|
|
// expression to refer to stack copy
|
2015-04-01 09:38:44 -07:00
|
|
|
case PPARAM, PPARAMOUT:
|
2015-05-27 00:44:05 -04:00
|
|
|
n.Name.Param.Stackparam = Nod(OPARAM, n, nil)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-05-27 00:44:05 -04:00
|
|
|
n.Name.Param.Stackparam.Type = n.Type
|
|
|
|
|
n.Name.Param.Stackparam.Addable = true
|
2015-02-13 14:40:36 -05:00
|
|
|
if n.Xoffset == BADWIDTH {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("addrescapes before param assignment")
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-05-27 00:44:05 -04:00
|
|
|
n.Name.Param.Stackparam.Xoffset = n.Xoffset
|
2015-02-13 14:40:36 -05:00
|
|
|
fallthrough
|
|
|
|
|
|
|
|
|
|
case PAUTO:
|
|
|
|
|
n.Class |= PHEAP
|
|
|
|
|
|
2015-04-02 19:58:37 -07:00
|
|
|
n.Addable = false
|
2015-02-13 14:40:36 -05:00
|
|
|
n.Ullman = 2
|
|
|
|
|
n.Xoffset = 0
|
|
|
|
|
|
|
|
|
|
// create stack variable to hold pointer to heap
|
2015-02-23 16:07:24 -05:00
|
|
|
oldfn := Curfn
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-05-27 07:31:56 -04:00
|
|
|
Curfn = n.Name.Curfn
|
2016-02-25 10:35:19 -08:00
|
|
|
if Curfn.Func.Closure != nil && Curfn.Op == OCLOSURE {
|
|
|
|
|
Curfn = Curfn.Func.Closure
|
|
|
|
|
}
|
2015-05-15 10:02:19 -07:00
|
|
|
n.Name.Heapaddr = temp(Ptrto(n.Type))
|
2015-04-17 12:03:22 -04:00
|
|
|
buf := fmt.Sprintf("&%v", n.Sym)
|
2015-05-15 10:02:19 -07:00
|
|
|
n.Name.Heapaddr.Sym = Lookup(buf)
|
|
|
|
|
n.Name.Heapaddr.Orig.Sym = n.Name.Heapaddr.Sym
|
2015-02-13 14:40:36 -05:00
|
|
|
n.Esc = EscHeap
|
|
|
|
|
if Debug['m'] != 0 {
|
2015-04-17 12:03:22 -04:00
|
|
|
fmt.Printf("%v: moved to heap: %v\n", n.Line(), n)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
Curfn = oldfn
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case OIND, ODOTPTR:
|
2015-02-13 14:40:36 -05:00
|
|
|
break
|
|
|
|
|
|
cmd/internal/gc: improve flow of input params to output params
This includes the following information in the per-function summary:
outK = paramJ encoded in outK bits for paramJ
outK = *paramJ encoded in outK bits for paramJ
heap = paramJ EscHeap
heap = *paramJ EscContentEscapes
Note that (currently) if the address of a parameter is taken and
returned, necessarily a heap allocation occurred to contain that
reference, and the heap can never refer to stack, therefore the
parameter and everything downstream from it escapes to the heap.
The per-function summary information now has a tuneable number of bits
(2 is probably noticeably better than 1, 3 is likely overkill, but it
is now easy to check and the -m debugging output includes information
that allows you to figure out if more would be better.)
A new test was added to check pointer flow through struct-typed and
*struct-typed parameters and returns; some of these are sensitive to
the number of summary bits, and ought to yield better results with a
more competent escape analysis algorithm. Another new test checks
(some) correctness with array parameters, results, and operations.
The old analysis inferred a piece of plan9 runtime was non-escaping by
counteracting overconservative analysis with buggy analysis; with the
bug fixed, the result was too conservative (and it's not easy to fix
in this framework) so the source code was tweaked to get the desired
result. A test was added against the discovered bug.
The escape analysis was further improved splitting the "level" into
3 parts, one tracking the conventional "level" and the other two
computing the highest-level-suffix-from-copy, which is used to
generally model the cancelling effect of indirection applied to
address-of.
With the improved escape analysis enabled, it was necessary to
modify one of the runtime tests because it now attempts to allocate
too much on the (small, fixed-size) G0 (system) stack and this
failed the test.
Compiling src/std after touching src/runtime/*.go with -m logging
turned on shows 420 fewer heap allocation sites (10538 vs 10968).
Profiling allocations in src/html/template with
for i in {1..5} ;
do go tool 6g -memprofile=mastx.${i}.prof -memprofilerate=1 *.go;
go tool pprof -alloc_objects -text mastx.${i}.prof ;
done
showed a 15% reduction in allocations performed by the compiler.
Update #3753
Update #4720
Fixes #10466
Change-Id: I0fd97d5f5ac527b45f49e2218d158a6e89951432
Reviewed-on: https://go-review.googlesource.com/8202
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
2015-03-26 16:36:15 -04:00
|
|
|
// ODOTPTR has already been introduced,
|
2015-02-13 14:40:36 -05:00
|
|
|
// so these are the non-pointer ODOT and OINDEX.
|
|
|
|
|
// In &x[0], if x is a slice, then x does not
|
|
|
|
|
// escape--the pointer inside x does, but that
|
|
|
|
|
// is always a heap pointer anyway.
|
cmd/internal/gc: improve flow of input params to output params
This includes the following information in the per-function summary:
outK = paramJ encoded in outK bits for paramJ
outK = *paramJ encoded in outK bits for paramJ
heap = paramJ EscHeap
heap = *paramJ EscContentEscapes
Note that (currently) if the address of a parameter is taken and
returned, necessarily a heap allocation occurred to contain that
reference, and the heap can never refer to stack, therefore the
parameter and everything downstream from it escapes to the heap.
The per-function summary information now has a tuneable number of bits
(2 is probably noticeably better than 1, 3 is likely overkill, but it
is now easy to check and the -m debugging output includes information
that allows you to figure out if more would be better.)
A new test was added to check pointer flow through struct-typed and
*struct-typed parameters and returns; some of these are sensitive to
the number of summary bits, and ought to yield better results with a
more competent escape analysis algorithm. Another new test checks
(some) correctness with array parameters, results, and operations.
The old analysis inferred a piece of plan9 runtime was non-escaping by
counteracting overconservative analysis with buggy analysis; with the
bug fixed, the result was too conservative (and it's not easy to fix
in this framework) so the source code was tweaked to get the desired
result. A test was added against the discovered bug.
The escape analysis was further improved splitting the "level" into
3 parts, one tracking the conventional "level" and the other two
computing the highest-level-suffix-from-copy, which is used to
generally model the cancelling effect of indirection applied to
address-of.
With the improved escape analysis enabled, it was necessary to
modify one of the runtime tests because it now attempts to allocate
too much on the (small, fixed-size) G0 (system) stack and this
failed the test.
Compiling src/std after touching src/runtime/*.go with -m logging
turned on shows 420 fewer heap allocation sites (10538 vs 10968).
Profiling allocations in src/html/template with
for i in {1..5} ;
do go tool 6g -memprofile=mastx.${i}.prof -memprofilerate=1 *.go;
go tool pprof -alloc_objects -text mastx.${i}.prof ;
done
showed a 15% reduction in allocations performed by the compiler.
Update #3753
Update #4720
Fixes #10466
Change-Id: I0fd97d5f5ac527b45f49e2218d158a6e89951432
Reviewed-on: https://go-review.googlesource.com/8202
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
2015-03-26 16:36:15 -04:00
|
|
|
case ODOT, OINDEX, OPAREN, OCONVNOP:
|
2015-02-17 22:13:49 -05:00
|
|
|
if !Isslice(n.Left.Type) {
|
2015-02-13 14:40:36 -05:00
|
|
|
addrescapes(n.Left)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func clearlabels() {
|
2015-02-23 16:07:24 -05:00
|
|
|
for l := labellist; l != nil; l = l.Link {
|
2015-02-13 14:40:36 -05:00
|
|
|
l.Sym.Label = nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
labellist = nil
|
|
|
|
|
lastlabel = nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func newlab(n *Node) *Label {
|
2015-02-23 16:07:24 -05:00
|
|
|
s := n.Left.Sym
|
|
|
|
|
lab := s.Label
|
2015-02-13 14:40:36 -05:00
|
|
|
if lab == nil {
|
|
|
|
|
lab = new(Label)
|
|
|
|
|
if lastlabel == nil {
|
|
|
|
|
labellist = lab
|
|
|
|
|
} else {
|
|
|
|
|
lastlabel.Link = lab
|
|
|
|
|
}
|
|
|
|
|
lastlabel = lab
|
|
|
|
|
lab.Sym = s
|
|
|
|
|
s.Label = lab
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Op == OLABEL {
|
|
|
|
|
if lab.Def != nil {
|
2015-04-17 12:03:22 -04:00
|
|
|
Yyerror("label %v already defined at %v", s, lab.Def.Line())
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
|
|
|
|
lab.Def = n
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2015-08-30 22:24:53 +02:00
|
|
|
lab.Use = append(lab.Use, n)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return lab
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-20 15:39:14 -07:00
|
|
|
// There is a copy of checkgoto in the new SSA backend.
|
|
|
|
|
// Please keep them in sync.
|
2015-02-13 14:40:36 -05:00
|
|
|
func checkgoto(from *Node, to *Node) {
|
|
|
|
|
if from.Sym == to.Sym {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
nf := 0
|
|
|
|
|
for fs := from.Sym; fs != nil; fs = fs.Link {
|
2015-02-13 14:40:36 -05:00
|
|
|
nf++
|
|
|
|
|
}
|
2015-02-23 16:07:24 -05:00
|
|
|
nt := 0
|
|
|
|
|
for fs := to.Sym; fs != nil; fs = fs.Link {
|
2015-02-13 14:40:36 -05:00
|
|
|
nt++
|
|
|
|
|
}
|
2015-02-23 16:07:24 -05:00
|
|
|
fs := from.Sym
|
2015-02-13 14:40:36 -05:00
|
|
|
for ; nf > nt; nf-- {
|
|
|
|
|
fs = fs.Link
|
|
|
|
|
}
|
|
|
|
|
if fs != to.Sym {
|
2016-03-02 17:34:42 -08:00
|
|
|
lno := lineno
|
2015-02-13 14:40:36 -05:00
|
|
|
setlineno(from)
|
|
|
|
|
|
|
|
|
|
// decide what to complain about.
|
|
|
|
|
// prefer to complain about 'into block' over declarations,
|
|
|
|
|
// so scan backward to find most recent block or else dcl.
|
2015-03-02 14:22:05 -05:00
|
|
|
var block *Sym
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-03-02 14:22:05 -05:00
|
|
|
var dcl *Sym
|
2015-05-15 16:35:43 +00:00
|
|
|
ts := to.Sym
|
2015-02-13 14:40:36 -05:00
|
|
|
for ; nt > nf; nt-- {
|
|
|
|
|
if ts.Pkg == nil {
|
|
|
|
|
block = ts
|
2015-05-15 16:35:43 +00:00
|
|
|
} else {
|
2015-02-13 14:40:36 -05:00
|
|
|
dcl = ts
|
|
|
|
|
}
|
|
|
|
|
ts = ts.Link
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for ts != fs {
|
|
|
|
|
if ts.Pkg == nil {
|
|
|
|
|
block = ts
|
2015-05-15 16:35:43 +00:00
|
|
|
} else {
|
2015-02-13 14:40:36 -05:00
|
|
|
dcl = ts
|
|
|
|
|
}
|
|
|
|
|
ts = ts.Link
|
|
|
|
|
fs = fs.Link
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if block != nil {
|
2016-03-02 11:30:29 -08:00
|
|
|
Yyerror("goto %v jumps into block starting at %v", from.Left.Sym, linestr(block.Lastlineno))
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
2016-03-02 11:30:29 -08:00
|
|
|
Yyerror("goto %v jumps over declaration of %v at %v", from.Left.Sym, dcl, linestr(dcl.Lastlineno))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-03-02 17:34:42 -08:00
|
|
|
lineno = lno
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func stmtlabel(n *Node) *Label {
|
|
|
|
|
if n.Sym != nil {
|
2015-02-23 16:07:24 -05:00
|
|
|
lab := n.Sym.Label
|
2015-02-13 14:40:36 -05:00
|
|
|
if lab != nil {
|
|
|
|
|
if lab.Def != nil {
|
2015-05-26 22:19:27 -04:00
|
|
|
if lab.Def.Name.Defn == n {
|
2015-02-13 14:40:36 -05:00
|
|
|
return lab
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-22 09:51:12 +09:00
|
|
|
// compile statements
|
2015-02-13 14:40:36 -05:00
|
|
|
func Genlist(l *NodeList) {
|
|
|
|
|
for ; l != nil; l = l.Next {
|
|
|
|
|
gen(l.N)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-26 14:28:48 -08:00
|
|
|
func Genslice(l []*Node) {
|
|
|
|
|
for _, n := range l {
|
|
|
|
|
gen(n)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-22 09:51:12 +09:00
|
|
|
// generate code to start new proc running call n.
|
2015-02-13 14:40:36 -05:00
|
|
|
func cgen_proc(n *Node, proc int) {
|
|
|
|
|
switch n.Left.Op {
|
|
|
|
|
default:
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("cgen_proc: unknown call %v", Oconv(int(n.Left.Op), 0))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OCALLMETH:
|
2015-03-18 17:26:36 -04:00
|
|
|
cgen_callmeth(n.Left, proc)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OCALLINTER:
|
2015-03-18 17:26:36 -04:00
|
|
|
cgen_callinter(n.Left, nil, proc)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OCALLFUNC:
|
2015-03-18 17:26:36 -04:00
|
|
|
cgen_call(n.Left, proc)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-22 09:51:12 +09:00
|
|
|
// generate declaration.
|
|
|
|
|
// have to allocate heap copy
|
|
|
|
|
// for escaped variables.
|
2015-02-13 14:40:36 -05:00
|
|
|
func cgen_dcl(n *Node) {
|
|
|
|
|
if Debug['g'] != 0 {
|
|
|
|
|
Dump("\ncgen-dcl", n)
|
|
|
|
|
}
|
|
|
|
|
if n.Op != ONAME {
|
|
|
|
|
Dump("cgen_dcl", n)
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("cgen_dcl")
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if n.Class&PHEAP == 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if compiling_runtime != 0 {
|
2015-04-17 12:03:22 -04:00
|
|
|
Yyerror("%v escapes to heap, not allowed in runtime.", n)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-05-26 23:05:35 -04:00
|
|
|
if prealloc[n] == nil {
|
|
|
|
|
prealloc[n] = callnew(n.Type)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-05-26 23:05:35 -04:00
|
|
|
Cgen_as(n.Name.Heapaddr, prealloc[n])
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-10-22 09:51:12 +09:00
|
|
|
// generate discard of value
|
2015-02-13 14:40:36 -05:00
|
|
|
func cgen_discard(nr *Node) {
|
|
|
|
|
if nr == nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch nr.Op {
|
|
|
|
|
case ONAME:
|
2015-02-17 22:13:49 -05:00
|
|
|
if nr.Class&PHEAP == 0 && nr.Class != PEXTERN && nr.Class != PFUNC && nr.Class != PPARAMREF {
|
2015-02-13 14:40:36 -05:00
|
|
|
gused(nr)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// unary
|
|
|
|
|
case OADD,
|
|
|
|
|
OAND,
|
|
|
|
|
ODIV,
|
|
|
|
|
OEQ,
|
|
|
|
|
OGE,
|
|
|
|
|
OGT,
|
|
|
|
|
OLE,
|
|
|
|
|
OLSH,
|
|
|
|
|
OLT,
|
|
|
|
|
OMOD,
|
|
|
|
|
OMUL,
|
|
|
|
|
ONE,
|
|
|
|
|
OOR,
|
|
|
|
|
ORSH,
|
|
|
|
|
OSUB,
|
|
|
|
|
OXOR:
|
|
|
|
|
cgen_discard(nr.Left)
|
|
|
|
|
|
|
|
|
|
cgen_discard(nr.Right)
|
|
|
|
|
|
|
|
|
|
// binary
|
|
|
|
|
case OCAP,
|
|
|
|
|
OCOM,
|
|
|
|
|
OLEN,
|
|
|
|
|
OMINUS,
|
|
|
|
|
ONOT,
|
|
|
|
|
OPLUS:
|
|
|
|
|
cgen_discard(nr.Left)
|
|
|
|
|
|
|
|
|
|
case OIND:
|
|
|
|
|
Cgen_checknil(nr.Left)
|
|
|
|
|
|
|
|
|
|
// special enough to just evaluate
|
|
|
|
|
default:
|
2015-02-23 16:07:24 -05:00
|
|
|
var tmp Node
|
2015-02-13 14:40:36 -05:00
|
|
|
Tempname(&tmp, nr.Type)
|
|
|
|
|
|
|
|
|
|
Cgen_as(&tmp, nr)
|
|
|
|
|
gused(&tmp)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-22 09:51:12 +09:00
|
|
|
// clearslim generates code to zero a slim node.
|
2015-02-13 14:40:36 -05:00
|
|
|
func Clearslim(n *Node) {
|
2015-03-02 14:22:05 -05:00
|
|
|
var z Node
|
2015-02-13 14:40:36 -05:00
|
|
|
z.Op = OLITERAL
|
|
|
|
|
z.Type = n.Type
|
2015-04-02 19:58:37 -07:00
|
|
|
z.Addable = true
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
switch Simtype[n.Type.Etype] {
|
2015-04-01 09:38:44 -07:00
|
|
|
case TCOMPLEX64, TCOMPLEX128:
|
2015-05-27 00:47:05 -04:00
|
|
|
z.SetVal(Val{new(Mpcplx)})
|
|
|
|
|
Mpmovecflt(&z.Val().U.(*Mpcplx).Real, 0.0)
|
|
|
|
|
Mpmovecflt(&z.Val().U.(*Mpcplx).Imag, 0.0)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case TFLOAT32, TFLOAT64:
|
2015-02-23 16:07:24 -05:00
|
|
|
var zero Mpflt
|
2015-02-13 14:40:36 -05:00
|
|
|
Mpmovecflt(&zero, 0.0)
|
2015-05-27 00:47:05 -04:00
|
|
|
z.SetVal(Val{&zero})
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case TPTR32, TPTR64, TCHAN, TMAP:
|
2015-05-27 00:47:05 -04:00
|
|
|
z.SetVal(Val{new(NilVal)})
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case TBOOL:
|
2015-05-27 00:47:05 -04:00
|
|
|
z.SetVal(Val{false})
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case TINT8,
|
|
|
|
|
TINT16,
|
|
|
|
|
TINT32,
|
|
|
|
|
TINT64,
|
|
|
|
|
TUINT8,
|
|
|
|
|
TUINT16,
|
|
|
|
|
TUINT32,
|
|
|
|
|
TUINT64:
|
2015-05-27 00:47:05 -04:00
|
|
|
z.SetVal(Val{new(Mpint)})
|
|
|
|
|
Mpmovecfix(z.Val().U.(*Mpint), 0)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
default:
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("clearslim called on type %v", n.Type)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ullmancalc(&z)
|
2015-03-18 17:26:36 -04:00
|
|
|
Cgen(&z, n)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-10-22 09:51:12 +09:00
|
|
|
// generate:
|
|
|
|
|
// res = iface{typ, data}
|
|
|
|
|
// n->left is typ
|
|
|
|
|
// n->right is data
|
2015-02-13 14:40:36 -05:00
|
|
|
func Cgen_eface(n *Node, res *Node) {
|
2015-10-22 09:51:12 +09:00
|
|
|
// the right node of an eface may contain function calls that uses res as an argument,
|
|
|
|
|
// so it's important that it is done first
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
tmp := temp(Types[Tptr])
|
2015-03-18 17:26:36 -04:00
|
|
|
Cgen(n.Right, tmp)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
Gvardef(res)
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
dst := *res
|
2015-02-13 14:40:36 -05:00
|
|
|
dst.Type = Types[Tptr]
|
|
|
|
|
dst.Xoffset += int64(Widthptr)
|
2015-03-18 17:26:36 -04:00
|
|
|
Cgen(tmp, &dst)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
dst.Xoffset -= int64(Widthptr)
|
2015-03-18 17:26:36 -04:00
|
|
|
Cgen(n.Left, &dst)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-10-22 09:51:12 +09:00
|
|
|
// generate one of:
|
|
|
|
|
// res, resok = x.(T)
|
|
|
|
|
// res = x.(T) (when resok == nil)
|
|
|
|
|
// n.Left is x
|
|
|
|
|
// n.Type is T
|
cmd/internal/gc: emit write barriers at lower level
This is primarily preparation for inlining, not an optimization by itself,
but it still helps some.
name old new delta
BenchmarkBinaryTree17 18.2s × (0.99,1.01) 17.9s × (0.99,1.01) -1.57%
BenchmarkFannkuch11 4.44s × (1.00,1.00) 4.42s × (1.00,1.00) -0.40%
BenchmarkFmtFprintfEmpty 119ns × (0.95,1.02) 118ns × (0.96,1.02) ~
BenchmarkFmtFprintfString 501ns × (0.99,1.02) 486ns × (0.99,1.01) -2.89%
BenchmarkFmtFprintfInt 474ns × (0.99,1.00) 457ns × (0.99,1.01) -3.59%
BenchmarkFmtFprintfIntInt 792ns × (1.00,1.00) 768ns × (1.00,1.01) -3.03%
BenchmarkFmtFprintfPrefixedInt 574ns × (1.00,1.01) 584ns × (0.99,1.03) +1.83%
BenchmarkFmtFprintfFloat 749ns × (1.00,1.00) 739ns × (0.99,1.00) -1.34%
BenchmarkFmtManyArgs 2.94µs × (1.00,1.01) 2.77µs × (1.00,1.00) -5.76%
BenchmarkGobDecode 39.5ms × (0.99,1.01) 39.3ms × (0.99,1.01) ~
BenchmarkGobEncode 39.4ms × (1.00,1.01) 39.4ms × (0.99,1.00) ~
BenchmarkGzip 658ms × (1.00,1.01) 661ms × (0.99,1.01) ~
BenchmarkGunzip 142ms × (1.00,1.00) 142ms × (1.00,1.00) +0.22%
BenchmarkHTTPClientServer 134µs × (0.99,1.01) 133µs × (0.98,1.01) ~
BenchmarkJSONEncode 57.1ms × (0.99,1.01) 56.5ms × (0.99,1.01) ~
BenchmarkJSONDecode 141ms × (1.00,1.00) 143ms × (1.00,1.00) +1.09%
BenchmarkMandelbrot200 6.01ms × (1.00,1.00) 6.01ms × (1.00,1.00) ~
BenchmarkGoParse 10.1ms × (0.91,1.09) 9.6ms × (0.94,1.07) ~
BenchmarkRegexpMatchEasy0_32 207ns × (1.00,1.01) 210ns × (1.00,1.00) +1.45%
BenchmarkRegexpMatchEasy0_1K 592ns × (0.99,1.00) 596ns × (0.99,1.01) +0.68%
BenchmarkRegexpMatchEasy1_32 184ns × (0.99,1.01) 184ns × (0.99,1.01) ~
BenchmarkRegexpMatchEasy1_1K 1.01µs × (1.00,1.00) 1.01µs × (0.99,1.01) ~
BenchmarkRegexpMatchMedium_32 327ns × (0.99,1.00) 327ns × (1.00,1.01) ~
BenchmarkRegexpMatchMedium_1K 92.5µs × (1.00,1.00) 93.0µs × (1.00,1.02) +0.48%
BenchmarkRegexpMatchHard_32 4.79µs × (0.95,1.00) 4.76µs × (0.95,1.01) ~
BenchmarkRegexpMatchHard_1K 136µs × (1.00,1.00) 136µs × (1.00,1.01) ~
BenchmarkRevcomp 900ms × (0.99,1.01) 892ms × (1.00,1.01) ~
BenchmarkTemplate 170ms × (0.99,1.01) 175ms × (0.99,1.00) +2.95%
BenchmarkTimeParse 645ns × (1.00,1.00) 638ns × (1.00,1.00) -1.16%
BenchmarkTimeFormat 740ns × (1.00,1.00) 772ns × (1.00,1.00) +4.39%
Change-Id: I0be905e32791e0cb70ff01f169c4b309a971d981
Reviewed-on: https://go-review.googlesource.com/9159
Reviewed-by: Rick Hudson <rlh@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2015-04-17 00:25:10 -04:00
|
|
|
func cgen_dottype(n *Node, res, resok *Node, wb bool) {
|
2015-03-20 00:06:10 -04:00
|
|
|
if Debug_typeassert > 0 {
|
|
|
|
|
Warn("type assertion inlined")
|
|
|
|
|
}
|
|
|
|
|
// iface := n.Left
|
|
|
|
|
// r1 := iword(iface)
|
|
|
|
|
// if n.Left is non-empty interface {
|
|
|
|
|
// r1 = *r1
|
|
|
|
|
// }
|
|
|
|
|
// if r1 == T {
|
|
|
|
|
// res = idata(iface)
|
|
|
|
|
// resok = true
|
|
|
|
|
// } else {
|
|
|
|
|
// assert[EI]2T(x, T, nil) // (when resok == nil; does not return)
|
|
|
|
|
// resok = false // (when resok != nil)
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
var iface Node
|
|
|
|
|
Igen(n.Left, &iface, res)
|
|
|
|
|
var r1, r2 Node
|
|
|
|
|
byteptr := Ptrto(Types[TUINT8]) // type used in runtime prototypes for runtime type (*byte)
|
|
|
|
|
Regalloc(&r1, byteptr, nil)
|
|
|
|
|
iface.Type = byteptr
|
|
|
|
|
Cgen(&iface, &r1)
|
|
|
|
|
if !isnilinter(n.Left.Type) {
|
|
|
|
|
// Holding itab, want concrete type in second word.
|
2015-05-06 12:28:19 -04:00
|
|
|
p := Thearch.Ginscmp(OEQ, byteptr, &r1, Nodintconst(0), -1)
|
2015-03-20 00:06:10 -04:00
|
|
|
r2 = r1
|
|
|
|
|
r2.Op = OINDREG
|
|
|
|
|
r2.Xoffset = int64(Widthptr)
|
|
|
|
|
Cgen(&r2, &r1)
|
|
|
|
|
Patch(p, Pc)
|
|
|
|
|
}
|
|
|
|
|
Regalloc(&r2, byteptr, nil)
|
|
|
|
|
Cgen(typename(n.Type), &r2)
|
2015-05-06 12:28:19 -04:00
|
|
|
p := Thearch.Ginscmp(ONE, byteptr, &r1, &r2, -1)
|
cmd/internal/gc: emit write barriers at lower level
This is primarily preparation for inlining, not an optimization by itself,
but it still helps some.
name old new delta
BenchmarkBinaryTree17 18.2s × (0.99,1.01) 17.9s × (0.99,1.01) -1.57%
BenchmarkFannkuch11 4.44s × (1.00,1.00) 4.42s × (1.00,1.00) -0.40%
BenchmarkFmtFprintfEmpty 119ns × (0.95,1.02) 118ns × (0.96,1.02) ~
BenchmarkFmtFprintfString 501ns × (0.99,1.02) 486ns × (0.99,1.01) -2.89%
BenchmarkFmtFprintfInt 474ns × (0.99,1.00) 457ns × (0.99,1.01) -3.59%
BenchmarkFmtFprintfIntInt 792ns × (1.00,1.00) 768ns × (1.00,1.01) -3.03%
BenchmarkFmtFprintfPrefixedInt 574ns × (1.00,1.01) 584ns × (0.99,1.03) +1.83%
BenchmarkFmtFprintfFloat 749ns × (1.00,1.00) 739ns × (0.99,1.00) -1.34%
BenchmarkFmtManyArgs 2.94µs × (1.00,1.01) 2.77µs × (1.00,1.00) -5.76%
BenchmarkGobDecode 39.5ms × (0.99,1.01) 39.3ms × (0.99,1.01) ~
BenchmarkGobEncode 39.4ms × (1.00,1.01) 39.4ms × (0.99,1.00) ~
BenchmarkGzip 658ms × (1.00,1.01) 661ms × (0.99,1.01) ~
BenchmarkGunzip 142ms × (1.00,1.00) 142ms × (1.00,1.00) +0.22%
BenchmarkHTTPClientServer 134µs × (0.99,1.01) 133µs × (0.98,1.01) ~
BenchmarkJSONEncode 57.1ms × (0.99,1.01) 56.5ms × (0.99,1.01) ~
BenchmarkJSONDecode 141ms × (1.00,1.00) 143ms × (1.00,1.00) +1.09%
BenchmarkMandelbrot200 6.01ms × (1.00,1.00) 6.01ms × (1.00,1.00) ~
BenchmarkGoParse 10.1ms × (0.91,1.09) 9.6ms × (0.94,1.07) ~
BenchmarkRegexpMatchEasy0_32 207ns × (1.00,1.01) 210ns × (1.00,1.00) +1.45%
BenchmarkRegexpMatchEasy0_1K 592ns × (0.99,1.00) 596ns × (0.99,1.01) +0.68%
BenchmarkRegexpMatchEasy1_32 184ns × (0.99,1.01) 184ns × (0.99,1.01) ~
BenchmarkRegexpMatchEasy1_1K 1.01µs × (1.00,1.00) 1.01µs × (0.99,1.01) ~
BenchmarkRegexpMatchMedium_32 327ns × (0.99,1.00) 327ns × (1.00,1.01) ~
BenchmarkRegexpMatchMedium_1K 92.5µs × (1.00,1.00) 93.0µs × (1.00,1.02) +0.48%
BenchmarkRegexpMatchHard_32 4.79µs × (0.95,1.00) 4.76µs × (0.95,1.01) ~
BenchmarkRegexpMatchHard_1K 136µs × (1.00,1.00) 136µs × (1.00,1.01) ~
BenchmarkRevcomp 900ms × (0.99,1.01) 892ms × (1.00,1.01) ~
BenchmarkTemplate 170ms × (0.99,1.01) 175ms × (0.99,1.00) +2.95%
BenchmarkTimeParse 645ns × (1.00,1.00) 638ns × (1.00,1.00) -1.16%
BenchmarkTimeFormat 740ns × (1.00,1.00) 772ns × (1.00,1.00) +4.39%
Change-Id: I0be905e32791e0cb70ff01f169c4b309a971d981
Reviewed-on: https://go-review.googlesource.com/9159
Reviewed-by: Rick Hudson <rlh@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2015-04-17 00:25:10 -04:00
|
|
|
Regfree(&r2) // not needed for success path; reclaimed on one failure path
|
2015-03-20 00:06:10 -04:00
|
|
|
iface.Xoffset += int64(Widthptr)
|
|
|
|
|
Cgen(&iface, &r1)
|
|
|
|
|
Regfree(&iface)
|
|
|
|
|
|
|
|
|
|
if resok == nil {
|
|
|
|
|
r1.Type = res.Type
|
cmd/internal/gc: emit write barriers at lower level
This is primarily preparation for inlining, not an optimization by itself,
but it still helps some.
name old new delta
BenchmarkBinaryTree17 18.2s × (0.99,1.01) 17.9s × (0.99,1.01) -1.57%
BenchmarkFannkuch11 4.44s × (1.00,1.00) 4.42s × (1.00,1.00) -0.40%
BenchmarkFmtFprintfEmpty 119ns × (0.95,1.02) 118ns × (0.96,1.02) ~
BenchmarkFmtFprintfString 501ns × (0.99,1.02) 486ns × (0.99,1.01) -2.89%
BenchmarkFmtFprintfInt 474ns × (0.99,1.00) 457ns × (0.99,1.01) -3.59%
BenchmarkFmtFprintfIntInt 792ns × (1.00,1.00) 768ns × (1.00,1.01) -3.03%
BenchmarkFmtFprintfPrefixedInt 574ns × (1.00,1.01) 584ns × (0.99,1.03) +1.83%
BenchmarkFmtFprintfFloat 749ns × (1.00,1.00) 739ns × (0.99,1.00) -1.34%
BenchmarkFmtManyArgs 2.94µs × (1.00,1.01) 2.77µs × (1.00,1.00) -5.76%
BenchmarkGobDecode 39.5ms × (0.99,1.01) 39.3ms × (0.99,1.01) ~
BenchmarkGobEncode 39.4ms × (1.00,1.01) 39.4ms × (0.99,1.00) ~
BenchmarkGzip 658ms × (1.00,1.01) 661ms × (0.99,1.01) ~
BenchmarkGunzip 142ms × (1.00,1.00) 142ms × (1.00,1.00) +0.22%
BenchmarkHTTPClientServer 134µs × (0.99,1.01) 133µs × (0.98,1.01) ~
BenchmarkJSONEncode 57.1ms × (0.99,1.01) 56.5ms × (0.99,1.01) ~
BenchmarkJSONDecode 141ms × (1.00,1.00) 143ms × (1.00,1.00) +1.09%
BenchmarkMandelbrot200 6.01ms × (1.00,1.00) 6.01ms × (1.00,1.00) ~
BenchmarkGoParse 10.1ms × (0.91,1.09) 9.6ms × (0.94,1.07) ~
BenchmarkRegexpMatchEasy0_32 207ns × (1.00,1.01) 210ns × (1.00,1.00) +1.45%
BenchmarkRegexpMatchEasy0_1K 592ns × (0.99,1.00) 596ns × (0.99,1.01) +0.68%
BenchmarkRegexpMatchEasy1_32 184ns × (0.99,1.01) 184ns × (0.99,1.01) ~
BenchmarkRegexpMatchEasy1_1K 1.01µs × (1.00,1.00) 1.01µs × (0.99,1.01) ~
BenchmarkRegexpMatchMedium_32 327ns × (0.99,1.00) 327ns × (1.00,1.01) ~
BenchmarkRegexpMatchMedium_1K 92.5µs × (1.00,1.00) 93.0µs × (1.00,1.02) +0.48%
BenchmarkRegexpMatchHard_32 4.79µs × (0.95,1.00) 4.76µs × (0.95,1.01) ~
BenchmarkRegexpMatchHard_1K 136µs × (1.00,1.00) 136µs × (1.00,1.01) ~
BenchmarkRevcomp 900ms × (0.99,1.01) 892ms × (1.00,1.01) ~
BenchmarkTemplate 170ms × (0.99,1.01) 175ms × (0.99,1.00) +2.95%
BenchmarkTimeParse 645ns × (1.00,1.00) 638ns × (1.00,1.00) -1.16%
BenchmarkTimeFormat 740ns × (1.00,1.00) 772ns × (1.00,1.00) +4.39%
Change-Id: I0be905e32791e0cb70ff01f169c4b309a971d981
Reviewed-on: https://go-review.googlesource.com/9159
Reviewed-by: Rick Hudson <rlh@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2015-04-17 00:25:10 -04:00
|
|
|
cgen_wb(&r1, res, wb)
|
2015-03-20 00:06:10 -04:00
|
|
|
q := Gbranch(obj.AJMP, nil, 0)
|
|
|
|
|
Patch(p, Pc)
|
cmd/internal/gc: emit write barriers at lower level
This is primarily preparation for inlining, not an optimization by itself,
but it still helps some.
name old new delta
BenchmarkBinaryTree17 18.2s × (0.99,1.01) 17.9s × (0.99,1.01) -1.57%
BenchmarkFannkuch11 4.44s × (1.00,1.00) 4.42s × (1.00,1.00) -0.40%
BenchmarkFmtFprintfEmpty 119ns × (0.95,1.02) 118ns × (0.96,1.02) ~
BenchmarkFmtFprintfString 501ns × (0.99,1.02) 486ns × (0.99,1.01) -2.89%
BenchmarkFmtFprintfInt 474ns × (0.99,1.00) 457ns × (0.99,1.01) -3.59%
BenchmarkFmtFprintfIntInt 792ns × (1.00,1.00) 768ns × (1.00,1.01) -3.03%
BenchmarkFmtFprintfPrefixedInt 574ns × (1.00,1.01) 584ns × (0.99,1.03) +1.83%
BenchmarkFmtFprintfFloat 749ns × (1.00,1.00) 739ns × (0.99,1.00) -1.34%
BenchmarkFmtManyArgs 2.94µs × (1.00,1.01) 2.77µs × (1.00,1.00) -5.76%
BenchmarkGobDecode 39.5ms × (0.99,1.01) 39.3ms × (0.99,1.01) ~
BenchmarkGobEncode 39.4ms × (1.00,1.01) 39.4ms × (0.99,1.00) ~
BenchmarkGzip 658ms × (1.00,1.01) 661ms × (0.99,1.01) ~
BenchmarkGunzip 142ms × (1.00,1.00) 142ms × (1.00,1.00) +0.22%
BenchmarkHTTPClientServer 134µs × (0.99,1.01) 133µs × (0.98,1.01) ~
BenchmarkJSONEncode 57.1ms × (0.99,1.01) 56.5ms × (0.99,1.01) ~
BenchmarkJSONDecode 141ms × (1.00,1.00) 143ms × (1.00,1.00) +1.09%
BenchmarkMandelbrot200 6.01ms × (1.00,1.00) 6.01ms × (1.00,1.00) ~
BenchmarkGoParse 10.1ms × (0.91,1.09) 9.6ms × (0.94,1.07) ~
BenchmarkRegexpMatchEasy0_32 207ns × (1.00,1.01) 210ns × (1.00,1.00) +1.45%
BenchmarkRegexpMatchEasy0_1K 592ns × (0.99,1.00) 596ns × (0.99,1.01) +0.68%
BenchmarkRegexpMatchEasy1_32 184ns × (0.99,1.01) 184ns × (0.99,1.01) ~
BenchmarkRegexpMatchEasy1_1K 1.01µs × (1.00,1.00) 1.01µs × (0.99,1.01) ~
BenchmarkRegexpMatchMedium_32 327ns × (0.99,1.00) 327ns × (1.00,1.01) ~
BenchmarkRegexpMatchMedium_1K 92.5µs × (1.00,1.00) 93.0µs × (1.00,1.02) +0.48%
BenchmarkRegexpMatchHard_32 4.79µs × (0.95,1.00) 4.76µs × (0.95,1.01) ~
BenchmarkRegexpMatchHard_1K 136µs × (1.00,1.00) 136µs × (1.00,1.01) ~
BenchmarkRevcomp 900ms × (0.99,1.01) 892ms × (1.00,1.01) ~
BenchmarkTemplate 170ms × (0.99,1.01) 175ms × (0.99,1.00) +2.95%
BenchmarkTimeParse 645ns × (1.00,1.00) 638ns × (1.00,1.00) -1.16%
BenchmarkTimeFormat 740ns × (1.00,1.00) 772ns × (1.00,1.00) +4.39%
Change-Id: I0be905e32791e0cb70ff01f169c4b309a971d981
Reviewed-on: https://go-review.googlesource.com/9159
Reviewed-by: Rick Hudson <rlh@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2015-04-17 00:25:10 -04:00
|
|
|
Regrealloc(&r2) // reclaim from above, for this failure path
|
2015-03-20 00:06:10 -04:00
|
|
|
fn := syslook("panicdottype", 0)
|
|
|
|
|
dowidth(fn.Type)
|
|
|
|
|
call := Nod(OCALLFUNC, fn, nil)
|
|
|
|
|
r1.Type = byteptr
|
|
|
|
|
r2.Type = byteptr
|
|
|
|
|
call.List = list(list(list1(&r1), &r2), typename(n.Left.Type))
|
|
|
|
|
call.List = ascompatte(OCALLFUNC, call, false, getinarg(fn.Type), call.List, 0, nil)
|
|
|
|
|
gen(call)
|
|
|
|
|
Regfree(&r1)
|
|
|
|
|
Regfree(&r2)
|
|
|
|
|
Thearch.Gins(obj.AUNDEF, nil, nil)
|
|
|
|
|
Patch(q, Pc)
|
|
|
|
|
} else {
|
|
|
|
|
// This half is handling the res, resok = x.(T) case,
|
|
|
|
|
// which is called from gen, not cgen, and is consequently fussier
|
|
|
|
|
// about blank assignments. We have to avoid calling cgen for those.
|
|
|
|
|
r1.Type = res.Type
|
|
|
|
|
if !isblank(res) {
|
cmd/internal/gc: emit write barriers at lower level
This is primarily preparation for inlining, not an optimization by itself,
but it still helps some.
name old new delta
BenchmarkBinaryTree17 18.2s × (0.99,1.01) 17.9s × (0.99,1.01) -1.57%
BenchmarkFannkuch11 4.44s × (1.00,1.00) 4.42s × (1.00,1.00) -0.40%
BenchmarkFmtFprintfEmpty 119ns × (0.95,1.02) 118ns × (0.96,1.02) ~
BenchmarkFmtFprintfString 501ns × (0.99,1.02) 486ns × (0.99,1.01) -2.89%
BenchmarkFmtFprintfInt 474ns × (0.99,1.00) 457ns × (0.99,1.01) -3.59%
BenchmarkFmtFprintfIntInt 792ns × (1.00,1.00) 768ns × (1.00,1.01) -3.03%
BenchmarkFmtFprintfPrefixedInt 574ns × (1.00,1.01) 584ns × (0.99,1.03) +1.83%
BenchmarkFmtFprintfFloat 749ns × (1.00,1.00) 739ns × (0.99,1.00) -1.34%
BenchmarkFmtManyArgs 2.94µs × (1.00,1.01) 2.77µs × (1.00,1.00) -5.76%
BenchmarkGobDecode 39.5ms × (0.99,1.01) 39.3ms × (0.99,1.01) ~
BenchmarkGobEncode 39.4ms × (1.00,1.01) 39.4ms × (0.99,1.00) ~
BenchmarkGzip 658ms × (1.00,1.01) 661ms × (0.99,1.01) ~
BenchmarkGunzip 142ms × (1.00,1.00) 142ms × (1.00,1.00) +0.22%
BenchmarkHTTPClientServer 134µs × (0.99,1.01) 133µs × (0.98,1.01) ~
BenchmarkJSONEncode 57.1ms × (0.99,1.01) 56.5ms × (0.99,1.01) ~
BenchmarkJSONDecode 141ms × (1.00,1.00) 143ms × (1.00,1.00) +1.09%
BenchmarkMandelbrot200 6.01ms × (1.00,1.00) 6.01ms × (1.00,1.00) ~
BenchmarkGoParse 10.1ms × (0.91,1.09) 9.6ms × (0.94,1.07) ~
BenchmarkRegexpMatchEasy0_32 207ns × (1.00,1.01) 210ns × (1.00,1.00) +1.45%
BenchmarkRegexpMatchEasy0_1K 592ns × (0.99,1.00) 596ns × (0.99,1.01) +0.68%
BenchmarkRegexpMatchEasy1_32 184ns × (0.99,1.01) 184ns × (0.99,1.01) ~
BenchmarkRegexpMatchEasy1_1K 1.01µs × (1.00,1.00) 1.01µs × (0.99,1.01) ~
BenchmarkRegexpMatchMedium_32 327ns × (0.99,1.00) 327ns × (1.00,1.01) ~
BenchmarkRegexpMatchMedium_1K 92.5µs × (1.00,1.00) 93.0µs × (1.00,1.02) +0.48%
BenchmarkRegexpMatchHard_32 4.79µs × (0.95,1.00) 4.76µs × (0.95,1.01) ~
BenchmarkRegexpMatchHard_1K 136µs × (1.00,1.00) 136µs × (1.00,1.01) ~
BenchmarkRevcomp 900ms × (0.99,1.01) 892ms × (1.00,1.01) ~
BenchmarkTemplate 170ms × (0.99,1.01) 175ms × (0.99,1.00) +2.95%
BenchmarkTimeParse 645ns × (1.00,1.00) 638ns × (1.00,1.00) -1.16%
BenchmarkTimeFormat 740ns × (1.00,1.00) 772ns × (1.00,1.00) +4.39%
Change-Id: I0be905e32791e0cb70ff01f169c4b309a971d981
Reviewed-on: https://go-review.googlesource.com/9159
Reviewed-by: Rick Hudson <rlh@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2015-04-17 00:25:10 -04:00
|
|
|
cgen_wb(&r1, res, wb)
|
2015-03-20 00:06:10 -04:00
|
|
|
}
|
|
|
|
|
Regfree(&r1)
|
|
|
|
|
if !isblank(resok) {
|
|
|
|
|
Cgen(Nodbool(true), resok)
|
|
|
|
|
}
|
|
|
|
|
q := Gbranch(obj.AJMP, nil, 0)
|
|
|
|
|
Patch(p, Pc)
|
|
|
|
|
if !isblank(res) {
|
|
|
|
|
n := nodnil()
|
|
|
|
|
n.Type = res.Type
|
|
|
|
|
Cgen(n, res)
|
|
|
|
|
}
|
|
|
|
|
if !isblank(resok) {
|
|
|
|
|
Cgen(Nodbool(false), resok)
|
|
|
|
|
}
|
|
|
|
|
Patch(q, Pc)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-22 09:51:12 +09:00
|
|
|
// generate:
|
|
|
|
|
// res, resok = x.(T)
|
|
|
|
|
// n.Left is x
|
|
|
|
|
// n.Type is T
|
2015-03-20 00:06:10 -04:00
|
|
|
func Cgen_As2dottype(n, res, resok *Node) {
|
|
|
|
|
if Debug_typeassert > 0 {
|
|
|
|
|
Warn("type assertion inlined")
|
|
|
|
|
}
|
|
|
|
|
// iface := n.Left
|
|
|
|
|
// r1 := iword(iface)
|
|
|
|
|
// if n.Left is non-empty interface {
|
|
|
|
|
// r1 = *r1
|
|
|
|
|
// }
|
|
|
|
|
// if r1 == T {
|
|
|
|
|
// res = idata(iface)
|
|
|
|
|
// resok = true
|
|
|
|
|
// } else {
|
|
|
|
|
// res = nil
|
|
|
|
|
// resok = false
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
var iface Node
|
|
|
|
|
Igen(n.Left, &iface, nil)
|
|
|
|
|
var r1, r2 Node
|
|
|
|
|
byteptr := Ptrto(Types[TUINT8]) // type used in runtime prototypes for runtime type (*byte)
|
|
|
|
|
Regalloc(&r1, byteptr, res)
|
|
|
|
|
iface.Type = byteptr
|
|
|
|
|
Cgen(&iface, &r1)
|
|
|
|
|
if !isnilinter(n.Left.Type) {
|
|
|
|
|
// Holding itab, want concrete type in second word.
|
2015-05-06 12:28:19 -04:00
|
|
|
p := Thearch.Ginscmp(OEQ, byteptr, &r1, Nodintconst(0), -1)
|
2015-03-20 00:06:10 -04:00
|
|
|
r2 = r1
|
|
|
|
|
r2.Op = OINDREG
|
|
|
|
|
r2.Xoffset = int64(Widthptr)
|
|
|
|
|
Cgen(&r2, &r1)
|
|
|
|
|
Patch(p, Pc)
|
|
|
|
|
}
|
|
|
|
|
Regalloc(&r2, byteptr, nil)
|
|
|
|
|
Cgen(typename(n.Type), &r2)
|
2015-05-06 12:28:19 -04:00
|
|
|
p := Thearch.Ginscmp(ONE, byteptr, &r1, &r2, -1)
|
2015-03-20 00:06:10 -04:00
|
|
|
iface.Type = n.Type
|
|
|
|
|
iface.Xoffset += int64(Widthptr)
|
|
|
|
|
Cgen(&iface, &r1)
|
|
|
|
|
if iface.Op != 0 {
|
|
|
|
|
Regfree(&iface)
|
|
|
|
|
}
|
|
|
|
|
Cgen(&r1, res)
|
|
|
|
|
q := Gbranch(obj.AJMP, nil, 0)
|
|
|
|
|
Patch(p, Pc)
|
|
|
|
|
|
|
|
|
|
fn := syslook("panicdottype", 0)
|
|
|
|
|
dowidth(fn.Type)
|
|
|
|
|
call := Nod(OCALLFUNC, fn, nil)
|
|
|
|
|
call.List = list(list(list1(&r1), &r2), typename(n.Left.Type))
|
|
|
|
|
call.List = ascompatte(OCALLFUNC, call, false, getinarg(fn.Type), call.List, 0, nil)
|
|
|
|
|
gen(call)
|
|
|
|
|
Regfree(&r1)
|
|
|
|
|
Regfree(&r2)
|
|
|
|
|
Thearch.Gins(obj.AUNDEF, nil, nil)
|
|
|
|
|
Patch(q, Pc)
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-22 09:51:12 +09:00
|
|
|
// gather series of offsets
|
|
|
|
|
// >=0 is direct addressed field
|
|
|
|
|
// <0 is pointer to next field (+1)
|
2015-02-13 14:40:36 -05:00
|
|
|
func Dotoffset(n *Node, oary []int64, nn **Node) int {
|
|
|
|
|
var i int
|
|
|
|
|
|
|
|
|
|
switch n.Op {
|
|
|
|
|
case ODOT:
|
|
|
|
|
if n.Xoffset == BADWIDTH {
|
|
|
|
|
Dump("bad width in dotoffset", n)
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("bad width in dotoffset")
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
i = Dotoffset(n.Left, oary, nn)
|
|
|
|
|
if i > 0 {
|
|
|
|
|
if oary[i-1] >= 0 {
|
|
|
|
|
oary[i-1] += n.Xoffset
|
|
|
|
|
} else {
|
|
|
|
|
oary[i-1] -= n.Xoffset
|
|
|
|
|
}
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if i < 10 {
|
|
|
|
|
oary[i] = n.Xoffset
|
|
|
|
|
i++
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case ODOTPTR:
|
|
|
|
|
if n.Xoffset == BADWIDTH {
|
|
|
|
|
Dump("bad width in dotoffset", n)
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("bad width in dotoffset")
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
i = Dotoffset(n.Left, oary, nn)
|
|
|
|
|
if i < 10 {
|
|
|
|
|
oary[i] = -(n.Xoffset + 1)
|
|
|
|
|
i++
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
*nn = n
|
|
|
|
|
return 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if i >= 10 {
|
|
|
|
|
*nn = nil
|
|
|
|
|
}
|
|
|
|
|
return i
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-22 09:51:12 +09:00
|
|
|
// make a new off the books
|
2015-02-13 14:40:36 -05:00
|
|
|
func Tempname(nn *Node, t *Type) {
|
|
|
|
|
if Curfn == nil {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("no curfn for tempname")
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-02-25 10:35:19 -08:00
|
|
|
if Curfn.Func.Closure != nil && Curfn.Op == OCLOSURE {
|
|
|
|
|
Dump("Tempname", Curfn)
|
|
|
|
|
Fatalf("adding tempname to wrong closure function")
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
if t == nil {
|
|
|
|
|
Yyerror("tempname called with nil type")
|
|
|
|
|
t = Types[TINT32]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// give each tmp a different name so that there
|
|
|
|
|
// a chance to registerizer them
|
2015-03-06 12:02:24 -08:00
|
|
|
s := Lookupf("autotmp_%.4d", statuniqgen)
|
2015-02-13 14:40:36 -05:00
|
|
|
statuniqgen++
|
2015-02-23 16:07:24 -05:00
|
|
|
n := Nod(ONAME, nil, nil)
|
2015-02-13 14:40:36 -05:00
|
|
|
n.Sym = s
|
|
|
|
|
s.Def = n
|
|
|
|
|
n.Type = t
|
|
|
|
|
n.Class = PAUTO
|
2015-04-02 19:58:37 -07:00
|
|
|
n.Addable = true
|
2015-02-13 14:40:36 -05:00
|
|
|
n.Ullman = 1
|
|
|
|
|
n.Esc = EscNever
|
2015-05-27 07:31:56 -04:00
|
|
|
n.Name.Curfn = Curfn
|
2016-02-25 10:35:19 -08:00
|
|
|
Curfn.Func.Dcl = append(Curfn.Func.Dcl, n)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
dowidth(t)
|
|
|
|
|
n.Xoffset = 0
|
|
|
|
|
*nn = *n
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func temp(t *Type) *Node {
|
2015-02-23 16:07:24 -05:00
|
|
|
n := Nod(OXXX, nil, nil)
|
2015-02-13 14:40:36 -05:00
|
|
|
Tempname(n, t)
|
2015-03-06 21:18:41 +11:00
|
|
|
n.Sym.Def.Used = true
|
2015-02-13 14:40:36 -05:00
|
|
|
return n.Orig
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func gen(n *Node) {
|
|
|
|
|
//dump("gen", n);
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
lno := setlineno(n)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-03-18 17:26:36 -04:00
|
|
|
wasregalloc := Anyregalloc()
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
if n == nil {
|
|
|
|
|
goto ret
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Ninit != nil {
|
|
|
|
|
Genlist(n.Ninit)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setlineno(n)
|
|
|
|
|
|
|
|
|
|
switch n.Op {
|
|
|
|
|
default:
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("gen: unknown op %v", Nconv(n, obj.FmtShort|obj.FmtSign))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OCASE,
|
|
|
|
|
OFALL,
|
|
|
|
|
OXCASE,
|
|
|
|
|
OXFALL,
|
|
|
|
|
ODCLCONST,
|
|
|
|
|
ODCLFUNC,
|
|
|
|
|
ODCLTYPE:
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
case OEMPTY:
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
case OBLOCK:
|
|
|
|
|
Genlist(n.List)
|
|
|
|
|
|
|
|
|
|
case OLABEL:
|
|
|
|
|
if isblanksym(n.Left.Sym) {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
lab := newlab(n)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
// if there are pending gotos, resolve them all to the current pc.
|
2015-02-23 16:07:24 -05:00
|
|
|
var p2 *obj.Prog
|
|
|
|
|
for p1 := lab.Gotopc; p1 != nil; p1 = p2 {
|
2015-02-13 14:40:36 -05:00
|
|
|
p2 = unpatch(p1)
|
|
|
|
|
Patch(p1, Pc)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lab.Gotopc = nil
|
|
|
|
|
if lab.Labelpc == nil {
|
|
|
|
|
lab.Labelpc = Pc
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-26 22:19:27 -04:00
|
|
|
if n.Name.Defn != nil {
|
|
|
|
|
switch n.Name.Defn.Op {
|
2015-02-13 14:40:36 -05:00
|
|
|
// so stmtlabel can find the label
|
2015-04-01 09:38:44 -07:00
|
|
|
case OFOR, OSWITCH, OSELECT:
|
2015-05-26 22:19:27 -04:00
|
|
|
n.Name.Defn.Sym = lab.Sym
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if label is defined, emit jump to it.
|
|
|
|
|
// otherwise save list of pending gotos in lab->gotopc.
|
|
|
|
|
// the list is linked through the normal jump target field
|
|
|
|
|
// to avoid a second list. (the jumps are actually still
|
|
|
|
|
// valid code, since they're just going to another goto
|
|
|
|
|
// to the same label. we'll unwind it when we learn the pc
|
|
|
|
|
// of the label in the OLABEL case above.)
|
|
|
|
|
case OGOTO:
|
2015-02-23 16:07:24 -05:00
|
|
|
lab := newlab(n)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
if lab.Labelpc != nil {
|
|
|
|
|
gjmp(lab.Labelpc)
|
|
|
|
|
} else {
|
|
|
|
|
lab.Gotopc = gjmp(lab.Gotopc)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case OBREAK:
|
|
|
|
|
if n.Left != nil {
|
2015-02-23 16:07:24 -05:00
|
|
|
lab := n.Left.Sym.Label
|
2015-02-13 14:40:36 -05:00
|
|
|
if lab == nil {
|
2015-04-17 12:03:22 -04:00
|
|
|
Yyerror("break label not defined: %v", n.Left.Sym)
|
2015-02-13 14:40:36 -05:00
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-07 11:11:14 +10:00
|
|
|
lab.Used = true
|
2015-02-13 14:40:36 -05:00
|
|
|
if lab.Breakpc == nil {
|
2015-04-17 12:03:22 -04:00
|
|
|
Yyerror("invalid break label %v", n.Left.Sym)
|
2015-02-13 14:40:36 -05:00
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gjmp(lab.Breakpc)
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if breakpc == nil {
|
|
|
|
|
Yyerror("break is not in a loop")
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gjmp(breakpc)
|
|
|
|
|
|
|
|
|
|
case OCONTINUE:
|
|
|
|
|
if n.Left != nil {
|
2015-02-23 16:07:24 -05:00
|
|
|
lab := n.Left.Sym.Label
|
2015-02-13 14:40:36 -05:00
|
|
|
if lab == nil {
|
2015-04-17 12:03:22 -04:00
|
|
|
Yyerror("continue label not defined: %v", n.Left.Sym)
|
2015-02-13 14:40:36 -05:00
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-07 11:11:14 +10:00
|
|
|
lab.Used = true
|
2015-02-13 14:40:36 -05:00
|
|
|
if lab.Continpc == nil {
|
2015-04-17 12:03:22 -04:00
|
|
|
Yyerror("invalid continue label %v", n.Left.Sym)
|
2015-02-13 14:40:36 -05:00
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gjmp(lab.Continpc)
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if continpc == nil {
|
|
|
|
|
Yyerror("continue is not in a loop")
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gjmp(continpc)
|
|
|
|
|
|
|
|
|
|
case OFOR:
|
2015-02-23 16:07:24 -05:00
|
|
|
sbreak := breakpc
|
|
|
|
|
p1 := gjmp(nil) // goto test
|
2015-02-13 14:40:36 -05:00
|
|
|
breakpc = gjmp(nil) // break: goto done
|
2015-02-23 16:07:24 -05:00
|
|
|
scontin := continpc
|
2015-02-13 14:40:36 -05:00
|
|
|
continpc = Pc
|
|
|
|
|
|
|
|
|
|
// define break and continue labels
|
2015-02-23 16:07:24 -05:00
|
|
|
lab := stmtlabel(n)
|
2015-02-13 14:40:36 -05:00
|
|
|
if lab != nil {
|
|
|
|
|
lab.Breakpc = breakpc
|
|
|
|
|
lab.Continpc = continpc
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-26 21:30:20 -04:00
|
|
|
gen(n.Right) // contin: incr
|
|
|
|
|
Patch(p1, Pc) // test:
|
|
|
|
|
Bgen(n.Left, false, -1, breakpc) // if(!test) goto break
|
2016-02-27 14:31:33 -08:00
|
|
|
Genslice(n.Nbody.Slice()) // body
|
2015-02-13 14:40:36 -05:00
|
|
|
gjmp(continpc)
|
|
|
|
|
Patch(breakpc, Pc) // done:
|
|
|
|
|
continpc = scontin
|
|
|
|
|
breakpc = sbreak
|
|
|
|
|
if lab != nil {
|
|
|
|
|
lab.Breakpc = nil
|
|
|
|
|
lab.Continpc = nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case OIF:
|
2015-05-26 21:30:20 -04:00
|
|
|
p1 := gjmp(nil) // goto test
|
|
|
|
|
p2 := gjmp(nil) // p2: goto else
|
|
|
|
|
Patch(p1, Pc) // test:
|
|
|
|
|
Bgen(n.Left, false, int(-n.Likely), p2) // if(!test) goto p2
|
2016-02-27 14:31:33 -08:00
|
|
|
Genslice(n.Nbody.Slice()) // then
|
2015-05-26 21:30:20 -04:00
|
|
|
p3 := gjmp(nil) // goto done
|
|
|
|
|
Patch(p2, Pc) // else:
|
|
|
|
|
Genlist(n.Rlist) // else
|
|
|
|
|
Patch(p3, Pc) // done:
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OSWITCH:
|
2015-02-23 16:07:24 -05:00
|
|
|
sbreak := breakpc
|
|
|
|
|
p1 := gjmp(nil) // goto test
|
2015-02-13 14:40:36 -05:00
|
|
|
breakpc = gjmp(nil) // break: goto done
|
|
|
|
|
|
|
|
|
|
// define break label
|
2015-02-23 16:07:24 -05:00
|
|
|
lab := stmtlabel(n)
|
2015-02-13 14:40:36 -05:00
|
|
|
if lab != nil {
|
|
|
|
|
lab.Breakpc = breakpc
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-27 14:31:33 -08:00
|
|
|
Patch(p1, Pc) // test:
|
|
|
|
|
Genslice(n.Nbody.Slice()) // switch(test) body
|
|
|
|
|
Patch(breakpc, Pc) // done:
|
2015-02-13 14:40:36 -05:00
|
|
|
breakpc = sbreak
|
|
|
|
|
if lab != nil {
|
|
|
|
|
lab.Breakpc = nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case OSELECT:
|
2015-02-23 16:07:24 -05:00
|
|
|
sbreak := breakpc
|
|
|
|
|
p1 := gjmp(nil) // goto test
|
2015-02-13 14:40:36 -05:00
|
|
|
breakpc = gjmp(nil) // break: goto done
|
|
|
|
|
|
|
|
|
|
// define break label
|
2015-02-23 16:07:24 -05:00
|
|
|
lab := stmtlabel(n)
|
2015-02-13 14:40:36 -05:00
|
|
|
if lab != nil {
|
|
|
|
|
lab.Breakpc = breakpc
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-27 14:31:33 -08:00
|
|
|
Patch(p1, Pc) // test:
|
|
|
|
|
Genslice(n.Nbody.Slice()) // select() body
|
|
|
|
|
Patch(breakpc, Pc) // done:
|
2015-02-13 14:40:36 -05:00
|
|
|
breakpc = sbreak
|
|
|
|
|
if lab != nil {
|
|
|
|
|
lab.Breakpc = nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case ODCL:
|
|
|
|
|
cgen_dcl(n.Left)
|
|
|
|
|
|
|
|
|
|
case OAS:
|
2015-07-28 10:56:39 -07:00
|
|
|
if gen_as_init(n, false) {
|
2015-02-13 14:40:36 -05:00
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
Cgen_as(n.Left, n.Right)
|
|
|
|
|
|
cmd/internal/gc: emit write barriers at lower level
This is primarily preparation for inlining, not an optimization by itself,
but it still helps some.
name old new delta
BenchmarkBinaryTree17 18.2s × (0.99,1.01) 17.9s × (0.99,1.01) -1.57%
BenchmarkFannkuch11 4.44s × (1.00,1.00) 4.42s × (1.00,1.00) -0.40%
BenchmarkFmtFprintfEmpty 119ns × (0.95,1.02) 118ns × (0.96,1.02) ~
BenchmarkFmtFprintfString 501ns × (0.99,1.02) 486ns × (0.99,1.01) -2.89%
BenchmarkFmtFprintfInt 474ns × (0.99,1.00) 457ns × (0.99,1.01) -3.59%
BenchmarkFmtFprintfIntInt 792ns × (1.00,1.00) 768ns × (1.00,1.01) -3.03%
BenchmarkFmtFprintfPrefixedInt 574ns × (1.00,1.01) 584ns × (0.99,1.03) +1.83%
BenchmarkFmtFprintfFloat 749ns × (1.00,1.00) 739ns × (0.99,1.00) -1.34%
BenchmarkFmtManyArgs 2.94µs × (1.00,1.01) 2.77µs × (1.00,1.00) -5.76%
BenchmarkGobDecode 39.5ms × (0.99,1.01) 39.3ms × (0.99,1.01) ~
BenchmarkGobEncode 39.4ms × (1.00,1.01) 39.4ms × (0.99,1.00) ~
BenchmarkGzip 658ms × (1.00,1.01) 661ms × (0.99,1.01) ~
BenchmarkGunzip 142ms × (1.00,1.00) 142ms × (1.00,1.00) +0.22%
BenchmarkHTTPClientServer 134µs × (0.99,1.01) 133µs × (0.98,1.01) ~
BenchmarkJSONEncode 57.1ms × (0.99,1.01) 56.5ms × (0.99,1.01) ~
BenchmarkJSONDecode 141ms × (1.00,1.00) 143ms × (1.00,1.00) +1.09%
BenchmarkMandelbrot200 6.01ms × (1.00,1.00) 6.01ms × (1.00,1.00) ~
BenchmarkGoParse 10.1ms × (0.91,1.09) 9.6ms × (0.94,1.07) ~
BenchmarkRegexpMatchEasy0_32 207ns × (1.00,1.01) 210ns × (1.00,1.00) +1.45%
BenchmarkRegexpMatchEasy0_1K 592ns × (0.99,1.00) 596ns × (0.99,1.01) +0.68%
BenchmarkRegexpMatchEasy1_32 184ns × (0.99,1.01) 184ns × (0.99,1.01) ~
BenchmarkRegexpMatchEasy1_1K 1.01µs × (1.00,1.00) 1.01µs × (0.99,1.01) ~
BenchmarkRegexpMatchMedium_32 327ns × (0.99,1.00) 327ns × (1.00,1.01) ~
BenchmarkRegexpMatchMedium_1K 92.5µs × (1.00,1.00) 93.0µs × (1.00,1.02) +0.48%
BenchmarkRegexpMatchHard_32 4.79µs × (0.95,1.00) 4.76µs × (0.95,1.01) ~
BenchmarkRegexpMatchHard_1K 136µs × (1.00,1.00) 136µs × (1.00,1.01) ~
BenchmarkRevcomp 900ms × (0.99,1.01) 892ms × (1.00,1.01) ~
BenchmarkTemplate 170ms × (0.99,1.01) 175ms × (0.99,1.00) +2.95%
BenchmarkTimeParse 645ns × (1.00,1.00) 638ns × (1.00,1.00) -1.16%
BenchmarkTimeFormat 740ns × (1.00,1.00) 772ns × (1.00,1.00) +4.39%
Change-Id: I0be905e32791e0cb70ff01f169c4b309a971d981
Reviewed-on: https://go-review.googlesource.com/9159
Reviewed-by: Rick Hudson <rlh@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2015-04-17 00:25:10 -04:00
|
|
|
case OASWB:
|
|
|
|
|
Cgen_as_wb(n.Left, n.Right, true)
|
|
|
|
|
|
2015-03-20 00:06:10 -04:00
|
|
|
case OAS2DOTTYPE:
|
2016-02-12 10:07:36 -08:00
|
|
|
cgen_dottype(n.Rlist.N, n.List.N, n.List.Next.N, needwritebarrier(n.List.N, n.Rlist.N))
|
2015-03-20 00:06:10 -04:00
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
case OCALLMETH:
|
2015-03-18 17:26:36 -04:00
|
|
|
cgen_callmeth(n, 0)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OCALLINTER:
|
2015-03-18 17:26:36 -04:00
|
|
|
cgen_callinter(n, nil, 0)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OCALLFUNC:
|
2015-03-18 17:26:36 -04:00
|
|
|
cgen_call(n, 0)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OPROC:
|
|
|
|
|
cgen_proc(n, 1)
|
|
|
|
|
|
|
|
|
|
case ODEFER:
|
|
|
|
|
cgen_proc(n, 2)
|
|
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case ORETURN, ORETJMP:
|
2015-03-18 17:26:36 -04:00
|
|
|
cgen_ret(n)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-04-03 12:23:28 -04:00
|
|
|
// Function calls turned into compiler intrinsics.
|
|
|
|
|
// At top level, can just ignore the call and make sure to preserve side effects in the argument, if any.
|
|
|
|
|
case OGETG:
|
|
|
|
|
// nothing
|
2015-04-01 16:02:34 -04:00
|
|
|
case OSQRT:
|
|
|
|
|
cgen_discard(n.Left)
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
case OCHECKNIL:
|
|
|
|
|
Cgen_checknil(n.Left)
|
|
|
|
|
|
|
|
|
|
case OVARKILL:
|
|
|
|
|
gvarkill(n.Left)
|
cmd/compile: recognize Syscall-like functions for liveness analysis
Consider this code:
func f(*int)
func g() {
p := new(int)
f(p)
}
where f is an assembly function.
In general liveness analysis assumes that during the call to f, p is dead
in this frame. If f has retained p, p will be found alive in f's frame and keep
the new(int) from being garbage collected. This is all correct and works.
We use the Go func declaration for f to give the assembly function
liveness information (the arguments are assumed live for the entire call).
Now consider this code:
func h1() {
p := new(int)
syscall.Syscall(1, 2, 3, uintptr(unsafe.Pointer(p)))
}
Here syscall.Syscall is taking the place of f, but because its arguments
are uintptr, the liveness analysis and the garbage collector ignore them.
Since p is no longer live in h once the call starts, if the garbage collector
scans the stack while the system call is blocked, it will find no reference
to the new(int) and reclaim it. If the kernel is going to write to *p once
the call finishes, reclaiming the memory is a mistake.
We can't change the arguments or the liveness information for
syscall.Syscall itself, both for compatibility and because sometimes the
arguments really are integers, and the garbage collector will get quite upset
if it finds an integer where it expects a pointer. The problem is that
these arguments are fundamentally untyped.
The solution we have taken in the syscall package's wrappers in past
releases is to insert a call to a dummy function named "use", to make
it look like the argument is live during the call to syscall.Syscall:
func h2() {
p := new(int)
syscall.Syscall(1, 2, 3, uintptr(unsafe.Pointer(p)))
use(unsafe.Pointer(p))
}
Keeping p alive during the call means that if the garbage collector
scans the stack during the system call now, it will find the reference to p.
Unfortunately, this approach is not available to users outside syscall,
because 'use' is unexported, and people also have to realize they need
to use it and do so. There is much existing code using syscall.Syscall
without a 'use'-like function. That code will fail very occasionally in
mysterious ways (see #13372).
This CL fixes all that existing code by making the compiler do the right
thing automatically, without any code modifications. That is, it takes h1
above, which is incorrect code today, and makes it correct code.
Specifically, if the compiler sees a foreign func definition (one
without a body) that has uintptr arguments, it marks those arguments
as "unsafe uintptrs". If it later sees the function being called
with uintptr(unsafe.Pointer(x)) as an argument, it arranges to mark x
as having escaped, and it makes sure to hold x in a live temporary
variable until the call returns, so that the garbage collector cannot
reclaim whatever heap memory x points to.
For now I am leaving the explicit calls to use in package syscall,
but they can be removed early in a future cycle (likely Go 1.7).
The rule has no effect on escape analysis, only on liveness analysis.
Fixes #13372.
Change-Id: I2addb83f70d08db08c64d394f9d06ff0a063c500
Reviewed-on: https://go-review.googlesource.com/18584
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-01-13 00:46:28 -05:00
|
|
|
|
|
|
|
|
case OVARLIVE:
|
|
|
|
|
gvarlive(n.Left)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret:
|
2015-03-18 17:26:36 -04:00
|
|
|
if Anyregalloc() != wasregalloc {
|
2015-02-13 14:40:36 -05:00
|
|
|
Dump("node", n)
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("registers left allocated")
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lineno = lno
|
|
|
|
|
}
|
|
|
|
|
|
cmd/internal/gc: emit write barriers at lower level
This is primarily preparation for inlining, not an optimization by itself,
but it still helps some.
name old new delta
BenchmarkBinaryTree17 18.2s × (0.99,1.01) 17.9s × (0.99,1.01) -1.57%
BenchmarkFannkuch11 4.44s × (1.00,1.00) 4.42s × (1.00,1.00) -0.40%
BenchmarkFmtFprintfEmpty 119ns × (0.95,1.02) 118ns × (0.96,1.02) ~
BenchmarkFmtFprintfString 501ns × (0.99,1.02) 486ns × (0.99,1.01) -2.89%
BenchmarkFmtFprintfInt 474ns × (0.99,1.00) 457ns × (0.99,1.01) -3.59%
BenchmarkFmtFprintfIntInt 792ns × (1.00,1.00) 768ns × (1.00,1.01) -3.03%
BenchmarkFmtFprintfPrefixedInt 574ns × (1.00,1.01) 584ns × (0.99,1.03) +1.83%
BenchmarkFmtFprintfFloat 749ns × (1.00,1.00) 739ns × (0.99,1.00) -1.34%
BenchmarkFmtManyArgs 2.94µs × (1.00,1.01) 2.77µs × (1.00,1.00) -5.76%
BenchmarkGobDecode 39.5ms × (0.99,1.01) 39.3ms × (0.99,1.01) ~
BenchmarkGobEncode 39.4ms × (1.00,1.01) 39.4ms × (0.99,1.00) ~
BenchmarkGzip 658ms × (1.00,1.01) 661ms × (0.99,1.01) ~
BenchmarkGunzip 142ms × (1.00,1.00) 142ms × (1.00,1.00) +0.22%
BenchmarkHTTPClientServer 134µs × (0.99,1.01) 133µs × (0.98,1.01) ~
BenchmarkJSONEncode 57.1ms × (0.99,1.01) 56.5ms × (0.99,1.01) ~
BenchmarkJSONDecode 141ms × (1.00,1.00) 143ms × (1.00,1.00) +1.09%
BenchmarkMandelbrot200 6.01ms × (1.00,1.00) 6.01ms × (1.00,1.00) ~
BenchmarkGoParse 10.1ms × (0.91,1.09) 9.6ms × (0.94,1.07) ~
BenchmarkRegexpMatchEasy0_32 207ns × (1.00,1.01) 210ns × (1.00,1.00) +1.45%
BenchmarkRegexpMatchEasy0_1K 592ns × (0.99,1.00) 596ns × (0.99,1.01) +0.68%
BenchmarkRegexpMatchEasy1_32 184ns × (0.99,1.01) 184ns × (0.99,1.01) ~
BenchmarkRegexpMatchEasy1_1K 1.01µs × (1.00,1.00) 1.01µs × (0.99,1.01) ~
BenchmarkRegexpMatchMedium_32 327ns × (0.99,1.00) 327ns × (1.00,1.01) ~
BenchmarkRegexpMatchMedium_1K 92.5µs × (1.00,1.00) 93.0µs × (1.00,1.02) +0.48%
BenchmarkRegexpMatchHard_32 4.79µs × (0.95,1.00) 4.76µs × (0.95,1.01) ~
BenchmarkRegexpMatchHard_1K 136µs × (1.00,1.00) 136µs × (1.00,1.01) ~
BenchmarkRevcomp 900ms × (0.99,1.01) 892ms × (1.00,1.01) ~
BenchmarkTemplate 170ms × (0.99,1.01) 175ms × (0.99,1.00) +2.95%
BenchmarkTimeParse 645ns × (1.00,1.00) 638ns × (1.00,1.00) -1.16%
BenchmarkTimeFormat 740ns × (1.00,1.00) 772ns × (1.00,1.00) +4.39%
Change-Id: I0be905e32791e0cb70ff01f169c4b309a971d981
Reviewed-on: https://go-review.googlesource.com/9159
Reviewed-by: Rick Hudson <rlh@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2015-04-17 00:25:10 -04:00
|
|
|
func Cgen_as(nl, nr *Node) {
|
|
|
|
|
Cgen_as_wb(nl, nr, false)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Cgen_as_wb(nl, nr *Node, wb bool) {
|
2015-02-13 14:40:36 -05:00
|
|
|
if Debug['g'] != 0 {
|
cmd/internal/gc: emit write barriers at lower level
This is primarily preparation for inlining, not an optimization by itself,
but it still helps some.
name old new delta
BenchmarkBinaryTree17 18.2s × (0.99,1.01) 17.9s × (0.99,1.01) -1.57%
BenchmarkFannkuch11 4.44s × (1.00,1.00) 4.42s × (1.00,1.00) -0.40%
BenchmarkFmtFprintfEmpty 119ns × (0.95,1.02) 118ns × (0.96,1.02) ~
BenchmarkFmtFprintfString 501ns × (0.99,1.02) 486ns × (0.99,1.01) -2.89%
BenchmarkFmtFprintfInt 474ns × (0.99,1.00) 457ns × (0.99,1.01) -3.59%
BenchmarkFmtFprintfIntInt 792ns × (1.00,1.00) 768ns × (1.00,1.01) -3.03%
BenchmarkFmtFprintfPrefixedInt 574ns × (1.00,1.01) 584ns × (0.99,1.03) +1.83%
BenchmarkFmtFprintfFloat 749ns × (1.00,1.00) 739ns × (0.99,1.00) -1.34%
BenchmarkFmtManyArgs 2.94µs × (1.00,1.01) 2.77µs × (1.00,1.00) -5.76%
BenchmarkGobDecode 39.5ms × (0.99,1.01) 39.3ms × (0.99,1.01) ~
BenchmarkGobEncode 39.4ms × (1.00,1.01) 39.4ms × (0.99,1.00) ~
BenchmarkGzip 658ms × (1.00,1.01) 661ms × (0.99,1.01) ~
BenchmarkGunzip 142ms × (1.00,1.00) 142ms × (1.00,1.00) +0.22%
BenchmarkHTTPClientServer 134µs × (0.99,1.01) 133µs × (0.98,1.01) ~
BenchmarkJSONEncode 57.1ms × (0.99,1.01) 56.5ms × (0.99,1.01) ~
BenchmarkJSONDecode 141ms × (1.00,1.00) 143ms × (1.00,1.00) +1.09%
BenchmarkMandelbrot200 6.01ms × (1.00,1.00) 6.01ms × (1.00,1.00) ~
BenchmarkGoParse 10.1ms × (0.91,1.09) 9.6ms × (0.94,1.07) ~
BenchmarkRegexpMatchEasy0_32 207ns × (1.00,1.01) 210ns × (1.00,1.00) +1.45%
BenchmarkRegexpMatchEasy0_1K 592ns × (0.99,1.00) 596ns × (0.99,1.01) +0.68%
BenchmarkRegexpMatchEasy1_32 184ns × (0.99,1.01) 184ns × (0.99,1.01) ~
BenchmarkRegexpMatchEasy1_1K 1.01µs × (1.00,1.00) 1.01µs × (0.99,1.01) ~
BenchmarkRegexpMatchMedium_32 327ns × (0.99,1.00) 327ns × (1.00,1.01) ~
BenchmarkRegexpMatchMedium_1K 92.5µs × (1.00,1.00) 93.0µs × (1.00,1.02) +0.48%
BenchmarkRegexpMatchHard_32 4.79µs × (0.95,1.00) 4.76µs × (0.95,1.01) ~
BenchmarkRegexpMatchHard_1K 136µs × (1.00,1.00) 136µs × (1.00,1.01) ~
BenchmarkRevcomp 900ms × (0.99,1.01) 892ms × (1.00,1.01) ~
BenchmarkTemplate 170ms × (0.99,1.01) 175ms × (0.99,1.00) +2.95%
BenchmarkTimeParse 645ns × (1.00,1.00) 638ns × (1.00,1.00) -1.16%
BenchmarkTimeFormat 740ns × (1.00,1.00) 772ns × (1.00,1.00) +4.39%
Change-Id: I0be905e32791e0cb70ff01f169c4b309a971d981
Reviewed-on: https://go-review.googlesource.com/9159
Reviewed-by: Rick Hudson <rlh@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2015-04-17 00:25:10 -04:00
|
|
|
op := "cgen_as"
|
|
|
|
|
if wb {
|
|
|
|
|
op = "cgen_as_wb"
|
|
|
|
|
}
|
|
|
|
|
Dump(op, nl)
|
|
|
|
|
Dump(op+" = ", nr)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for nr != nil && nr.Op == OCONVNOP {
|
|
|
|
|
nr = nr.Left
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if nl == nil || isblank(nl) {
|
|
|
|
|
cgen_discard(nr)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if nr == nil || iszero(nr) {
|
2015-02-13 14:40:36 -05:00
|
|
|
// heaps should already be clear
|
|
|
|
|
if nr == nil && (nl.Class&PHEAP != 0) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
tl := nl.Type
|
2015-02-13 14:40:36 -05:00
|
|
|
if tl == nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
2015-02-17 22:13:49 -05:00
|
|
|
if Isfat(tl) {
|
2015-02-13 14:40:36 -05:00
|
|
|
if nl.Op == ONAME {
|
|
|
|
|
Gvardef(nl)
|
|
|
|
|
}
|
|
|
|
|
Thearch.Clearfat(nl)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Clearslim(nl)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
tl := nl.Type
|
2015-02-13 14:40:36 -05:00
|
|
|
if tl == nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
cmd/internal/gc: emit write barriers at lower level
This is primarily preparation for inlining, not an optimization by itself,
but it still helps some.
name old new delta
BenchmarkBinaryTree17 18.2s × (0.99,1.01) 17.9s × (0.99,1.01) -1.57%
BenchmarkFannkuch11 4.44s × (1.00,1.00) 4.42s × (1.00,1.00) -0.40%
BenchmarkFmtFprintfEmpty 119ns × (0.95,1.02) 118ns × (0.96,1.02) ~
BenchmarkFmtFprintfString 501ns × (0.99,1.02) 486ns × (0.99,1.01) -2.89%
BenchmarkFmtFprintfInt 474ns × (0.99,1.00) 457ns × (0.99,1.01) -3.59%
BenchmarkFmtFprintfIntInt 792ns × (1.00,1.00) 768ns × (1.00,1.01) -3.03%
BenchmarkFmtFprintfPrefixedInt 574ns × (1.00,1.01) 584ns × (0.99,1.03) +1.83%
BenchmarkFmtFprintfFloat 749ns × (1.00,1.00) 739ns × (0.99,1.00) -1.34%
BenchmarkFmtManyArgs 2.94µs × (1.00,1.01) 2.77µs × (1.00,1.00) -5.76%
BenchmarkGobDecode 39.5ms × (0.99,1.01) 39.3ms × (0.99,1.01) ~
BenchmarkGobEncode 39.4ms × (1.00,1.01) 39.4ms × (0.99,1.00) ~
BenchmarkGzip 658ms × (1.00,1.01) 661ms × (0.99,1.01) ~
BenchmarkGunzip 142ms × (1.00,1.00) 142ms × (1.00,1.00) +0.22%
BenchmarkHTTPClientServer 134µs × (0.99,1.01) 133µs × (0.98,1.01) ~
BenchmarkJSONEncode 57.1ms × (0.99,1.01) 56.5ms × (0.99,1.01) ~
BenchmarkJSONDecode 141ms × (1.00,1.00) 143ms × (1.00,1.00) +1.09%
BenchmarkMandelbrot200 6.01ms × (1.00,1.00) 6.01ms × (1.00,1.00) ~
BenchmarkGoParse 10.1ms × (0.91,1.09) 9.6ms × (0.94,1.07) ~
BenchmarkRegexpMatchEasy0_32 207ns × (1.00,1.01) 210ns × (1.00,1.00) +1.45%
BenchmarkRegexpMatchEasy0_1K 592ns × (0.99,1.00) 596ns × (0.99,1.01) +0.68%
BenchmarkRegexpMatchEasy1_32 184ns × (0.99,1.01) 184ns × (0.99,1.01) ~
BenchmarkRegexpMatchEasy1_1K 1.01µs × (1.00,1.00) 1.01µs × (0.99,1.01) ~
BenchmarkRegexpMatchMedium_32 327ns × (0.99,1.00) 327ns × (1.00,1.01) ~
BenchmarkRegexpMatchMedium_1K 92.5µs × (1.00,1.00) 93.0µs × (1.00,1.02) +0.48%
BenchmarkRegexpMatchHard_32 4.79µs × (0.95,1.00) 4.76µs × (0.95,1.01) ~
BenchmarkRegexpMatchHard_1K 136µs × (1.00,1.00) 136µs × (1.00,1.01) ~
BenchmarkRevcomp 900ms × (0.99,1.01) 892ms × (1.00,1.01) ~
BenchmarkTemplate 170ms × (0.99,1.01) 175ms × (0.99,1.00) +2.95%
BenchmarkTimeParse 645ns × (1.00,1.00) 638ns × (1.00,1.00) -1.16%
BenchmarkTimeFormat 740ns × (1.00,1.00) 772ns × (1.00,1.00) +4.39%
Change-Id: I0be905e32791e0cb70ff01f169c4b309a971d981
Reviewed-on: https://go-review.googlesource.com/9159
Reviewed-by: Rick Hudson <rlh@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2015-04-17 00:25:10 -04:00
|
|
|
cgen_wb(nr, nl, wb)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-03-18 17:26:36 -04:00
|
|
|
func cgen_callmeth(n *Node, proc int) {
|
2015-02-13 14:40:36 -05:00
|
|
|
// generate a rewrite in n2 for the method call
|
|
|
|
|
// (p.f)(...) goes to (f)(p,...)
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
l := n.Left
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
if l.Op != ODOTMETH {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("cgen_callmeth: not dotmethod: %v", l)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
n2 := *n
|
2015-02-13 14:40:36 -05:00
|
|
|
n2.Op = OCALLFUNC
|
|
|
|
|
n2.Left = l.Right
|
|
|
|
|
n2.Left.Type = l.Type
|
|
|
|
|
|
|
|
|
|
if n2.Left.Op == ONAME {
|
|
|
|
|
n2.Left.Class = PFUNC
|
|
|
|
|
}
|
2015-03-18 17:26:36 -04:00
|
|
|
cgen_call(&n2, proc)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-04-06 19:36:36 -07:00
|
|
|
// CgenTemp creates a temporary node, assigns n to it, and returns it.
|
|
|
|
|
func CgenTemp(n *Node) *Node {
|
|
|
|
|
var tmp Node
|
|
|
|
|
Tempname(&tmp, n.Type)
|
|
|
|
|
Cgen(n, &tmp)
|
|
|
|
|
return &tmp
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
func checklabels() {
|
2015-02-23 16:07:24 -05:00
|
|
|
for lab := labellist; lab != nil; lab = lab.Link {
|
2015-02-13 14:40:36 -05:00
|
|
|
if lab.Def == nil {
|
2015-08-30 22:24:53 +02:00
|
|
|
for _, n := range lab.Use {
|
2016-03-02 11:01:25 -08:00
|
|
|
yyerrorl(n.Lineno, "label %v not defined", lab.Sym)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-07 11:11:14 +10:00
|
|
|
if lab.Use == nil && !lab.Used {
|
2016-03-02 11:01:25 -08:00
|
|
|
yyerrorl(lab.Def.Lineno, "label %v defined and not used", lab.Sym)
|
2015-02-13 14:40:36 -05:00
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if lab.Gotopc != nil {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("label %v never resolved", lab.Sym)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-08-30 22:24:53 +02:00
|
|
|
for _, n := range lab.Use {
|
|
|
|
|
checkgoto(n, lab.Def)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-03-18 12:29:40 -04:00
|
|
|
|
2015-04-09 20:10:16 +10:00
|
|
|
// Componentgen copies a composite value by moving its individual components.
|
|
|
|
|
// Slices, strings and interfaces are supported. Small structs or arrays with
|
|
|
|
|
// elements of basic type are also supported.
|
|
|
|
|
// nr is nil when assigning a zero value.
|
cmd/internal/gc: emit write barriers at lower level
This is primarily preparation for inlining, not an optimization by itself,
but it still helps some.
name old new delta
BenchmarkBinaryTree17 18.2s × (0.99,1.01) 17.9s × (0.99,1.01) -1.57%
BenchmarkFannkuch11 4.44s × (1.00,1.00) 4.42s × (1.00,1.00) -0.40%
BenchmarkFmtFprintfEmpty 119ns × (0.95,1.02) 118ns × (0.96,1.02) ~
BenchmarkFmtFprintfString 501ns × (0.99,1.02) 486ns × (0.99,1.01) -2.89%
BenchmarkFmtFprintfInt 474ns × (0.99,1.00) 457ns × (0.99,1.01) -3.59%
BenchmarkFmtFprintfIntInt 792ns × (1.00,1.00) 768ns × (1.00,1.01) -3.03%
BenchmarkFmtFprintfPrefixedInt 574ns × (1.00,1.01) 584ns × (0.99,1.03) +1.83%
BenchmarkFmtFprintfFloat 749ns × (1.00,1.00) 739ns × (0.99,1.00) -1.34%
BenchmarkFmtManyArgs 2.94µs × (1.00,1.01) 2.77µs × (1.00,1.00) -5.76%
BenchmarkGobDecode 39.5ms × (0.99,1.01) 39.3ms × (0.99,1.01) ~
BenchmarkGobEncode 39.4ms × (1.00,1.01) 39.4ms × (0.99,1.00) ~
BenchmarkGzip 658ms × (1.00,1.01) 661ms × (0.99,1.01) ~
BenchmarkGunzip 142ms × (1.00,1.00) 142ms × (1.00,1.00) +0.22%
BenchmarkHTTPClientServer 134µs × (0.99,1.01) 133µs × (0.98,1.01) ~
BenchmarkJSONEncode 57.1ms × (0.99,1.01) 56.5ms × (0.99,1.01) ~
BenchmarkJSONDecode 141ms × (1.00,1.00) 143ms × (1.00,1.00) +1.09%
BenchmarkMandelbrot200 6.01ms × (1.00,1.00) 6.01ms × (1.00,1.00) ~
BenchmarkGoParse 10.1ms × (0.91,1.09) 9.6ms × (0.94,1.07) ~
BenchmarkRegexpMatchEasy0_32 207ns × (1.00,1.01) 210ns × (1.00,1.00) +1.45%
BenchmarkRegexpMatchEasy0_1K 592ns × (0.99,1.00) 596ns × (0.99,1.01) +0.68%
BenchmarkRegexpMatchEasy1_32 184ns × (0.99,1.01) 184ns × (0.99,1.01) ~
BenchmarkRegexpMatchEasy1_1K 1.01µs × (1.00,1.00) 1.01µs × (0.99,1.01) ~
BenchmarkRegexpMatchMedium_32 327ns × (0.99,1.00) 327ns × (1.00,1.01) ~
BenchmarkRegexpMatchMedium_1K 92.5µs × (1.00,1.00) 93.0µs × (1.00,1.02) +0.48%
BenchmarkRegexpMatchHard_32 4.79µs × (0.95,1.00) 4.76µs × (0.95,1.01) ~
BenchmarkRegexpMatchHard_1K 136µs × (1.00,1.00) 136µs × (1.00,1.01) ~
BenchmarkRevcomp 900ms × (0.99,1.01) 892ms × (1.00,1.01) ~
BenchmarkTemplate 170ms × (0.99,1.01) 175ms × (0.99,1.00) +2.95%
BenchmarkTimeParse 645ns × (1.00,1.00) 638ns × (1.00,1.00) -1.16%
BenchmarkTimeFormat 740ns × (1.00,1.00) 772ns × (1.00,1.00) +4.39%
Change-Id: I0be905e32791e0cb70ff01f169c4b309a971d981
Reviewed-on: https://go-review.googlesource.com/9159
Reviewed-by: Rick Hudson <rlh@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2015-04-17 00:25:10 -04:00
|
|
|
func Componentgen(nr, nl *Node) bool {
|
|
|
|
|
return componentgen_wb(nr, nl, false)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// componentgen_wb is like componentgen but if wb==true emits write barriers for pointer updates.
|
|
|
|
|
func componentgen_wb(nr, nl *Node, wb bool) bool {
|
|
|
|
|
// Don't generate any code for complete copy of a variable into itself.
|
|
|
|
|
// It's useless, and the VARDEF will incorrectly mark the old value as dead.
|
|
|
|
|
// (This check assumes that the arguments passed to componentgen did not
|
|
|
|
|
// themselves come from Igen, or else we could have Op==ONAME but
|
|
|
|
|
// with a Type and Xoffset describing an individual field, not the entire
|
|
|
|
|
// variable.)
|
|
|
|
|
if nl.Op == ONAME && nl == nr {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-16 16:22:30 -04:00
|
|
|
// Count number of moves required to move components.
|
cmd/internal/gc: emit write barriers at lower level
This is primarily preparation for inlining, not an optimization by itself,
but it still helps some.
name old new delta
BenchmarkBinaryTree17 18.2s × (0.99,1.01) 17.9s × (0.99,1.01) -1.57%
BenchmarkFannkuch11 4.44s × (1.00,1.00) 4.42s × (1.00,1.00) -0.40%
BenchmarkFmtFprintfEmpty 119ns × (0.95,1.02) 118ns × (0.96,1.02) ~
BenchmarkFmtFprintfString 501ns × (0.99,1.02) 486ns × (0.99,1.01) -2.89%
BenchmarkFmtFprintfInt 474ns × (0.99,1.00) 457ns × (0.99,1.01) -3.59%
BenchmarkFmtFprintfIntInt 792ns × (1.00,1.00) 768ns × (1.00,1.01) -3.03%
BenchmarkFmtFprintfPrefixedInt 574ns × (1.00,1.01) 584ns × (0.99,1.03) +1.83%
BenchmarkFmtFprintfFloat 749ns × (1.00,1.00) 739ns × (0.99,1.00) -1.34%
BenchmarkFmtManyArgs 2.94µs × (1.00,1.01) 2.77µs × (1.00,1.00) -5.76%
BenchmarkGobDecode 39.5ms × (0.99,1.01) 39.3ms × (0.99,1.01) ~
BenchmarkGobEncode 39.4ms × (1.00,1.01) 39.4ms × (0.99,1.00) ~
BenchmarkGzip 658ms × (1.00,1.01) 661ms × (0.99,1.01) ~
BenchmarkGunzip 142ms × (1.00,1.00) 142ms × (1.00,1.00) +0.22%
BenchmarkHTTPClientServer 134µs × (0.99,1.01) 133µs × (0.98,1.01) ~
BenchmarkJSONEncode 57.1ms × (0.99,1.01) 56.5ms × (0.99,1.01) ~
BenchmarkJSONDecode 141ms × (1.00,1.00) 143ms × (1.00,1.00) +1.09%
BenchmarkMandelbrot200 6.01ms × (1.00,1.00) 6.01ms × (1.00,1.00) ~
BenchmarkGoParse 10.1ms × (0.91,1.09) 9.6ms × (0.94,1.07) ~
BenchmarkRegexpMatchEasy0_32 207ns × (1.00,1.01) 210ns × (1.00,1.00) +1.45%
BenchmarkRegexpMatchEasy0_1K 592ns × (0.99,1.00) 596ns × (0.99,1.01) +0.68%
BenchmarkRegexpMatchEasy1_32 184ns × (0.99,1.01) 184ns × (0.99,1.01) ~
BenchmarkRegexpMatchEasy1_1K 1.01µs × (1.00,1.00) 1.01µs × (0.99,1.01) ~
BenchmarkRegexpMatchMedium_32 327ns × (0.99,1.00) 327ns × (1.00,1.01) ~
BenchmarkRegexpMatchMedium_1K 92.5µs × (1.00,1.00) 93.0µs × (1.00,1.02) +0.48%
BenchmarkRegexpMatchHard_32 4.79µs × (0.95,1.00) 4.76µs × (0.95,1.01) ~
BenchmarkRegexpMatchHard_1K 136µs × (1.00,1.00) 136µs × (1.00,1.01) ~
BenchmarkRevcomp 900ms × (0.99,1.01) 892ms × (1.00,1.01) ~
BenchmarkTemplate 170ms × (0.99,1.01) 175ms × (0.99,1.00) +2.95%
BenchmarkTimeParse 645ns × (1.00,1.00) 638ns × (1.00,1.00) -1.16%
BenchmarkTimeFormat 740ns × (1.00,1.00) 772ns × (1.00,1.00) +4.39%
Change-Id: I0be905e32791e0cb70ff01f169c4b309a971d981
Reviewed-on: https://go-review.googlesource.com/9159
Reviewed-by: Rick Hudson <rlh@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2015-04-17 00:25:10 -04:00
|
|
|
// If using write barrier, can only emit one pointer.
|
|
|
|
|
// TODO(rsc): Allow more pointers, for reflect.Value.
|
2015-04-16 16:22:30 -04:00
|
|
|
const maxMoves = 8
|
|
|
|
|
n := 0
|
cmd/internal/gc: emit write barriers at lower level
This is primarily preparation for inlining, not an optimization by itself,
but it still helps some.
name old new delta
BenchmarkBinaryTree17 18.2s × (0.99,1.01) 17.9s × (0.99,1.01) -1.57%
BenchmarkFannkuch11 4.44s × (1.00,1.00) 4.42s × (1.00,1.00) -0.40%
BenchmarkFmtFprintfEmpty 119ns × (0.95,1.02) 118ns × (0.96,1.02) ~
BenchmarkFmtFprintfString 501ns × (0.99,1.02) 486ns × (0.99,1.01) -2.89%
BenchmarkFmtFprintfInt 474ns × (0.99,1.00) 457ns × (0.99,1.01) -3.59%
BenchmarkFmtFprintfIntInt 792ns × (1.00,1.00) 768ns × (1.00,1.01) -3.03%
BenchmarkFmtFprintfPrefixedInt 574ns × (1.00,1.01) 584ns × (0.99,1.03) +1.83%
BenchmarkFmtFprintfFloat 749ns × (1.00,1.00) 739ns × (0.99,1.00) -1.34%
BenchmarkFmtManyArgs 2.94µs × (1.00,1.01) 2.77µs × (1.00,1.00) -5.76%
BenchmarkGobDecode 39.5ms × (0.99,1.01) 39.3ms × (0.99,1.01) ~
BenchmarkGobEncode 39.4ms × (1.00,1.01) 39.4ms × (0.99,1.00) ~
BenchmarkGzip 658ms × (1.00,1.01) 661ms × (0.99,1.01) ~
BenchmarkGunzip 142ms × (1.00,1.00) 142ms × (1.00,1.00) +0.22%
BenchmarkHTTPClientServer 134µs × (0.99,1.01) 133µs × (0.98,1.01) ~
BenchmarkJSONEncode 57.1ms × (0.99,1.01) 56.5ms × (0.99,1.01) ~
BenchmarkJSONDecode 141ms × (1.00,1.00) 143ms × (1.00,1.00) +1.09%
BenchmarkMandelbrot200 6.01ms × (1.00,1.00) 6.01ms × (1.00,1.00) ~
BenchmarkGoParse 10.1ms × (0.91,1.09) 9.6ms × (0.94,1.07) ~
BenchmarkRegexpMatchEasy0_32 207ns × (1.00,1.01) 210ns × (1.00,1.00) +1.45%
BenchmarkRegexpMatchEasy0_1K 592ns × (0.99,1.00) 596ns × (0.99,1.01) +0.68%
BenchmarkRegexpMatchEasy1_32 184ns × (0.99,1.01) 184ns × (0.99,1.01) ~
BenchmarkRegexpMatchEasy1_1K 1.01µs × (1.00,1.00) 1.01µs × (0.99,1.01) ~
BenchmarkRegexpMatchMedium_32 327ns × (0.99,1.00) 327ns × (1.00,1.01) ~
BenchmarkRegexpMatchMedium_1K 92.5µs × (1.00,1.00) 93.0µs × (1.00,1.02) +0.48%
BenchmarkRegexpMatchHard_32 4.79µs × (0.95,1.00) 4.76µs × (0.95,1.01) ~
BenchmarkRegexpMatchHard_1K 136µs × (1.00,1.00) 136µs × (1.00,1.01) ~
BenchmarkRevcomp 900ms × (0.99,1.01) 892ms × (1.00,1.01) ~
BenchmarkTemplate 170ms × (0.99,1.01) 175ms × (0.99,1.00) +2.95%
BenchmarkTimeParse 645ns × (1.00,1.00) 638ns × (1.00,1.00) -1.16%
BenchmarkTimeFormat 740ns × (1.00,1.00) 772ns × (1.00,1.00) +4.39%
Change-Id: I0be905e32791e0cb70ff01f169c4b309a971d981
Reviewed-on: https://go-review.googlesource.com/9159
Reviewed-by: Rick Hudson <rlh@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2015-04-17 00:25:10 -04:00
|
|
|
numPtr := 0
|
2015-04-16 16:22:30 -04:00
|
|
|
visitComponents(nl.Type, 0, func(t *Type, offset int64) bool {
|
|
|
|
|
n++
|
2015-09-24 23:21:18 +02:00
|
|
|
if Simtype[t.Etype] == Tptr && t != itable {
|
cmd/internal/gc: emit write barriers at lower level
This is primarily preparation for inlining, not an optimization by itself,
but it still helps some.
name old new delta
BenchmarkBinaryTree17 18.2s × (0.99,1.01) 17.9s × (0.99,1.01) -1.57%
BenchmarkFannkuch11 4.44s × (1.00,1.00) 4.42s × (1.00,1.00) -0.40%
BenchmarkFmtFprintfEmpty 119ns × (0.95,1.02) 118ns × (0.96,1.02) ~
BenchmarkFmtFprintfString 501ns × (0.99,1.02) 486ns × (0.99,1.01) -2.89%
BenchmarkFmtFprintfInt 474ns × (0.99,1.00) 457ns × (0.99,1.01) -3.59%
BenchmarkFmtFprintfIntInt 792ns × (1.00,1.00) 768ns × (1.00,1.01) -3.03%
BenchmarkFmtFprintfPrefixedInt 574ns × (1.00,1.01) 584ns × (0.99,1.03) +1.83%
BenchmarkFmtFprintfFloat 749ns × (1.00,1.00) 739ns × (0.99,1.00) -1.34%
BenchmarkFmtManyArgs 2.94µs × (1.00,1.01) 2.77µs × (1.00,1.00) -5.76%
BenchmarkGobDecode 39.5ms × (0.99,1.01) 39.3ms × (0.99,1.01) ~
BenchmarkGobEncode 39.4ms × (1.00,1.01) 39.4ms × (0.99,1.00) ~
BenchmarkGzip 658ms × (1.00,1.01) 661ms × (0.99,1.01) ~
BenchmarkGunzip 142ms × (1.00,1.00) 142ms × (1.00,1.00) +0.22%
BenchmarkHTTPClientServer 134µs × (0.99,1.01) 133µs × (0.98,1.01) ~
BenchmarkJSONEncode 57.1ms × (0.99,1.01) 56.5ms × (0.99,1.01) ~
BenchmarkJSONDecode 141ms × (1.00,1.00) 143ms × (1.00,1.00) +1.09%
BenchmarkMandelbrot200 6.01ms × (1.00,1.00) 6.01ms × (1.00,1.00) ~
BenchmarkGoParse 10.1ms × (0.91,1.09) 9.6ms × (0.94,1.07) ~
BenchmarkRegexpMatchEasy0_32 207ns × (1.00,1.01) 210ns × (1.00,1.00) +1.45%
BenchmarkRegexpMatchEasy0_1K 592ns × (0.99,1.00) 596ns × (0.99,1.01) +0.68%
BenchmarkRegexpMatchEasy1_32 184ns × (0.99,1.01) 184ns × (0.99,1.01) ~
BenchmarkRegexpMatchEasy1_1K 1.01µs × (1.00,1.00) 1.01µs × (0.99,1.01) ~
BenchmarkRegexpMatchMedium_32 327ns × (0.99,1.00) 327ns × (1.00,1.01) ~
BenchmarkRegexpMatchMedium_1K 92.5µs × (1.00,1.00) 93.0µs × (1.00,1.02) +0.48%
BenchmarkRegexpMatchHard_32 4.79µs × (0.95,1.00) 4.76µs × (0.95,1.01) ~
BenchmarkRegexpMatchHard_1K 136µs × (1.00,1.00) 136µs × (1.00,1.01) ~
BenchmarkRevcomp 900ms × (0.99,1.01) 892ms × (1.00,1.01) ~
BenchmarkTemplate 170ms × (0.99,1.01) 175ms × (0.99,1.00) +2.95%
BenchmarkTimeParse 645ns × (1.00,1.00) 638ns × (1.00,1.00) -1.16%
BenchmarkTimeFormat 740ns × (1.00,1.00) 772ns × (1.00,1.00) +4.39%
Change-Id: I0be905e32791e0cb70ff01f169c4b309a971d981
Reviewed-on: https://go-review.googlesource.com/9159
Reviewed-by: Rick Hudson <rlh@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2015-04-17 00:25:10 -04:00
|
|
|
numPtr++
|
|
|
|
|
}
|
|
|
|
|
return n <= maxMoves && (!wb || numPtr <= 1)
|
2015-04-16 16:22:30 -04:00
|
|
|
})
|
cmd/internal/gc: emit write barriers at lower level
This is primarily preparation for inlining, not an optimization by itself,
but it still helps some.
name old new delta
BenchmarkBinaryTree17 18.2s × (0.99,1.01) 17.9s × (0.99,1.01) -1.57%
BenchmarkFannkuch11 4.44s × (1.00,1.00) 4.42s × (1.00,1.00) -0.40%
BenchmarkFmtFprintfEmpty 119ns × (0.95,1.02) 118ns × (0.96,1.02) ~
BenchmarkFmtFprintfString 501ns × (0.99,1.02) 486ns × (0.99,1.01) -2.89%
BenchmarkFmtFprintfInt 474ns × (0.99,1.00) 457ns × (0.99,1.01) -3.59%
BenchmarkFmtFprintfIntInt 792ns × (1.00,1.00) 768ns × (1.00,1.01) -3.03%
BenchmarkFmtFprintfPrefixedInt 574ns × (1.00,1.01) 584ns × (0.99,1.03) +1.83%
BenchmarkFmtFprintfFloat 749ns × (1.00,1.00) 739ns × (0.99,1.00) -1.34%
BenchmarkFmtManyArgs 2.94µs × (1.00,1.01) 2.77µs × (1.00,1.00) -5.76%
BenchmarkGobDecode 39.5ms × (0.99,1.01) 39.3ms × (0.99,1.01) ~
BenchmarkGobEncode 39.4ms × (1.00,1.01) 39.4ms × (0.99,1.00) ~
BenchmarkGzip 658ms × (1.00,1.01) 661ms × (0.99,1.01) ~
BenchmarkGunzip 142ms × (1.00,1.00) 142ms × (1.00,1.00) +0.22%
BenchmarkHTTPClientServer 134µs × (0.99,1.01) 133µs × (0.98,1.01) ~
BenchmarkJSONEncode 57.1ms × (0.99,1.01) 56.5ms × (0.99,1.01) ~
BenchmarkJSONDecode 141ms × (1.00,1.00) 143ms × (1.00,1.00) +1.09%
BenchmarkMandelbrot200 6.01ms × (1.00,1.00) 6.01ms × (1.00,1.00) ~
BenchmarkGoParse 10.1ms × (0.91,1.09) 9.6ms × (0.94,1.07) ~
BenchmarkRegexpMatchEasy0_32 207ns × (1.00,1.01) 210ns × (1.00,1.00) +1.45%
BenchmarkRegexpMatchEasy0_1K 592ns × (0.99,1.00) 596ns × (0.99,1.01) +0.68%
BenchmarkRegexpMatchEasy1_32 184ns × (0.99,1.01) 184ns × (0.99,1.01) ~
BenchmarkRegexpMatchEasy1_1K 1.01µs × (1.00,1.00) 1.01µs × (0.99,1.01) ~
BenchmarkRegexpMatchMedium_32 327ns × (0.99,1.00) 327ns × (1.00,1.01) ~
BenchmarkRegexpMatchMedium_1K 92.5µs × (1.00,1.00) 93.0µs × (1.00,1.02) +0.48%
BenchmarkRegexpMatchHard_32 4.79µs × (0.95,1.00) 4.76µs × (0.95,1.01) ~
BenchmarkRegexpMatchHard_1K 136µs × (1.00,1.00) 136µs × (1.00,1.01) ~
BenchmarkRevcomp 900ms × (0.99,1.01) 892ms × (1.00,1.01) ~
BenchmarkTemplate 170ms × (0.99,1.01) 175ms × (0.99,1.00) +2.95%
BenchmarkTimeParse 645ns × (1.00,1.00) 638ns × (1.00,1.00) -1.16%
BenchmarkTimeFormat 740ns × (1.00,1.00) 772ns × (1.00,1.00) +4.39%
Change-Id: I0be905e32791e0cb70ff01f169c4b309a971d981
Reviewed-on: https://go-review.googlesource.com/9159
Reviewed-by: Rick Hudson <rlh@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2015-04-17 00:25:10 -04:00
|
|
|
if n > maxMoves || wb && numPtr > 1 {
|
2015-04-09 20:10:16 +10:00
|
|
|
return false
|
2015-03-18 12:29:40 -04:00
|
|
|
}
|
|
|
|
|
|
cmd/internal/gc: emit write barriers at lower level
This is primarily preparation for inlining, not an optimization by itself,
but it still helps some.
name old new delta
BenchmarkBinaryTree17 18.2s × (0.99,1.01) 17.9s × (0.99,1.01) -1.57%
BenchmarkFannkuch11 4.44s × (1.00,1.00) 4.42s × (1.00,1.00) -0.40%
BenchmarkFmtFprintfEmpty 119ns × (0.95,1.02) 118ns × (0.96,1.02) ~
BenchmarkFmtFprintfString 501ns × (0.99,1.02) 486ns × (0.99,1.01) -2.89%
BenchmarkFmtFprintfInt 474ns × (0.99,1.00) 457ns × (0.99,1.01) -3.59%
BenchmarkFmtFprintfIntInt 792ns × (1.00,1.00) 768ns × (1.00,1.01) -3.03%
BenchmarkFmtFprintfPrefixedInt 574ns × (1.00,1.01) 584ns × (0.99,1.03) +1.83%
BenchmarkFmtFprintfFloat 749ns × (1.00,1.00) 739ns × (0.99,1.00) -1.34%
BenchmarkFmtManyArgs 2.94µs × (1.00,1.01) 2.77µs × (1.00,1.00) -5.76%
BenchmarkGobDecode 39.5ms × (0.99,1.01) 39.3ms × (0.99,1.01) ~
BenchmarkGobEncode 39.4ms × (1.00,1.01) 39.4ms × (0.99,1.00) ~
BenchmarkGzip 658ms × (1.00,1.01) 661ms × (0.99,1.01) ~
BenchmarkGunzip 142ms × (1.00,1.00) 142ms × (1.00,1.00) +0.22%
BenchmarkHTTPClientServer 134µs × (0.99,1.01) 133µs × (0.98,1.01) ~
BenchmarkJSONEncode 57.1ms × (0.99,1.01) 56.5ms × (0.99,1.01) ~
BenchmarkJSONDecode 141ms × (1.00,1.00) 143ms × (1.00,1.00) +1.09%
BenchmarkMandelbrot200 6.01ms × (1.00,1.00) 6.01ms × (1.00,1.00) ~
BenchmarkGoParse 10.1ms × (0.91,1.09) 9.6ms × (0.94,1.07) ~
BenchmarkRegexpMatchEasy0_32 207ns × (1.00,1.01) 210ns × (1.00,1.00) +1.45%
BenchmarkRegexpMatchEasy0_1K 592ns × (0.99,1.00) 596ns × (0.99,1.01) +0.68%
BenchmarkRegexpMatchEasy1_32 184ns × (0.99,1.01) 184ns × (0.99,1.01) ~
BenchmarkRegexpMatchEasy1_1K 1.01µs × (1.00,1.00) 1.01µs × (0.99,1.01) ~
BenchmarkRegexpMatchMedium_32 327ns × (0.99,1.00) 327ns × (1.00,1.01) ~
BenchmarkRegexpMatchMedium_1K 92.5µs × (1.00,1.00) 93.0µs × (1.00,1.02) +0.48%
BenchmarkRegexpMatchHard_32 4.79µs × (0.95,1.00) 4.76µs × (0.95,1.01) ~
BenchmarkRegexpMatchHard_1K 136µs × (1.00,1.00) 136µs × (1.00,1.01) ~
BenchmarkRevcomp 900ms × (0.99,1.01) 892ms × (1.00,1.01) ~
BenchmarkTemplate 170ms × (0.99,1.01) 175ms × (0.99,1.00) +2.95%
BenchmarkTimeParse 645ns × (1.00,1.00) 638ns × (1.00,1.00) -1.16%
BenchmarkTimeFormat 740ns × (1.00,1.00) 772ns × (1.00,1.00) +4.39%
Change-Id: I0be905e32791e0cb70ff01f169c4b309a971d981
Reviewed-on: https://go-review.googlesource.com/9159
Reviewed-by: Rick Hudson <rlh@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2015-04-17 00:25:10 -04:00
|
|
|
// Must call emitVardef after evaluating rhs but before writing to lhs.
|
2015-04-16 16:22:30 -04:00
|
|
|
emitVardef := func() {
|
|
|
|
|
// Emit vardef if needed.
|
|
|
|
|
if nl.Op == ONAME {
|
|
|
|
|
switch nl.Type.Etype {
|
|
|
|
|
case TARRAY, TSTRING, TINTER, TSTRUCT:
|
|
|
|
|
Gvardef(nl)
|
|
|
|
|
}
|
2015-03-18 12:29:40 -04:00
|
|
|
}
|
2015-04-16 16:22:30 -04:00
|
|
|
}
|
|
|
|
|
|
cmd/internal/gc: emit write barriers at lower level
This is primarily preparation for inlining, not an optimization by itself,
but it still helps some.
name old new delta
BenchmarkBinaryTree17 18.2s × (0.99,1.01) 17.9s × (0.99,1.01) -1.57%
BenchmarkFannkuch11 4.44s × (1.00,1.00) 4.42s × (1.00,1.00) -0.40%
BenchmarkFmtFprintfEmpty 119ns × (0.95,1.02) 118ns × (0.96,1.02) ~
BenchmarkFmtFprintfString 501ns × (0.99,1.02) 486ns × (0.99,1.01) -2.89%
BenchmarkFmtFprintfInt 474ns × (0.99,1.00) 457ns × (0.99,1.01) -3.59%
BenchmarkFmtFprintfIntInt 792ns × (1.00,1.00) 768ns × (1.00,1.01) -3.03%
BenchmarkFmtFprintfPrefixedInt 574ns × (1.00,1.01) 584ns × (0.99,1.03) +1.83%
BenchmarkFmtFprintfFloat 749ns × (1.00,1.00) 739ns × (0.99,1.00) -1.34%
BenchmarkFmtManyArgs 2.94µs × (1.00,1.01) 2.77µs × (1.00,1.00) -5.76%
BenchmarkGobDecode 39.5ms × (0.99,1.01) 39.3ms × (0.99,1.01) ~
BenchmarkGobEncode 39.4ms × (1.00,1.01) 39.4ms × (0.99,1.00) ~
BenchmarkGzip 658ms × (1.00,1.01) 661ms × (0.99,1.01) ~
BenchmarkGunzip 142ms × (1.00,1.00) 142ms × (1.00,1.00) +0.22%
BenchmarkHTTPClientServer 134µs × (0.99,1.01) 133µs × (0.98,1.01) ~
BenchmarkJSONEncode 57.1ms × (0.99,1.01) 56.5ms × (0.99,1.01) ~
BenchmarkJSONDecode 141ms × (1.00,1.00) 143ms × (1.00,1.00) +1.09%
BenchmarkMandelbrot200 6.01ms × (1.00,1.00) 6.01ms × (1.00,1.00) ~
BenchmarkGoParse 10.1ms × (0.91,1.09) 9.6ms × (0.94,1.07) ~
BenchmarkRegexpMatchEasy0_32 207ns × (1.00,1.01) 210ns × (1.00,1.00) +1.45%
BenchmarkRegexpMatchEasy0_1K 592ns × (0.99,1.00) 596ns × (0.99,1.01) +0.68%
BenchmarkRegexpMatchEasy1_32 184ns × (0.99,1.01) 184ns × (0.99,1.01) ~
BenchmarkRegexpMatchEasy1_1K 1.01µs × (1.00,1.00) 1.01µs × (0.99,1.01) ~
BenchmarkRegexpMatchMedium_32 327ns × (0.99,1.00) 327ns × (1.00,1.01) ~
BenchmarkRegexpMatchMedium_1K 92.5µs × (1.00,1.00) 93.0µs × (1.00,1.02) +0.48%
BenchmarkRegexpMatchHard_32 4.79µs × (0.95,1.00) 4.76µs × (0.95,1.01) ~
BenchmarkRegexpMatchHard_1K 136µs × (1.00,1.00) 136µs × (1.00,1.01) ~
BenchmarkRevcomp 900ms × (0.99,1.01) 892ms × (1.00,1.01) ~
BenchmarkTemplate 170ms × (0.99,1.01) 175ms × (0.99,1.00) +2.95%
BenchmarkTimeParse 645ns × (1.00,1.00) 638ns × (1.00,1.00) -1.16%
BenchmarkTimeFormat 740ns × (1.00,1.00) 772ns × (1.00,1.00) +4.39%
Change-Id: I0be905e32791e0cb70ff01f169c4b309a971d981
Reviewed-on: https://go-review.googlesource.com/9159
Reviewed-by: Rick Hudson <rlh@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2015-04-17 00:25:10 -04:00
|
|
|
isConstString := Isconst(nr, CTSTR)
|
|
|
|
|
|
|
|
|
|
if !cadable(nl) && nr != nil && !cadable(nr) && !isConstString {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var nodl Node
|
|
|
|
|
if cadable(nl) {
|
|
|
|
|
nodl = *nl
|
|
|
|
|
} else {
|
|
|
|
|
if nr != nil && !cadable(nr) && !isConstString {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
if nr == nil || isConstString || nl.Ullman >= nr.Ullman {
|
|
|
|
|
Igen(nl, &nodl, nil)
|
|
|
|
|
defer Regfree(&nodl)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
lbase := nodl.Xoffset
|
|
|
|
|
|
2015-04-16 16:22:30 -04:00
|
|
|
// Special case: zeroing.
|
|
|
|
|
var nodr Node
|
|
|
|
|
if nr == nil {
|
2015-03-18 12:29:40 -04:00
|
|
|
// When zeroing, prepare a register containing zero.
|
2015-04-16 16:22:30 -04:00
|
|
|
// TODO(rsc): Check that this is actually generating the best code.
|
2015-04-09 21:25:48 +10:00
|
|
|
if Thearch.REGZERO != 0 {
|
|
|
|
|
// cpu has a dedicated zero register
|
|
|
|
|
Nodreg(&nodr, Types[TUINT], Thearch.REGZERO)
|
|
|
|
|
} else {
|
|
|
|
|
// no dedicated zero register
|
2015-04-16 16:22:30 -04:00
|
|
|
var zero Node
|
|
|
|
|
Nodconst(&zero, nl.Type, 0)
|
2015-04-09 21:25:48 +10:00
|
|
|
Regalloc(&nodr, Types[TUINT], nil)
|
2015-04-16 16:22:30 -04:00
|
|
|
Thearch.Gmove(&zero, &nodr)
|
2015-04-09 21:25:48 +10:00
|
|
|
defer Regfree(&nodr)
|
|
|
|
|
}
|
2015-03-18 12:29:40 -04:00
|
|
|
|
2015-04-16 16:22:30 -04:00
|
|
|
emitVardef()
|
|
|
|
|
visitComponents(nl.Type, 0, func(t *Type, offset int64) bool {
|
|
|
|
|
nodl.Type = t
|
|
|
|
|
nodl.Xoffset = lbase + offset
|
|
|
|
|
nodr.Type = t
|
|
|
|
|
if Isfloat[t.Etype] {
|
|
|
|
|
// TODO(rsc): Cache zero register like we do for integers?
|
|
|
|
|
Clearslim(&nodl)
|
|
|
|
|
} else {
|
|
|
|
|
Thearch.Gmove(&nodr, &nodl)
|
2015-03-18 12:29:40 -04:00
|
|
|
}
|
2015-04-09 20:10:16 +10:00
|
|
|
return true
|
2015-04-16 16:22:30 -04:00
|
|
|
})
|
|
|
|
|
return true
|
|
|
|
|
}
|
2015-03-18 12:29:40 -04:00
|
|
|
|
2015-04-16 16:22:30 -04:00
|
|
|
// Special case: assignment of string constant.
|
|
|
|
|
if isConstString {
|
|
|
|
|
emitVardef()
|
2015-03-18 12:29:40 -04:00
|
|
|
|
2015-04-16 16:22:30 -04:00
|
|
|
// base
|
|
|
|
|
nodl.Type = Ptrto(Types[TUINT8])
|
|
|
|
|
Regalloc(&nodr, Types[Tptr], nil)
|
|
|
|
|
p := Thearch.Gins(Thearch.Optoas(OAS, Types[Tptr]), nil, &nodr)
|
2015-05-27 00:47:05 -04:00
|
|
|
Datastring(nr.Val().U.(string), &p.From)
|
2015-04-16 16:22:30 -04:00
|
|
|
p.From.Type = obj.TYPE_ADDR
|
2015-03-18 12:29:40 -04:00
|
|
|
Thearch.Gmove(&nodr, &nodl)
|
2015-04-16 16:22:30 -04:00
|
|
|
Regfree(&nodr)
|
2015-03-18 12:29:40 -04:00
|
|
|
|
2015-04-16 16:22:30 -04:00
|
|
|
// length
|
2015-03-18 12:29:40 -04:00
|
|
|
nodl.Type = Types[Simtype[TUINT]]
|
2015-04-16 16:22:30 -04:00
|
|
|
nodl.Xoffset += int64(Array_nel) - int64(Array_array)
|
2015-05-27 00:47:05 -04:00
|
|
|
Nodconst(&nodr, nodl.Type, int64(len(nr.Val().U.(string))))
|
2015-03-18 12:29:40 -04:00
|
|
|
Thearch.Gmove(&nodr, &nodl)
|
2015-04-16 16:22:30 -04:00
|
|
|
return true
|
|
|
|
|
}
|
2015-03-18 12:29:40 -04:00
|
|
|
|
2015-04-16 16:22:30 -04:00
|
|
|
// General case: copy nl = nr.
|
|
|
|
|
nodr = *nr
|
|
|
|
|
if !cadable(nr) {
|
cmd/internal/gc: emit write barriers at lower level
This is primarily preparation for inlining, not an optimization by itself,
but it still helps some.
name old new delta
BenchmarkBinaryTree17 18.2s × (0.99,1.01) 17.9s × (0.99,1.01) -1.57%
BenchmarkFannkuch11 4.44s × (1.00,1.00) 4.42s × (1.00,1.00) -0.40%
BenchmarkFmtFprintfEmpty 119ns × (0.95,1.02) 118ns × (0.96,1.02) ~
BenchmarkFmtFprintfString 501ns × (0.99,1.02) 486ns × (0.99,1.01) -2.89%
BenchmarkFmtFprintfInt 474ns × (0.99,1.00) 457ns × (0.99,1.01) -3.59%
BenchmarkFmtFprintfIntInt 792ns × (1.00,1.00) 768ns × (1.00,1.01) -3.03%
BenchmarkFmtFprintfPrefixedInt 574ns × (1.00,1.01) 584ns × (0.99,1.03) +1.83%
BenchmarkFmtFprintfFloat 749ns × (1.00,1.00) 739ns × (0.99,1.00) -1.34%
BenchmarkFmtManyArgs 2.94µs × (1.00,1.01) 2.77µs × (1.00,1.00) -5.76%
BenchmarkGobDecode 39.5ms × (0.99,1.01) 39.3ms × (0.99,1.01) ~
BenchmarkGobEncode 39.4ms × (1.00,1.01) 39.4ms × (0.99,1.00) ~
BenchmarkGzip 658ms × (1.00,1.01) 661ms × (0.99,1.01) ~
BenchmarkGunzip 142ms × (1.00,1.00) 142ms × (1.00,1.00) +0.22%
BenchmarkHTTPClientServer 134µs × (0.99,1.01) 133µs × (0.98,1.01) ~
BenchmarkJSONEncode 57.1ms × (0.99,1.01) 56.5ms × (0.99,1.01) ~
BenchmarkJSONDecode 141ms × (1.00,1.00) 143ms × (1.00,1.00) +1.09%
BenchmarkMandelbrot200 6.01ms × (1.00,1.00) 6.01ms × (1.00,1.00) ~
BenchmarkGoParse 10.1ms × (0.91,1.09) 9.6ms × (0.94,1.07) ~
BenchmarkRegexpMatchEasy0_32 207ns × (1.00,1.01) 210ns × (1.00,1.00) +1.45%
BenchmarkRegexpMatchEasy0_1K 592ns × (0.99,1.00) 596ns × (0.99,1.01) +0.68%
BenchmarkRegexpMatchEasy1_32 184ns × (0.99,1.01) 184ns × (0.99,1.01) ~
BenchmarkRegexpMatchEasy1_1K 1.01µs × (1.00,1.00) 1.01µs × (0.99,1.01) ~
BenchmarkRegexpMatchMedium_32 327ns × (0.99,1.00) 327ns × (1.00,1.01) ~
BenchmarkRegexpMatchMedium_1K 92.5µs × (1.00,1.00) 93.0µs × (1.00,1.02) +0.48%
BenchmarkRegexpMatchHard_32 4.79µs × (0.95,1.00) 4.76µs × (0.95,1.01) ~
BenchmarkRegexpMatchHard_1K 136µs × (1.00,1.00) 136µs × (1.00,1.01) ~
BenchmarkRevcomp 900ms × (0.99,1.01) 892ms × (1.00,1.01) ~
BenchmarkTemplate 170ms × (0.99,1.01) 175ms × (0.99,1.00) +2.95%
BenchmarkTimeParse 645ns × (1.00,1.00) 638ns × (1.00,1.00) -1.16%
BenchmarkTimeFormat 740ns × (1.00,1.00) 772ns × (1.00,1.00) +4.39%
Change-Id: I0be905e32791e0cb70ff01f169c4b309a971d981
Reviewed-on: https://go-review.googlesource.com/9159
Reviewed-by: Rick Hudson <rlh@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2015-04-17 00:25:10 -04:00
|
|
|
if nr.Ullman >= UINF && nodl.Op == OINDREG {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("miscompile")
|
cmd/internal/gc: emit write barriers at lower level
This is primarily preparation for inlining, not an optimization by itself,
but it still helps some.
name old new delta
BenchmarkBinaryTree17 18.2s × (0.99,1.01) 17.9s × (0.99,1.01) -1.57%
BenchmarkFannkuch11 4.44s × (1.00,1.00) 4.42s × (1.00,1.00) -0.40%
BenchmarkFmtFprintfEmpty 119ns × (0.95,1.02) 118ns × (0.96,1.02) ~
BenchmarkFmtFprintfString 501ns × (0.99,1.02) 486ns × (0.99,1.01) -2.89%
BenchmarkFmtFprintfInt 474ns × (0.99,1.00) 457ns × (0.99,1.01) -3.59%
BenchmarkFmtFprintfIntInt 792ns × (1.00,1.00) 768ns × (1.00,1.01) -3.03%
BenchmarkFmtFprintfPrefixedInt 574ns × (1.00,1.01) 584ns × (0.99,1.03) +1.83%
BenchmarkFmtFprintfFloat 749ns × (1.00,1.00) 739ns × (0.99,1.00) -1.34%
BenchmarkFmtManyArgs 2.94µs × (1.00,1.01) 2.77µs × (1.00,1.00) -5.76%
BenchmarkGobDecode 39.5ms × (0.99,1.01) 39.3ms × (0.99,1.01) ~
BenchmarkGobEncode 39.4ms × (1.00,1.01) 39.4ms × (0.99,1.00) ~
BenchmarkGzip 658ms × (1.00,1.01) 661ms × (0.99,1.01) ~
BenchmarkGunzip 142ms × (1.00,1.00) 142ms × (1.00,1.00) +0.22%
BenchmarkHTTPClientServer 134µs × (0.99,1.01) 133µs × (0.98,1.01) ~
BenchmarkJSONEncode 57.1ms × (0.99,1.01) 56.5ms × (0.99,1.01) ~
BenchmarkJSONDecode 141ms × (1.00,1.00) 143ms × (1.00,1.00) +1.09%
BenchmarkMandelbrot200 6.01ms × (1.00,1.00) 6.01ms × (1.00,1.00) ~
BenchmarkGoParse 10.1ms × (0.91,1.09) 9.6ms × (0.94,1.07) ~
BenchmarkRegexpMatchEasy0_32 207ns × (1.00,1.01) 210ns × (1.00,1.00) +1.45%
BenchmarkRegexpMatchEasy0_1K 592ns × (0.99,1.00) 596ns × (0.99,1.01) +0.68%
BenchmarkRegexpMatchEasy1_32 184ns × (0.99,1.01) 184ns × (0.99,1.01) ~
BenchmarkRegexpMatchEasy1_1K 1.01µs × (1.00,1.00) 1.01µs × (0.99,1.01) ~
BenchmarkRegexpMatchMedium_32 327ns × (0.99,1.00) 327ns × (1.00,1.01) ~
BenchmarkRegexpMatchMedium_1K 92.5µs × (1.00,1.00) 93.0µs × (1.00,1.02) +0.48%
BenchmarkRegexpMatchHard_32 4.79µs × (0.95,1.00) 4.76µs × (0.95,1.01) ~
BenchmarkRegexpMatchHard_1K 136µs × (1.00,1.00) 136µs × (1.00,1.01) ~
BenchmarkRevcomp 900ms × (0.99,1.01) 892ms × (1.00,1.01) ~
BenchmarkTemplate 170ms × (0.99,1.01) 175ms × (0.99,1.00) +2.95%
BenchmarkTimeParse 645ns × (1.00,1.00) 638ns × (1.00,1.00) -1.16%
BenchmarkTimeFormat 740ns × (1.00,1.00) 772ns × (1.00,1.00) +4.39%
Change-Id: I0be905e32791e0cb70ff01f169c4b309a971d981
Reviewed-on: https://go-review.googlesource.com/9159
Reviewed-by: Rick Hudson <rlh@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2015-04-17 00:25:10 -04:00
|
|
|
}
|
2015-04-16 16:22:30 -04:00
|
|
|
Igen(nr, &nodr, nil)
|
|
|
|
|
defer Regfree(&nodr)
|
|
|
|
|
}
|
|
|
|
|
rbase := nodr.Xoffset
|
|
|
|
|
|
cmd/internal/gc: emit write barriers at lower level
This is primarily preparation for inlining, not an optimization by itself,
but it still helps some.
name old new delta
BenchmarkBinaryTree17 18.2s × (0.99,1.01) 17.9s × (0.99,1.01) -1.57%
BenchmarkFannkuch11 4.44s × (1.00,1.00) 4.42s × (1.00,1.00) -0.40%
BenchmarkFmtFprintfEmpty 119ns × (0.95,1.02) 118ns × (0.96,1.02) ~
BenchmarkFmtFprintfString 501ns × (0.99,1.02) 486ns × (0.99,1.01) -2.89%
BenchmarkFmtFprintfInt 474ns × (0.99,1.00) 457ns × (0.99,1.01) -3.59%
BenchmarkFmtFprintfIntInt 792ns × (1.00,1.00) 768ns × (1.00,1.01) -3.03%
BenchmarkFmtFprintfPrefixedInt 574ns × (1.00,1.01) 584ns × (0.99,1.03) +1.83%
BenchmarkFmtFprintfFloat 749ns × (1.00,1.00) 739ns × (0.99,1.00) -1.34%
BenchmarkFmtManyArgs 2.94µs × (1.00,1.01) 2.77µs × (1.00,1.00) -5.76%
BenchmarkGobDecode 39.5ms × (0.99,1.01) 39.3ms × (0.99,1.01) ~
BenchmarkGobEncode 39.4ms × (1.00,1.01) 39.4ms × (0.99,1.00) ~
BenchmarkGzip 658ms × (1.00,1.01) 661ms × (0.99,1.01) ~
BenchmarkGunzip 142ms × (1.00,1.00) 142ms × (1.00,1.00) +0.22%
BenchmarkHTTPClientServer 134µs × (0.99,1.01) 133µs × (0.98,1.01) ~
BenchmarkJSONEncode 57.1ms × (0.99,1.01) 56.5ms × (0.99,1.01) ~
BenchmarkJSONDecode 141ms × (1.00,1.00) 143ms × (1.00,1.00) +1.09%
BenchmarkMandelbrot200 6.01ms × (1.00,1.00) 6.01ms × (1.00,1.00) ~
BenchmarkGoParse 10.1ms × (0.91,1.09) 9.6ms × (0.94,1.07) ~
BenchmarkRegexpMatchEasy0_32 207ns × (1.00,1.01) 210ns × (1.00,1.00) +1.45%
BenchmarkRegexpMatchEasy0_1K 592ns × (0.99,1.00) 596ns × (0.99,1.01) +0.68%
BenchmarkRegexpMatchEasy1_32 184ns × (0.99,1.01) 184ns × (0.99,1.01) ~
BenchmarkRegexpMatchEasy1_1K 1.01µs × (1.00,1.00) 1.01µs × (0.99,1.01) ~
BenchmarkRegexpMatchMedium_32 327ns × (0.99,1.00) 327ns × (1.00,1.01) ~
BenchmarkRegexpMatchMedium_1K 92.5µs × (1.00,1.00) 93.0µs × (1.00,1.02) +0.48%
BenchmarkRegexpMatchHard_32 4.79µs × (0.95,1.00) 4.76µs × (0.95,1.01) ~
BenchmarkRegexpMatchHard_1K 136µs × (1.00,1.00) 136µs × (1.00,1.01) ~
BenchmarkRevcomp 900ms × (0.99,1.01) 892ms × (1.00,1.01) ~
BenchmarkTemplate 170ms × (0.99,1.01) 175ms × (0.99,1.00) +2.95%
BenchmarkTimeParse 645ns × (1.00,1.00) 638ns × (1.00,1.00) -1.16%
BenchmarkTimeFormat 740ns × (1.00,1.00) 772ns × (1.00,1.00) +4.39%
Change-Id: I0be905e32791e0cb70ff01f169c4b309a971d981
Reviewed-on: https://go-review.googlesource.com/9159
Reviewed-by: Rick Hudson <rlh@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2015-04-17 00:25:10 -04:00
|
|
|
if nodl.Op == 0 {
|
|
|
|
|
Igen(nl, &nodl, nil)
|
|
|
|
|
defer Regfree(&nodl)
|
|
|
|
|
lbase = nodl.Xoffset
|
2015-04-16 16:22:30 -04:00
|
|
|
}
|
2015-03-18 12:29:40 -04:00
|
|
|
|
2015-04-16 16:22:30 -04:00
|
|
|
emitVardef()
|
cmd/internal/gc: emit write barriers at lower level
This is primarily preparation for inlining, not an optimization by itself,
but it still helps some.
name old new delta
BenchmarkBinaryTree17 18.2s × (0.99,1.01) 17.9s × (0.99,1.01) -1.57%
BenchmarkFannkuch11 4.44s × (1.00,1.00) 4.42s × (1.00,1.00) -0.40%
BenchmarkFmtFprintfEmpty 119ns × (0.95,1.02) 118ns × (0.96,1.02) ~
BenchmarkFmtFprintfString 501ns × (0.99,1.02) 486ns × (0.99,1.01) -2.89%
BenchmarkFmtFprintfInt 474ns × (0.99,1.00) 457ns × (0.99,1.01) -3.59%
BenchmarkFmtFprintfIntInt 792ns × (1.00,1.00) 768ns × (1.00,1.01) -3.03%
BenchmarkFmtFprintfPrefixedInt 574ns × (1.00,1.01) 584ns × (0.99,1.03) +1.83%
BenchmarkFmtFprintfFloat 749ns × (1.00,1.00) 739ns × (0.99,1.00) -1.34%
BenchmarkFmtManyArgs 2.94µs × (1.00,1.01) 2.77µs × (1.00,1.00) -5.76%
BenchmarkGobDecode 39.5ms × (0.99,1.01) 39.3ms × (0.99,1.01) ~
BenchmarkGobEncode 39.4ms × (1.00,1.01) 39.4ms × (0.99,1.00) ~
BenchmarkGzip 658ms × (1.00,1.01) 661ms × (0.99,1.01) ~
BenchmarkGunzip 142ms × (1.00,1.00) 142ms × (1.00,1.00) +0.22%
BenchmarkHTTPClientServer 134µs × (0.99,1.01) 133µs × (0.98,1.01) ~
BenchmarkJSONEncode 57.1ms × (0.99,1.01) 56.5ms × (0.99,1.01) ~
BenchmarkJSONDecode 141ms × (1.00,1.00) 143ms × (1.00,1.00) +1.09%
BenchmarkMandelbrot200 6.01ms × (1.00,1.00) 6.01ms × (1.00,1.00) ~
BenchmarkGoParse 10.1ms × (0.91,1.09) 9.6ms × (0.94,1.07) ~
BenchmarkRegexpMatchEasy0_32 207ns × (1.00,1.01) 210ns × (1.00,1.00) +1.45%
BenchmarkRegexpMatchEasy0_1K 592ns × (0.99,1.00) 596ns × (0.99,1.01) +0.68%
BenchmarkRegexpMatchEasy1_32 184ns × (0.99,1.01) 184ns × (0.99,1.01) ~
BenchmarkRegexpMatchEasy1_1K 1.01µs × (1.00,1.00) 1.01µs × (0.99,1.01) ~
BenchmarkRegexpMatchMedium_32 327ns × (0.99,1.00) 327ns × (1.00,1.01) ~
BenchmarkRegexpMatchMedium_1K 92.5µs × (1.00,1.00) 93.0µs × (1.00,1.02) +0.48%
BenchmarkRegexpMatchHard_32 4.79µs × (0.95,1.00) 4.76µs × (0.95,1.01) ~
BenchmarkRegexpMatchHard_1K 136µs × (1.00,1.00) 136µs × (1.00,1.01) ~
BenchmarkRevcomp 900ms × (0.99,1.01) 892ms × (1.00,1.01) ~
BenchmarkTemplate 170ms × (0.99,1.01) 175ms × (0.99,1.00) +2.95%
BenchmarkTimeParse 645ns × (1.00,1.00) 638ns × (1.00,1.00) -1.16%
BenchmarkTimeFormat 740ns × (1.00,1.00) 772ns × (1.00,1.00) +4.39%
Change-Id: I0be905e32791e0cb70ff01f169c4b309a971d981
Reviewed-on: https://go-review.googlesource.com/9159
Reviewed-by: Rick Hudson <rlh@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2015-04-17 00:25:10 -04:00
|
|
|
var (
|
|
|
|
|
ptrType *Type
|
|
|
|
|
ptrOffset int64
|
|
|
|
|
)
|
2015-04-16 16:22:30 -04:00
|
|
|
visitComponents(nl.Type, 0, func(t *Type, offset int64) bool {
|
2015-09-24 23:21:18 +02:00
|
|
|
if wb && Simtype[t.Etype] == Tptr && t != itable {
|
cmd/internal/gc: emit write barriers at lower level
This is primarily preparation for inlining, not an optimization by itself,
but it still helps some.
name old new delta
BenchmarkBinaryTree17 18.2s × (0.99,1.01) 17.9s × (0.99,1.01) -1.57%
BenchmarkFannkuch11 4.44s × (1.00,1.00) 4.42s × (1.00,1.00) -0.40%
BenchmarkFmtFprintfEmpty 119ns × (0.95,1.02) 118ns × (0.96,1.02) ~
BenchmarkFmtFprintfString 501ns × (0.99,1.02) 486ns × (0.99,1.01) -2.89%
BenchmarkFmtFprintfInt 474ns × (0.99,1.00) 457ns × (0.99,1.01) -3.59%
BenchmarkFmtFprintfIntInt 792ns × (1.00,1.00) 768ns × (1.00,1.01) -3.03%
BenchmarkFmtFprintfPrefixedInt 574ns × (1.00,1.01) 584ns × (0.99,1.03) +1.83%
BenchmarkFmtFprintfFloat 749ns × (1.00,1.00) 739ns × (0.99,1.00) -1.34%
BenchmarkFmtManyArgs 2.94µs × (1.00,1.01) 2.77µs × (1.00,1.00) -5.76%
BenchmarkGobDecode 39.5ms × (0.99,1.01) 39.3ms × (0.99,1.01) ~
BenchmarkGobEncode 39.4ms × (1.00,1.01) 39.4ms × (0.99,1.00) ~
BenchmarkGzip 658ms × (1.00,1.01) 661ms × (0.99,1.01) ~
BenchmarkGunzip 142ms × (1.00,1.00) 142ms × (1.00,1.00) +0.22%
BenchmarkHTTPClientServer 134µs × (0.99,1.01) 133µs × (0.98,1.01) ~
BenchmarkJSONEncode 57.1ms × (0.99,1.01) 56.5ms × (0.99,1.01) ~
BenchmarkJSONDecode 141ms × (1.00,1.00) 143ms × (1.00,1.00) +1.09%
BenchmarkMandelbrot200 6.01ms × (1.00,1.00) 6.01ms × (1.00,1.00) ~
BenchmarkGoParse 10.1ms × (0.91,1.09) 9.6ms × (0.94,1.07) ~
BenchmarkRegexpMatchEasy0_32 207ns × (1.00,1.01) 210ns × (1.00,1.00) +1.45%
BenchmarkRegexpMatchEasy0_1K 592ns × (0.99,1.00) 596ns × (0.99,1.01) +0.68%
BenchmarkRegexpMatchEasy1_32 184ns × (0.99,1.01) 184ns × (0.99,1.01) ~
BenchmarkRegexpMatchEasy1_1K 1.01µs × (1.00,1.00) 1.01µs × (0.99,1.01) ~
BenchmarkRegexpMatchMedium_32 327ns × (0.99,1.00) 327ns × (1.00,1.01) ~
BenchmarkRegexpMatchMedium_1K 92.5µs × (1.00,1.00) 93.0µs × (1.00,1.02) +0.48%
BenchmarkRegexpMatchHard_32 4.79µs × (0.95,1.00) 4.76µs × (0.95,1.01) ~
BenchmarkRegexpMatchHard_1K 136µs × (1.00,1.00) 136µs × (1.00,1.01) ~
BenchmarkRevcomp 900ms × (0.99,1.01) 892ms × (1.00,1.01) ~
BenchmarkTemplate 170ms × (0.99,1.01) 175ms × (0.99,1.00) +2.95%
BenchmarkTimeParse 645ns × (1.00,1.00) 638ns × (1.00,1.00) -1.16%
BenchmarkTimeFormat 740ns × (1.00,1.00) 772ns × (1.00,1.00) +4.39%
Change-Id: I0be905e32791e0cb70ff01f169c4b309a971d981
Reviewed-on: https://go-review.googlesource.com/9159
Reviewed-by: Rick Hudson <rlh@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2015-04-17 00:25:10 -04:00
|
|
|
if ptrType != nil {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("componentgen_wb %v", Tconv(nl.Type, 0))
|
cmd/internal/gc: emit write barriers at lower level
This is primarily preparation for inlining, not an optimization by itself,
but it still helps some.
name old new delta
BenchmarkBinaryTree17 18.2s × (0.99,1.01) 17.9s × (0.99,1.01) -1.57%
BenchmarkFannkuch11 4.44s × (1.00,1.00) 4.42s × (1.00,1.00) -0.40%
BenchmarkFmtFprintfEmpty 119ns × (0.95,1.02) 118ns × (0.96,1.02) ~
BenchmarkFmtFprintfString 501ns × (0.99,1.02) 486ns × (0.99,1.01) -2.89%
BenchmarkFmtFprintfInt 474ns × (0.99,1.00) 457ns × (0.99,1.01) -3.59%
BenchmarkFmtFprintfIntInt 792ns × (1.00,1.00) 768ns × (1.00,1.01) -3.03%
BenchmarkFmtFprintfPrefixedInt 574ns × (1.00,1.01) 584ns × (0.99,1.03) +1.83%
BenchmarkFmtFprintfFloat 749ns × (1.00,1.00) 739ns × (0.99,1.00) -1.34%
BenchmarkFmtManyArgs 2.94µs × (1.00,1.01) 2.77µs × (1.00,1.00) -5.76%
BenchmarkGobDecode 39.5ms × (0.99,1.01) 39.3ms × (0.99,1.01) ~
BenchmarkGobEncode 39.4ms × (1.00,1.01) 39.4ms × (0.99,1.00) ~
BenchmarkGzip 658ms × (1.00,1.01) 661ms × (0.99,1.01) ~
BenchmarkGunzip 142ms × (1.00,1.00) 142ms × (1.00,1.00) +0.22%
BenchmarkHTTPClientServer 134µs × (0.99,1.01) 133µs × (0.98,1.01) ~
BenchmarkJSONEncode 57.1ms × (0.99,1.01) 56.5ms × (0.99,1.01) ~
BenchmarkJSONDecode 141ms × (1.00,1.00) 143ms × (1.00,1.00) +1.09%
BenchmarkMandelbrot200 6.01ms × (1.00,1.00) 6.01ms × (1.00,1.00) ~
BenchmarkGoParse 10.1ms × (0.91,1.09) 9.6ms × (0.94,1.07) ~
BenchmarkRegexpMatchEasy0_32 207ns × (1.00,1.01) 210ns × (1.00,1.00) +1.45%
BenchmarkRegexpMatchEasy0_1K 592ns × (0.99,1.00) 596ns × (0.99,1.01) +0.68%
BenchmarkRegexpMatchEasy1_32 184ns × (0.99,1.01) 184ns × (0.99,1.01) ~
BenchmarkRegexpMatchEasy1_1K 1.01µs × (1.00,1.00) 1.01µs × (0.99,1.01) ~
BenchmarkRegexpMatchMedium_32 327ns × (0.99,1.00) 327ns × (1.00,1.01) ~
BenchmarkRegexpMatchMedium_1K 92.5µs × (1.00,1.00) 93.0µs × (1.00,1.02) +0.48%
BenchmarkRegexpMatchHard_32 4.79µs × (0.95,1.00) 4.76µs × (0.95,1.01) ~
BenchmarkRegexpMatchHard_1K 136µs × (1.00,1.00) 136µs × (1.00,1.01) ~
BenchmarkRevcomp 900ms × (0.99,1.01) 892ms × (1.00,1.01) ~
BenchmarkTemplate 170ms × (0.99,1.01) 175ms × (0.99,1.00) +2.95%
BenchmarkTimeParse 645ns × (1.00,1.00) 638ns × (1.00,1.00) -1.16%
BenchmarkTimeFormat 740ns × (1.00,1.00) 772ns × (1.00,1.00) +4.39%
Change-Id: I0be905e32791e0cb70ff01f169c4b309a971d981
Reviewed-on: https://go-review.googlesource.com/9159
Reviewed-by: Rick Hudson <rlh@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2015-04-17 00:25:10 -04:00
|
|
|
}
|
|
|
|
|
ptrType = t
|
|
|
|
|
ptrOffset = offset
|
|
|
|
|
return true
|
|
|
|
|
}
|
2015-04-16 16:22:30 -04:00
|
|
|
nodl.Type = t
|
|
|
|
|
nodl.Xoffset = lbase + offset
|
|
|
|
|
nodr.Type = t
|
|
|
|
|
nodr.Xoffset = rbase + offset
|
2015-03-18 12:29:40 -04:00
|
|
|
Thearch.Gmove(&nodr, &nodl)
|
2015-04-09 20:10:16 +10:00
|
|
|
return true
|
2015-04-16 16:22:30 -04:00
|
|
|
})
|
cmd/internal/gc: emit write barriers at lower level
This is primarily preparation for inlining, not an optimization by itself,
but it still helps some.
name old new delta
BenchmarkBinaryTree17 18.2s × (0.99,1.01) 17.9s × (0.99,1.01) -1.57%
BenchmarkFannkuch11 4.44s × (1.00,1.00) 4.42s × (1.00,1.00) -0.40%
BenchmarkFmtFprintfEmpty 119ns × (0.95,1.02) 118ns × (0.96,1.02) ~
BenchmarkFmtFprintfString 501ns × (0.99,1.02) 486ns × (0.99,1.01) -2.89%
BenchmarkFmtFprintfInt 474ns × (0.99,1.00) 457ns × (0.99,1.01) -3.59%
BenchmarkFmtFprintfIntInt 792ns × (1.00,1.00) 768ns × (1.00,1.01) -3.03%
BenchmarkFmtFprintfPrefixedInt 574ns × (1.00,1.01) 584ns × (0.99,1.03) +1.83%
BenchmarkFmtFprintfFloat 749ns × (1.00,1.00) 739ns × (0.99,1.00) -1.34%
BenchmarkFmtManyArgs 2.94µs × (1.00,1.01) 2.77µs × (1.00,1.00) -5.76%
BenchmarkGobDecode 39.5ms × (0.99,1.01) 39.3ms × (0.99,1.01) ~
BenchmarkGobEncode 39.4ms × (1.00,1.01) 39.4ms × (0.99,1.00) ~
BenchmarkGzip 658ms × (1.00,1.01) 661ms × (0.99,1.01) ~
BenchmarkGunzip 142ms × (1.00,1.00) 142ms × (1.00,1.00) +0.22%
BenchmarkHTTPClientServer 134µs × (0.99,1.01) 133µs × (0.98,1.01) ~
BenchmarkJSONEncode 57.1ms × (0.99,1.01) 56.5ms × (0.99,1.01) ~
BenchmarkJSONDecode 141ms × (1.00,1.00) 143ms × (1.00,1.00) +1.09%
BenchmarkMandelbrot200 6.01ms × (1.00,1.00) 6.01ms × (1.00,1.00) ~
BenchmarkGoParse 10.1ms × (0.91,1.09) 9.6ms × (0.94,1.07) ~
BenchmarkRegexpMatchEasy0_32 207ns × (1.00,1.01) 210ns × (1.00,1.00) +1.45%
BenchmarkRegexpMatchEasy0_1K 592ns × (0.99,1.00) 596ns × (0.99,1.01) +0.68%
BenchmarkRegexpMatchEasy1_32 184ns × (0.99,1.01) 184ns × (0.99,1.01) ~
BenchmarkRegexpMatchEasy1_1K 1.01µs × (1.00,1.00) 1.01µs × (0.99,1.01) ~
BenchmarkRegexpMatchMedium_32 327ns × (0.99,1.00) 327ns × (1.00,1.01) ~
BenchmarkRegexpMatchMedium_1K 92.5µs × (1.00,1.00) 93.0µs × (1.00,1.02) +0.48%
BenchmarkRegexpMatchHard_32 4.79µs × (0.95,1.00) 4.76µs × (0.95,1.01) ~
BenchmarkRegexpMatchHard_1K 136µs × (1.00,1.00) 136µs × (1.00,1.01) ~
BenchmarkRevcomp 900ms × (0.99,1.01) 892ms × (1.00,1.01) ~
BenchmarkTemplate 170ms × (0.99,1.01) 175ms × (0.99,1.00) +2.95%
BenchmarkTimeParse 645ns × (1.00,1.00) 638ns × (1.00,1.00) -1.16%
BenchmarkTimeFormat 740ns × (1.00,1.00) 772ns × (1.00,1.00) +4.39%
Change-Id: I0be905e32791e0cb70ff01f169c4b309a971d981
Reviewed-on: https://go-review.googlesource.com/9159
Reviewed-by: Rick Hudson <rlh@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2015-04-17 00:25:10 -04:00
|
|
|
if ptrType != nil {
|
|
|
|
|
nodl.Type = ptrType
|
|
|
|
|
nodl.Xoffset = lbase + ptrOffset
|
|
|
|
|
nodr.Type = ptrType
|
|
|
|
|
nodr.Xoffset = rbase + ptrOffset
|
|
|
|
|
cgen_wbptr(&nodr, &nodl)
|
|
|
|
|
}
|
2015-04-16 16:22:30 -04:00
|
|
|
return true
|
|
|
|
|
}
|
2015-03-18 12:29:40 -04:00
|
|
|
|
2015-04-16 16:22:30 -04:00
|
|
|
// visitComponents walks the individual components of the type t,
|
|
|
|
|
// walking into array elements, struct fields, the real and imaginary
|
|
|
|
|
// parts of complex numbers, and on 32-bit systems the high and
|
|
|
|
|
// low halves of 64-bit integers.
|
|
|
|
|
// It calls f for each such component, passing the component (aka element)
|
|
|
|
|
// type and memory offset, assuming t starts at startOffset.
|
|
|
|
|
// If f ever returns false, visitComponents returns false without any more
|
|
|
|
|
// calls to f. Otherwise visitComponents returns true.
|
|
|
|
|
func visitComponents(t *Type, startOffset int64, f func(elem *Type, elemOffset int64) bool) bool {
|
|
|
|
|
switch t.Etype {
|
|
|
|
|
case TINT64:
|
|
|
|
|
if Widthreg == 8 {
|
|
|
|
|
break
|
2015-03-18 12:29:40 -04:00
|
|
|
}
|
2015-04-16 16:22:30 -04:00
|
|
|
// NOTE: Assuming little endian (signed top half at offset 4).
|
|
|
|
|
// We don't have any 32-bit big-endian systems.
|
|
|
|
|
if Thearch.Thechar != '5' && Thearch.Thechar != '8' {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("unknown 32-bit architecture")
|
2015-03-18 12:29:40 -04:00
|
|
|
}
|
2015-04-16 16:22:30 -04:00
|
|
|
return f(Types[TUINT32], startOffset) &&
|
|
|
|
|
f(Types[TINT32], startOffset+4)
|
2015-03-18 12:29:40 -04:00
|
|
|
|
2015-04-16 16:22:30 -04:00
|
|
|
case TUINT64:
|
|
|
|
|
if Widthreg == 8 {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
return f(Types[TUINT32], startOffset) &&
|
|
|
|
|
f(Types[TUINT32], startOffset+4)
|
2015-03-18 12:29:40 -04:00
|
|
|
|
2015-04-16 16:22:30 -04:00
|
|
|
case TCOMPLEX64:
|
|
|
|
|
return f(Types[TFLOAT32], startOffset) &&
|
|
|
|
|
f(Types[TFLOAT32], startOffset+4)
|
2015-03-18 12:29:40 -04:00
|
|
|
|
2015-04-16 16:22:30 -04:00
|
|
|
case TCOMPLEX128:
|
|
|
|
|
return f(Types[TFLOAT64], startOffset) &&
|
|
|
|
|
f(Types[TFLOAT64], startOffset+8)
|
2015-03-18 12:29:40 -04:00
|
|
|
|
2015-04-16 16:22:30 -04:00
|
|
|
case TINTER:
|
cmd/internal/gc: emit write barriers at lower level
This is primarily preparation for inlining, not an optimization by itself,
but it still helps some.
name old new delta
BenchmarkBinaryTree17 18.2s × (0.99,1.01) 17.9s × (0.99,1.01) -1.57%
BenchmarkFannkuch11 4.44s × (1.00,1.00) 4.42s × (1.00,1.00) -0.40%
BenchmarkFmtFprintfEmpty 119ns × (0.95,1.02) 118ns × (0.96,1.02) ~
BenchmarkFmtFprintfString 501ns × (0.99,1.02) 486ns × (0.99,1.01) -2.89%
BenchmarkFmtFprintfInt 474ns × (0.99,1.00) 457ns × (0.99,1.01) -3.59%
BenchmarkFmtFprintfIntInt 792ns × (1.00,1.00) 768ns × (1.00,1.01) -3.03%
BenchmarkFmtFprintfPrefixedInt 574ns × (1.00,1.01) 584ns × (0.99,1.03) +1.83%
BenchmarkFmtFprintfFloat 749ns × (1.00,1.00) 739ns × (0.99,1.00) -1.34%
BenchmarkFmtManyArgs 2.94µs × (1.00,1.01) 2.77µs × (1.00,1.00) -5.76%
BenchmarkGobDecode 39.5ms × (0.99,1.01) 39.3ms × (0.99,1.01) ~
BenchmarkGobEncode 39.4ms × (1.00,1.01) 39.4ms × (0.99,1.00) ~
BenchmarkGzip 658ms × (1.00,1.01) 661ms × (0.99,1.01) ~
BenchmarkGunzip 142ms × (1.00,1.00) 142ms × (1.00,1.00) +0.22%
BenchmarkHTTPClientServer 134µs × (0.99,1.01) 133µs × (0.98,1.01) ~
BenchmarkJSONEncode 57.1ms × (0.99,1.01) 56.5ms × (0.99,1.01) ~
BenchmarkJSONDecode 141ms × (1.00,1.00) 143ms × (1.00,1.00) +1.09%
BenchmarkMandelbrot200 6.01ms × (1.00,1.00) 6.01ms × (1.00,1.00) ~
BenchmarkGoParse 10.1ms × (0.91,1.09) 9.6ms × (0.94,1.07) ~
BenchmarkRegexpMatchEasy0_32 207ns × (1.00,1.01) 210ns × (1.00,1.00) +1.45%
BenchmarkRegexpMatchEasy0_1K 592ns × (0.99,1.00) 596ns × (0.99,1.01) +0.68%
BenchmarkRegexpMatchEasy1_32 184ns × (0.99,1.01) 184ns × (0.99,1.01) ~
BenchmarkRegexpMatchEasy1_1K 1.01µs × (1.00,1.00) 1.01µs × (0.99,1.01) ~
BenchmarkRegexpMatchMedium_32 327ns × (0.99,1.00) 327ns × (1.00,1.01) ~
BenchmarkRegexpMatchMedium_1K 92.5µs × (1.00,1.00) 93.0µs × (1.00,1.02) +0.48%
BenchmarkRegexpMatchHard_32 4.79µs × (0.95,1.00) 4.76µs × (0.95,1.01) ~
BenchmarkRegexpMatchHard_1K 136µs × (1.00,1.00) 136µs × (1.00,1.01) ~
BenchmarkRevcomp 900ms × (0.99,1.01) 892ms × (1.00,1.01) ~
BenchmarkTemplate 170ms × (0.99,1.01) 175ms × (0.99,1.00) +2.95%
BenchmarkTimeParse 645ns × (1.00,1.00) 638ns × (1.00,1.00) -1.16%
BenchmarkTimeFormat 740ns × (1.00,1.00) 772ns × (1.00,1.00) +4.39%
Change-Id: I0be905e32791e0cb70ff01f169c4b309a971d981
Reviewed-on: https://go-review.googlesource.com/9159
Reviewed-by: Rick Hudson <rlh@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2015-04-17 00:25:10 -04:00
|
|
|
return f(itable, startOffset) &&
|
2015-04-16 16:22:30 -04:00
|
|
|
f(Ptrto(Types[TUINT8]), startOffset+int64(Widthptr))
|
2015-03-18 12:29:40 -04:00
|
|
|
|
2015-04-16 16:22:30 -04:00
|
|
|
case TSTRING:
|
|
|
|
|
return f(Ptrto(Types[TUINT8]), startOffset) &&
|
|
|
|
|
f(Types[Simtype[TUINT]], startOffset+int64(Widthptr))
|
2015-03-18 12:29:40 -04:00
|
|
|
|
2015-04-16 16:22:30 -04:00
|
|
|
case TARRAY:
|
|
|
|
|
if Isslice(t) {
|
|
|
|
|
return f(Ptrto(t.Type), startOffset+int64(Array_array)) &&
|
|
|
|
|
f(Types[Simtype[TUINT]], startOffset+int64(Array_nel)) &&
|
|
|
|
|
f(Types[Simtype[TUINT]], startOffset+int64(Array_cap))
|
2015-03-18 12:29:40 -04:00
|
|
|
}
|
|
|
|
|
|
2015-04-16 16:22:30 -04:00
|
|
|
// Short-circuit [1e6]struct{}.
|
|
|
|
|
if t.Type.Width == 0 {
|
|
|
|
|
return true
|
2015-03-18 12:29:40 -04:00
|
|
|
}
|
|
|
|
|
|
2015-04-16 16:22:30 -04:00
|
|
|
for i := int64(0); i < t.Bound; i++ {
|
|
|
|
|
if !visitComponents(t.Type, startOffset+i*t.Type.Width, f) {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-04-09 20:10:16 +10:00
|
|
|
return true
|
2015-03-18 12:29:40 -04:00
|
|
|
|
|
|
|
|
case TSTRUCT:
|
2015-04-16 16:22:30 -04:00
|
|
|
if t.Type != nil && t.Type.Width != 0 {
|
|
|
|
|
// NOTE(rsc): If this happens, the right thing to do is to say
|
|
|
|
|
// startOffset -= t.Type.Width
|
|
|
|
|
// but I want to see if it does.
|
|
|
|
|
// The old version of componentgen handled this,
|
|
|
|
|
// in code introduced in CL 6932045 to fix issue #4518.
|
|
|
|
|
// But the test case in issue 4518 does not trigger this anymore,
|
|
|
|
|
// so maybe this complication is no longer needed.
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("struct not at offset 0")
|
2015-04-16 16:22:30 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for field := t.Type; field != nil; field = field.Down {
|
|
|
|
|
if field.Etype != TFIELD {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("bad struct")
|
2015-04-16 16:22:30 -04:00
|
|
|
}
|
|
|
|
|
if !visitComponents(field.Type, startOffset+field.Width, f) {
|
|
|
|
|
return false
|
2015-03-18 12:29:40 -04:00
|
|
|
}
|
|
|
|
|
}
|
2015-04-09 20:10:16 +10:00
|
|
|
return true
|
2015-03-18 12:29:40 -04:00
|
|
|
}
|
2015-04-16 16:22:30 -04:00
|
|
|
return f(t, startOffset)
|
2015-03-18 12:29:40 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func cadable(n *Node) bool {
|
2015-04-16 16:22:30 -04:00
|
|
|
// Note: Not sure why you can have n.Op == ONAME without n.Addable, but you can.
|
|
|
|
|
return n.Addable && n.Op == ONAME
|
2015-03-18 12:29:40 -04:00
|
|
|
}
|