1
0
mirror of https://github.com/golang/go synced 2024-11-23 23:40:13 -07:00

cmd/compile: add Func.SetNilCheckDisabled

Generated hash and eq routines don't need nil checks.
Prior to this CL, this was accomplished by
temporarily incrementing the global variable disable_checknil.
However, that increment lasted only the lifetime of the
call to funccompile. After CL 41503, funccompile may
do nothing but enqueue the function for compilation,
resulting in nil checks being generated.

Fix this by adding an explicit flag to a function
indicating whether nil checks should be disabled
for that function.

While we're here, allow concurrent compilation
with the -w and -W flags, since that was needed
to investigate this issue.

Fixes #20242

Change-Id: Ib9140c22c49e9a09e62fa3cf350f5d3eff18e2bd
Reviewed-on: https://go-review.googlesource.com/42591
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Marvin Stenger <marvin.stenger94@gmail.com>
Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
Josh Bleecher Snyder 2017-05-04 07:55:00 -07:00
parent 09b71d563a
commit 53e62aba2f
4 changed files with 24 additions and 22 deletions

View File

@ -311,9 +311,8 @@ func genhash(sym *types.Sym, t *types.Type) {
old_safemode := safemode old_safemode := safemode
safemode = false safemode = false
disable_checknil++ fn.Func.SetNilCheckDisabled(true)
funccompile(fn) funccompile(fn)
disable_checknil--
safemode = old_safemode safemode = old_safemode
} }
@ -500,12 +499,10 @@ func geneq(sym *types.Sym, t *types.Type) {
// We are comparing a struct or an array, // We are comparing a struct or an array,
// neither of which can be nil, and our comparisons // neither of which can be nil, and our comparisons
// are shallow. // are shallow.
disable_checknil++ fn.Func.SetNilCheckDisabled(true)
funccompile(fn) funccompile(fn)
safemode = old_safemode safemode = old_safemode
disable_checknil--
} }
// eqfield returns the node // eqfield returns the node

View File

@ -1087,6 +1087,8 @@ var concurrentFlagOK = [256]bool{
'I': true, // add `directory` to import search path 'I': true, // add `directory` to import search path
'N': true, // disable optimizations 'N': true, // disable optimizations
'l': true, // disable inlining 'l': true, // disable inlining
'w': true, // all printing happens before compilation
'W': true, // all printing happens before compilation
} }
func concurrentBackendAllowed() bool { func concurrentBackendAllowed() bool {

View File

@ -3399,7 +3399,7 @@ func (s *state) exprPtr(n *Node, bounded bool, lineno src.XPos) *ssa.Value {
// Used only for automatically inserted nil checks, // Used only for automatically inserted nil checks,
// not for user code like 'x != nil'. // not for user code like 'x != nil'.
func (s *state) nilCheck(ptr *ssa.Value) { func (s *state) nilCheck(ptr *ssa.Value) {
if disable_checknil != 0 { if disable_checknil != 0 || s.curfn.Func.NilCheckDisabled() {
return return
} }
s.newValue2(ssa.OpNilCheck, ssa.TypeVoid, ptr, s.mem()) s.newValue2(ssa.OpNilCheck, ssa.TypeVoid, ptr, s.mem())

View File

@ -386,25 +386,28 @@ const (
funcNeedctxt // function uses context register (has closure variables) funcNeedctxt // function uses context register (has closure variables)
funcReflectMethod // function calls reflect.Type.Method or MethodByName funcReflectMethod // function calls reflect.Type.Method or MethodByName
funcIsHiddenClosure funcIsHiddenClosure
funcNoFramePointer // Must not use a frame pointer for this function funcNoFramePointer // Must not use a frame pointer for this function
funcHasDefer // contains a defer statement funcHasDefer // contains a defer statement
funcNilCheckDisabled // disable nil checks when compiling this function
) )
func (f *Func) Dupok() bool { return f.flags&funcDupok != 0 } func (f *Func) Dupok() bool { return f.flags&funcDupok != 0 }
func (f *Func) Wrapper() bool { return f.flags&funcWrapper != 0 } func (f *Func) Wrapper() bool { return f.flags&funcWrapper != 0 }
func (f *Func) Needctxt() bool { return f.flags&funcNeedctxt != 0 } func (f *Func) Needctxt() bool { return f.flags&funcNeedctxt != 0 }
func (f *Func) ReflectMethod() bool { return f.flags&funcReflectMethod != 0 } func (f *Func) ReflectMethod() bool { return f.flags&funcReflectMethod != 0 }
func (f *Func) IsHiddenClosure() bool { return f.flags&funcIsHiddenClosure != 0 } func (f *Func) IsHiddenClosure() bool { return f.flags&funcIsHiddenClosure != 0 }
func (f *Func) NoFramePointer() bool { return f.flags&funcNoFramePointer != 0 } func (f *Func) NoFramePointer() bool { return f.flags&funcNoFramePointer != 0 }
func (f *Func) HasDefer() bool { return f.flags&funcHasDefer != 0 } func (f *Func) HasDefer() bool { return f.flags&funcHasDefer != 0 }
func (f *Func) NilCheckDisabled() bool { return f.flags&funcNilCheckDisabled != 0 }
func (f *Func) SetDupok(b bool) { f.flags.set(funcDupok, b) } func (f *Func) SetDupok(b bool) { f.flags.set(funcDupok, b) }
func (f *Func) SetWrapper(b bool) { f.flags.set(funcWrapper, b) } func (f *Func) SetWrapper(b bool) { f.flags.set(funcWrapper, b) }
func (f *Func) SetNeedctxt(b bool) { f.flags.set(funcNeedctxt, b) } func (f *Func) SetNeedctxt(b bool) { f.flags.set(funcNeedctxt, b) }
func (f *Func) SetReflectMethod(b bool) { f.flags.set(funcReflectMethod, b) } func (f *Func) SetReflectMethod(b bool) { f.flags.set(funcReflectMethod, b) }
func (f *Func) SetIsHiddenClosure(b bool) { f.flags.set(funcIsHiddenClosure, b) } func (f *Func) SetIsHiddenClosure(b bool) { f.flags.set(funcIsHiddenClosure, b) }
func (f *Func) SetNoFramePointer(b bool) { f.flags.set(funcNoFramePointer, b) } func (f *Func) SetNoFramePointer(b bool) { f.flags.set(funcNoFramePointer, b) }
func (f *Func) SetHasDefer(b bool) { f.flags.set(funcHasDefer, b) } func (f *Func) SetHasDefer(b bool) { f.flags.set(funcHasDefer, b) }
func (f *Func) SetNilCheckDisabled(b bool) { f.flags.set(funcNilCheckDisabled, b) }
type Op uint8 type Op uint8