Commit 53e62aba authored by Josh Bleecher Snyder's avatar Josh Bleecher Snyder

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: 's avatarMarvin Stenger <marvin.stenger94@gmail.com>
Reviewed-by: 's avatarRobert Griesemer <gri@golang.org>
parent 09b71d56
......@@ -311,9 +311,8 @@ func genhash(sym *types.Sym, t *types.Type) {
old_safemode := safemode
safemode = false
disable_checknil++
fn.Func.SetNilCheckDisabled(true)
funccompile(fn)
disable_checknil--
safemode = old_safemode
}
......@@ -500,12 +499,10 @@ func geneq(sym *types.Sym, t *types.Type) {
// We are comparing a struct or an array,
// neither of which can be nil, and our comparisons
// are shallow.
disable_checknil++
fn.Func.SetNilCheckDisabled(true)
funccompile(fn)
safemode = old_safemode
disable_checknil--
}
// eqfield returns the node
......
......@@ -1087,6 +1087,8 @@ var concurrentFlagOK = [256]bool{
'I': true, // add `directory` to import search path
'N': true, // disable optimizations
'l': true, // disable inlining
'w': true, // all printing happens before compilation
'W': true, // all printing happens before compilation
}
func concurrentBackendAllowed() bool {
......
......@@ -3399,7 +3399,7 @@ func (s *state) exprPtr(n *Node, bounded bool, lineno src.XPos) *ssa.Value {
// Used only for automatically inserted nil checks,
// not for user code like 'x != nil'.
func (s *state) nilCheck(ptr *ssa.Value) {
if disable_checknil != 0 {
if disable_checknil != 0 || s.curfn.Func.NilCheckDisabled() {
return
}
s.newValue2(ssa.OpNilCheck, ssa.TypeVoid, ptr, s.mem())
......
......@@ -386,25 +386,28 @@ const (
funcNeedctxt // function uses context register (has closure variables)
funcReflectMethod // function calls reflect.Type.Method or MethodByName
funcIsHiddenClosure
funcNoFramePointer // Must not use a frame pointer for this function
funcHasDefer // contains a defer statement
funcNoFramePointer // Must not use a frame pointer for this function
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) Wrapper() bool { return f.flags&funcWrapper != 0 }
func (f *Func) Needctxt() bool { return f.flags&funcNeedctxt != 0 }
func (f *Func) ReflectMethod() bool { return f.flags&funcReflectMethod != 0 }
func (f *Func) IsHiddenClosure() bool { return f.flags&funcIsHiddenClosure != 0 }
func (f *Func) NoFramePointer() bool { return f.flags&funcNoFramePointer != 0 }
func (f *Func) HasDefer() bool { return f.flags&funcHasDefer != 0 }
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) SetNeedctxt(b bool) { f.flags.set(funcNeedctxt, 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) SetNoFramePointer(b bool) { f.flags.set(funcNoFramePointer, b) }
func (f *Func) SetHasDefer(b bool) { f.flags.set(funcHasDefer, b) }
func (f *Func) Dupok() bool { return f.flags&funcDupok != 0 }
func (f *Func) Wrapper() bool { return f.flags&funcWrapper != 0 }
func (f *Func) Needctxt() bool { return f.flags&funcNeedctxt != 0 }
func (f *Func) ReflectMethod() bool { return f.flags&funcReflectMethod != 0 }
func (f *Func) IsHiddenClosure() bool { return f.flags&funcIsHiddenClosure != 0 }
func (f *Func) NoFramePointer() bool { return f.flags&funcNoFramePointer != 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) SetWrapper(b bool) { f.flags.set(funcWrapper, 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) SetIsHiddenClosure(b bool) { f.flags.set(funcIsHiddenClosure, 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) SetNilCheckDisabled(b bool) { f.flags.set(funcNilCheckDisabled, b) }
type Op uint8
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment