mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile: track pragmas in lexer rather than global variables
By using a Pragma bit set (8 bits) rather than 8 booleans, also reduce Func type size by 8 bytes (208B -> 200B on 64bit platforms, 116B -> 108B on 32bit platforms). Change-Id: Ibb7e1f8c418a0b5bc6ff813cbdde7bc6f0013b5a Reviewed-on: https://go-review.googlesource.com/19966 Reviewed-by: Dave Cheney <dave@cheney.net>
This commit is contained in:
parent
071e43a958
commit
3c0fae5306
10 changed files with 50 additions and 67 deletions
|
|
@ -240,10 +240,9 @@ func (p *importer) typ() *Type {
|
||||||
{
|
{
|
||||||
saved := structpkg
|
saved := structpkg
|
||||||
structpkg = tsym.Pkg
|
structpkg = tsym.Pkg
|
||||||
addmethod(sym, n.Type, false, nointerface)
|
addmethod(sym, n.Type, false, false)
|
||||||
structpkg = saved
|
structpkg = saved
|
||||||
}
|
}
|
||||||
nointerface = false
|
|
||||||
funchdr(n)
|
funchdr(n)
|
||||||
|
|
||||||
// (comment from go.y)
|
// (comment from go.y)
|
||||||
|
|
|
||||||
|
|
@ -781,7 +781,7 @@ var sys_wbptr *Node
|
||||||
|
|
||||||
func cgen_wbptr(n, res *Node) {
|
func cgen_wbptr(n, res *Node) {
|
||||||
if Curfn != nil {
|
if Curfn != nil {
|
||||||
if Curfn.Func.Nowritebarrier {
|
if Curfn.Func.Pragma&Nowritebarrier != 0 {
|
||||||
Yyerror("write barrier prohibited")
|
Yyerror("write barrier prohibited")
|
||||||
}
|
}
|
||||||
if Curfn.Func.WBLineno == 0 {
|
if Curfn.Func.WBLineno == 0 {
|
||||||
|
|
@ -831,7 +831,7 @@ func cgen_wbptr(n, res *Node) {
|
||||||
|
|
||||||
func cgen_wbfat(n, res *Node) {
|
func cgen_wbfat(n, res *Node) {
|
||||||
if Curfn != nil {
|
if Curfn != nil {
|
||||||
if Curfn.Func.Nowritebarrier {
|
if Curfn.Func.Pragma&Nowritebarrier != 0 {
|
||||||
Yyerror("write barrier prohibited")
|
Yyerror("write barrier prohibited")
|
||||||
}
|
}
|
||||||
if Curfn.Func.WBLineno == 0 {
|
if Curfn.Func.WBLineno == 0 {
|
||||||
|
|
|
||||||
|
|
@ -1530,7 +1530,7 @@ func checknowritebarrierrec() {
|
||||||
|
|
||||||
// Check nowritebarrierrec functions.
|
// Check nowritebarrierrec functions.
|
||||||
for _, n := range list {
|
for _, n := range list {
|
||||||
if !n.Func.Nowritebarrierrec {
|
if n.Func.Pragma&Nowritebarrierrec == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
call, hasWB := c.best[n]
|
call, hasWB := c.best[n]
|
||||||
|
|
|
||||||
|
|
@ -616,23 +616,10 @@ var flag_largemodel int
|
||||||
// when the race detector is enabled.
|
// when the race detector is enabled.
|
||||||
var instrumenting bool
|
var instrumenting bool
|
||||||
|
|
||||||
// Pending annotations for next func declaration.
|
|
||||||
var (
|
|
||||||
noescape bool
|
|
||||||
noinline bool
|
|
||||||
norace bool
|
|
||||||
nosplit bool
|
|
||||||
nowritebarrier bool
|
|
||||||
nowritebarrierrec bool
|
|
||||||
systemstack bool
|
|
||||||
)
|
|
||||||
|
|
||||||
var debuglive int
|
var debuglive int
|
||||||
|
|
||||||
var Ctxt *obj.Link
|
var Ctxt *obj.Link
|
||||||
|
|
||||||
var nointerface bool
|
|
||||||
|
|
||||||
var writearchive int
|
var writearchive int
|
||||||
|
|
||||||
var bstdout obj.Biobuf
|
var bstdout obj.Biobuf
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,7 @@ func caninl(fn *Node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If marked "go:noinline", don't inline
|
// If marked "go:noinline", don't inline
|
||||||
if fn.Func.Noinline {
|
if fn.Func.Pragma&Noinline != 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -844,6 +844,19 @@ func plan9quote(s string) string {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Pragma uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
Nointerface Pragma = 1 << iota
|
||||||
|
Noescape // func parameters don't escape
|
||||||
|
Norace // func must not have race detector annotations
|
||||||
|
Nosplit // func should not execute on separate stack
|
||||||
|
Noinline // func should not be inlined
|
||||||
|
Systemstack // func must run on system stack
|
||||||
|
Nowritebarrier // emit compiler error instead of write barrier
|
||||||
|
Nowritebarrierrec // error on write barrier in this or recursive callees
|
||||||
|
)
|
||||||
|
|
||||||
type lexer struct {
|
type lexer struct {
|
||||||
// source
|
// source
|
||||||
bin *obj.Biobuf
|
bin *obj.Biobuf
|
||||||
|
|
@ -852,6 +865,10 @@ type lexer struct {
|
||||||
|
|
||||||
nlsemi bool // if set, '\n' and EOF translate to ';'
|
nlsemi bool // if set, '\n' and EOF translate to ';'
|
||||||
|
|
||||||
|
// pragma flags
|
||||||
|
// accumulated by lexer; reset by parser
|
||||||
|
pragma Pragma
|
||||||
|
|
||||||
// current token
|
// current token
|
||||||
tok int32
|
tok int32
|
||||||
sym_ *Sym // valid if tok == LNAME
|
sym_ *Sym // valid if tok == LNAME
|
||||||
|
|
@ -1650,32 +1667,31 @@ func (l *lexer) getlinepragma() rune {
|
||||||
Lookup(f[1]).Linkname = f[2]
|
Lookup(f[1]).Linkname = f[2]
|
||||||
case "go:nointerface":
|
case "go:nointerface":
|
||||||
if obj.Fieldtrack_enabled != 0 {
|
if obj.Fieldtrack_enabled != 0 {
|
||||||
nointerface = true
|
l.pragma |= Nointerface
|
||||||
}
|
}
|
||||||
case "go:noescape":
|
case "go:noescape":
|
||||||
noescape = true
|
l.pragma |= Noescape
|
||||||
case "go:norace":
|
case "go:norace":
|
||||||
norace = true
|
l.pragma |= Norace
|
||||||
case "go:nosplit":
|
case "go:nosplit":
|
||||||
nosplit = true
|
l.pragma |= Nosplit
|
||||||
case "go:noinline":
|
case "go:noinline":
|
||||||
noinline = true
|
l.pragma |= Noinline
|
||||||
case "go:systemstack":
|
case "go:systemstack":
|
||||||
if compiling_runtime == 0 {
|
if compiling_runtime == 0 {
|
||||||
Yyerror("//go:systemstack only allowed in runtime")
|
Yyerror("//go:systemstack only allowed in runtime")
|
||||||
}
|
}
|
||||||
systemstack = true
|
l.pragma |= Systemstack
|
||||||
case "go:nowritebarrier":
|
case "go:nowritebarrier":
|
||||||
if compiling_runtime == 0 {
|
if compiling_runtime == 0 {
|
||||||
Yyerror("//go:nowritebarrier only allowed in runtime")
|
Yyerror("//go:nowritebarrier only allowed in runtime")
|
||||||
}
|
}
|
||||||
nowritebarrier = true
|
l.pragma |= Nowritebarrier
|
||||||
case "go:nowritebarrierrec":
|
case "go:nowritebarrierrec":
|
||||||
if compiling_runtime == 0 {
|
if compiling_runtime == 0 {
|
||||||
Yyerror("//go:nowritebarrierrec only allowed in runtime")
|
Yyerror("//go:nowritebarrierrec only allowed in runtime")
|
||||||
}
|
}
|
||||||
nowritebarrierrec = true
|
l.pragma |= Nowritebarrierrec | Nowritebarrier // implies Nowritebarrier
|
||||||
nowritebarrier = true // Implies nowritebarrier
|
|
||||||
}
|
}
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1893,25 +1893,21 @@ func (p *parser) xfndcl() *Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
p.want(LFUNC)
|
p.want(LFUNC)
|
||||||
f := p.fndcl()
|
f := p.fndcl(p.pragma&Nointerface != 0)
|
||||||
body := p.fnbody()
|
body := p.fnbody()
|
||||||
|
|
||||||
if f == nil {
|
if f == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if noescape && body != nil {
|
|
||||||
Yyerror("can only use //go:noescape with external func implementations")
|
|
||||||
}
|
|
||||||
|
|
||||||
f.Nbody = body
|
f.Nbody = body
|
||||||
|
f.Noescape = p.pragma&Noescape != 0
|
||||||
|
if f.Noescape && body != nil {
|
||||||
|
Yyerror("can only use //go:noescape with external func implementations")
|
||||||
|
}
|
||||||
|
f.Func.Pragma = p.pragma
|
||||||
f.Func.Endlineno = lineno
|
f.Func.Endlineno = lineno
|
||||||
f.Noescape = noescape
|
|
||||||
f.Func.Norace = norace
|
|
||||||
f.Func.Nosplit = nosplit
|
|
||||||
f.Func.Noinline = noinline
|
|
||||||
f.Func.Nowritebarrier = nowritebarrier
|
|
||||||
f.Func.Nowritebarrierrec = nowritebarrierrec
|
|
||||||
f.Func.Systemstack = systemstack
|
|
||||||
funcbody(f)
|
funcbody(f)
|
||||||
|
|
||||||
return f
|
return f
|
||||||
|
|
@ -1922,7 +1918,7 @@ func (p *parser) xfndcl() *Node {
|
||||||
// Function = Signature FunctionBody .
|
// Function = Signature FunctionBody .
|
||||||
// MethodDecl = "func" Receiver MethodName ( Function | Signature ) .
|
// MethodDecl = "func" Receiver MethodName ( Function | Signature ) .
|
||||||
// Receiver = Parameters .
|
// Receiver = Parameters .
|
||||||
func (p *parser) fndcl() *Node {
|
func (p *parser) fndcl(nointerface bool) *Node {
|
||||||
if trace && Debug['x'] != 0 {
|
if trace && Debug['x'] != 0 {
|
||||||
defer p.trace("fndcl")()
|
defer p.trace("fndcl")()
|
||||||
}
|
}
|
||||||
|
|
@ -2058,8 +2054,7 @@ func (p *parser) hidden_fndcl() *Node {
|
||||||
ss.Type = functype(s2.N, s6, s8)
|
ss.Type = functype(s2.N, s6, s8)
|
||||||
|
|
||||||
checkwidth(ss.Type)
|
checkwidth(ss.Type)
|
||||||
addmethod(s4, ss.Type, false, nointerface)
|
addmethod(s4, ss.Type, false, false)
|
||||||
nointerface = false
|
|
||||||
funchdr(ss)
|
funchdr(ss)
|
||||||
|
|
||||||
// inl.C's inlnode in on a dotmeth node expects to find the inlineable body as
|
// inl.C's inlnode in on a dotmeth node expects to find the inlineable body as
|
||||||
|
|
@ -2140,18 +2135,10 @@ loop:
|
||||||
testdclstack()
|
testdclstack()
|
||||||
}
|
}
|
||||||
|
|
||||||
noescape = false
|
// Reset p.pragma BEFORE advancing to the next token (consuming ';')
|
||||||
noinline = false
|
// since comments before may set pragmas for the next function decl.
|
||||||
nointerface = false
|
p.pragma = 0
|
||||||
norace = false
|
|
||||||
nosplit = false
|
|
||||||
nowritebarrier = false
|
|
||||||
nowritebarrierrec = false
|
|
||||||
systemstack = false
|
|
||||||
|
|
||||||
// Consume ';' AFTER resetting the above flags since
|
|
||||||
// it may read the subsequent comment line which may
|
|
||||||
// set the flags for the next function declaration.
|
|
||||||
if p.tok != EOF && !p.got(';') {
|
if p.tok != EOF && !p.got(';') {
|
||||||
p.syntax_error("after top level declaration")
|
p.syntax_error("after top level declaration")
|
||||||
p.advance(LVAR, LCONST, LTYPE, LFUNC)
|
p.advance(LVAR, LCONST, LTYPE, LFUNC)
|
||||||
|
|
|
||||||
|
|
@ -434,10 +434,10 @@ func compile(fn *Node) {
|
||||||
if fn.Func.Needctxt {
|
if fn.Func.Needctxt {
|
||||||
ptxt.From3.Offset |= obj.NEEDCTXT
|
ptxt.From3.Offset |= obj.NEEDCTXT
|
||||||
}
|
}
|
||||||
if fn.Func.Nosplit {
|
if fn.Func.Pragma&Nosplit != 0 {
|
||||||
ptxt.From3.Offset |= obj.NOSPLIT
|
ptxt.From3.Offset |= obj.NOSPLIT
|
||||||
}
|
}
|
||||||
if fn.Func.Systemstack {
|
if fn.Func.Pragma&Systemstack != 0 {
|
||||||
ptxt.From.Sym.Cfunc = 1
|
ptxt.From.Sym.Cfunc = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ func ispkgin(pkgs []string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func instrument(fn *Node) {
|
func instrument(fn *Node) {
|
||||||
if ispkgin(omit_pkgs) || fn.Func.Norace {
|
if ispkgin(omit_pkgs) || fn.Func.Pragma&Norace != 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -169,18 +169,12 @@ type Func struct {
|
||||||
Depth int32
|
Depth int32
|
||||||
|
|
||||||
Endlineno int32
|
Endlineno int32
|
||||||
|
WBLineno int32 // line number of first write barrier
|
||||||
|
|
||||||
Norace bool // func must not have race detector annotations
|
Pragma Pragma // go:xxx function annotations
|
||||||
Nosplit bool // func should not execute on separate stack
|
Dupok bool // duplicate definitions ok
|
||||||
Noinline bool // func should not be inlined
|
Wrapper bool // is method wrapper
|
||||||
Nowritebarrier bool // emit compiler error instead of write barrier
|
Needctxt bool // function uses context register (has closure variables)
|
||||||
Nowritebarrierrec bool // error on write barrier in this or recursive callees
|
|
||||||
Dupok bool // duplicate definitions ok
|
|
||||||
Wrapper bool // is method wrapper
|
|
||||||
Needctxt bool // function uses context register (has closure variables)
|
|
||||||
Systemstack bool // must run on system stack
|
|
||||||
|
|
||||||
WBLineno int32 // line number of first write barrier
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Op uint8
|
type Op uint8
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue