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
|
|
|
|
|
|
|
|
// case OADD:
|
|
|
|
// if(n->right->op == OLITERAL) {
|
|
|
|
// v = n->right->vconst;
|
|
|
|
// naddr(n->left, a, canemitcode);
|
|
|
|
// } else
|
|
|
|
// if(n->left->op == OLITERAL) {
|
|
|
|
// v = n->left->vconst;
|
|
|
|
// naddr(n->right, a, canemitcode);
|
|
|
|
// } else
|
|
|
|
// goto bad;
|
|
|
|
// a->offset += v;
|
|
|
|
// break;
|
|
|
|
|
2015-10-22 09:51:12 +09:00
|
|
|
// a function named init is a special case.
|
|
|
|
// it is called by the initialization before
|
|
|
|
// main is run. to make it unique within a
|
|
|
|
// package and also uncallable, the name,
|
|
|
|
// normally "pkg.init", is altered to "pkg.init.1".
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
var renameinit_initgen int
|
|
|
|
|
|
|
|
func renameinit() *Sym {
|
|
|
|
renameinit_initgen++
|
2015-03-06 12:02:24 -08:00
|
|
|
return Lookupf("init.%d", renameinit_initgen)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
2015-10-22 09:51:12 +09:00
|
|
|
// hand-craft the following initialization code
|
|
|
|
// var initdone· uint8 (1)
|
|
|
|
// func init() (2)
|
|
|
|
// if initdone· != 0 { (3)
|
|
|
|
// if initdone· == 2 (4)
|
|
|
|
// return
|
|
|
|
// throw(); (5)
|
|
|
|
// }
|
|
|
|
// initdone· = 1; (6)
|
|
|
|
// // over all matching imported symbols
|
|
|
|
// <pkg>.init() (7)
|
|
|
|
// { <init stmts> } (8)
|
|
|
|
// init.<n>() // if any (9)
|
|
|
|
// initdone· = 2; (10)
|
|
|
|
// return (11)
|
|
|
|
// }
|
2015-02-17 22:13:49 -05:00
|
|
|
func anyinit(n *NodeList) bool {
|
2015-02-13 14:40:36 -05:00
|
|
|
// are there any interesting init statements
|
2015-02-23 16:07:24 -05:00
|
|
|
for l := n; l != nil; l = l.Next {
|
2015-02-13 14:40:36 -05:00
|
|
|
switch l.N.Op {
|
2015-04-01 09:38:44 -07:00
|
|
|
case ODCLFUNC, ODCLCONST, ODCLTYPE, OEMPTY:
|
2015-02-13 14:40:36 -05:00
|
|
|
break
|
|
|
|
|
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 OAS, OASWB:
|
2015-02-17 22:13:49 -05:00
|
|
|
if isblank(l.N.Left) && candiscard(l.N.Right) {
|
2015-02-13 14:40:36 -05:00
|
|
|
break
|
|
|
|
}
|
|
|
|
fallthrough
|
|
|
|
|
|
|
|
// fall through
|
|
|
|
default:
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// is this main
|
|
|
|
if localpkg.Name == "main" {
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// is there an explicit init function
|
2015-02-23 16:07:24 -05:00
|
|
|
s := Lookup("init.1")
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
if s.Def != nil {
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// are there any imported init functions
|
2015-03-02 16:21:15 -05:00
|
|
|
for _, s := range initSyms {
|
|
|
|
if s.Def != nil {
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// then none
|
2015-02-17 22:13:49 -05:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
func fninit(n *NodeList) {
|
|
|
|
if Debug['A'] != 0 {
|
|
|
|
// sys.go or unsafe.go during compiler build
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
n = initfix(n)
|
2015-02-17 22:13:49 -05:00
|
|
|
if !anyinit(n) {
|
2015-02-13 14:40:36 -05:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2015-03-02 14:22:05 -05:00
|
|
|
var r *NodeList
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
// (1)
|
2015-03-06 12:02:24 -08:00
|
|
|
gatevar := newname(Lookup("initdone·"))
|
2015-02-13 14:40:36 -05:00
|
|
|
addvar(gatevar, Types[TUINT8], PEXTERN)
|
|
|
|
|
|
|
|
// (2)
|
|
|
|
Maxarg = 0
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
fn := Nod(ODCLFUNC, nil, nil)
|
2015-03-06 12:02:24 -08:00
|
|
|
initsym := Lookup("init")
|
2015-05-27 10:42:55 -04:00
|
|
|
fn.Func.Nname = newname(initsym)
|
|
|
|
fn.Func.Nname.Name.Defn = fn
|
|
|
|
fn.Func.Nname.Name.Param.Ntype = Nod(OTFUNC, nil, nil)
|
|
|
|
declare(fn.Func.Nname, PFUNC)
|
2015-02-13 14:40:36 -05:00
|
|
|
funchdr(fn)
|
|
|
|
|
|
|
|
// (3)
|
2015-02-23 16:07:24 -05:00
|
|
|
a := Nod(OIF, nil, nil)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-05-26 21:30:20 -04:00
|
|
|
a.Left = Nod(ONE, gatevar, Nodintconst(0))
|
2015-02-13 14:40:36 -05:00
|
|
|
r = list(r, a)
|
|
|
|
|
|
|
|
// (4)
|
2015-02-23 16:07:24 -05:00
|
|
|
b := Nod(OIF, nil, nil)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-05-26 21:30:20 -04:00
|
|
|
b.Left = Nod(OEQ, gatevar, Nodintconst(2))
|
2015-02-13 14:40:36 -05:00
|
|
|
b.Nbody = list1(Nod(ORETURN, nil, nil))
|
|
|
|
a.Nbody = list1(b)
|
|
|
|
|
|
|
|
// (5)
|
|
|
|
b = syslook("throwinit", 0)
|
|
|
|
|
|
|
|
b = Nod(OCALL, b, nil)
|
|
|
|
a.Nbody = list(a.Nbody, b)
|
|
|
|
|
|
|
|
// (6)
|
|
|
|
a = Nod(OAS, gatevar, Nodintconst(1))
|
|
|
|
|
|
|
|
r = list(r, a)
|
|
|
|
|
|
|
|
// (7)
|
2015-03-02 16:21:15 -05:00
|
|
|
for _, s := range initSyms {
|
|
|
|
if s.Def != nil && s != initsym {
|
2015-02-13 14:40:36 -05:00
|
|
|
// could check that it is fn of no args/returns
|
|
|
|
a = Nod(OCALL, s.Def, nil)
|
|
|
|
r = list(r, a)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// (8)
|
|
|
|
r = concat(r, n)
|
|
|
|
|
|
|
|
// (9)
|
|
|
|
// could check that it is fn of no args/returns
|
2015-02-23 16:07:24 -05:00
|
|
|
for i := 1; ; i++ {
|
2015-03-06 12:02:24 -08:00
|
|
|
s := Lookupf("init.%d", i)
|
2015-02-13 14:40:36 -05:00
|
|
|
if s.Def == nil {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
a = Nod(OCALL, s.Def, nil)
|
|
|
|
r = list(r, a)
|
|
|
|
}
|
|
|
|
|
|
|
|
// (10)
|
|
|
|
a = Nod(OAS, gatevar, Nodintconst(2))
|
|
|
|
|
|
|
|
r = list(r, a)
|
|
|
|
|
|
|
|
// (11)
|
|
|
|
a = Nod(ORETURN, nil, nil)
|
|
|
|
|
|
|
|
r = list(r, a)
|
2015-05-27 10:42:55 -04:00
|
|
|
exportsym(fn.Func.Nname)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
fn.Nbody = r
|
|
|
|
funcbody(fn)
|
|
|
|
|
|
|
|
Curfn = fn
|
|
|
|
typecheck(&fn, Etop)
|
|
|
|
typechecklist(r, Etop)
|
|
|
|
Curfn = nil
|
|
|
|
funccompile(fn)
|
|
|
|
}
|