mirror of
https://github.com/golang/go
synced 2024-09-04 23:44:16 +00:00
[dev.typeparams] cmd/compile: simplify openDeferSave
Now it is only used to save the deferred the function (closure), which must be a function type. Simplify the code. Change-Id: Id4b8f2760fbf39a95883df2327f97378e7edab88 Reviewed-on: https://go-review.googlesource.com/c/go/+/326060 Trust: Cherry Mui <cherryyz@google.com> Run-TryBot: Cherry Mui <cherryyz@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Than McIntosh <thanm@google.com>
This commit is contained in:
parent
74b0b2772a
commit
c0a86c10f1
|
@ -4672,7 +4672,7 @@ func (s *state) openDeferRecord(n *ir.CallExpr) {
|
||||||
// runtime panic code to use. But in the defer exit code, we will
|
// runtime panic code to use. But in the defer exit code, we will
|
||||||
// call the function directly if it is a static function.
|
// call the function directly if it is a static function.
|
||||||
closureVal := s.expr(fn)
|
closureVal := s.expr(fn)
|
||||||
closure := s.openDeferSave(nil, fn.Type(), closureVal)
|
closure := s.openDeferSave(fn.Type(), closureVal)
|
||||||
opendefer.closureNode = closure.Aux.(*ir.Name)
|
opendefer.closureNode = closure.Aux.(*ir.Name)
|
||||||
if !(fn.Op() == ir.ONAME && fn.(*ir.Name).Class == ir.PFUNC) {
|
if !(fn.Op() == ir.ONAME && fn.(*ir.Name).Class == ir.PFUNC) {
|
||||||
opendefer.closure = closure
|
opendefer.closure = closure
|
||||||
|
@ -4690,57 +4690,47 @@ func (s *state) openDeferRecord(n *ir.CallExpr) {
|
||||||
|
|
||||||
// openDeferSave generates SSA nodes to store a value (with type t) for an
|
// openDeferSave generates SSA nodes to store a value (with type t) for an
|
||||||
// open-coded defer at an explicit autotmp location on the stack, so it can be
|
// open-coded defer at an explicit autotmp location on the stack, so it can be
|
||||||
// reloaded and used for the appropriate call on exit. If type t is SSAable, then
|
// reloaded and used for the appropriate call on exit. Type t must be a function type
|
||||||
// val must be non-nil (and n should be nil) and val is the value to be stored. If
|
// (therefore SSAable). val is the value to be stored. The function returns an SSA
|
||||||
// type t is non-SSAable, then n must be non-nil (and val should be nil) and n is
|
// value representing a pointer to the autotmp location.
|
||||||
// evaluated (via s.addr() below) to get the value that is to be stored. The
|
func (s *state) openDeferSave(t *types.Type, val *ssa.Value) *ssa.Value {
|
||||||
// function returns an SSA value representing a pointer to the autotmp location.
|
if !TypeOK(t) {
|
||||||
func (s *state) openDeferSave(n ir.Node, t *types.Type, val *ssa.Value) *ssa.Value {
|
s.Fatalf("openDeferSave of non-SSA-able type %v val=%v", t, val)
|
||||||
canSSA := TypeOK(t)
|
|
||||||
var pos src.XPos
|
|
||||||
if canSSA {
|
|
||||||
pos = val.Pos
|
|
||||||
} else {
|
|
||||||
pos = n.Pos()
|
|
||||||
}
|
}
|
||||||
argTemp := typecheck.TempAt(pos.WithNotStmt(), s.curfn, t)
|
if !t.HasPointers() {
|
||||||
argTemp.SetOpenDeferSlot(true)
|
s.Fatalf("openDeferSave of pointerless type %v val=%v", t, val)
|
||||||
var addrArgTemp *ssa.Value
|
}
|
||||||
// Use OpVarLive to make sure stack slots for the args, etc. are not
|
pos := val.Pos
|
||||||
// removed by dead-store elimination
|
temp := typecheck.TempAt(pos.WithNotStmt(), s.curfn, t)
|
||||||
|
temp.SetOpenDeferSlot(true)
|
||||||
|
var addrTemp *ssa.Value
|
||||||
|
// Use OpVarLive to make sure stack slot for the closure is not removed by
|
||||||
|
// dead-store elimination
|
||||||
if s.curBlock.ID != s.f.Entry.ID {
|
if s.curBlock.ID != s.f.Entry.ID {
|
||||||
// Force the argtmp storing this defer function/receiver/arg to be
|
// Force the tmp storing this defer function to be declared in the entry
|
||||||
// declared in the entry block, so that it will be live for the
|
// block, so that it will be live for the defer exit code (which will
|
||||||
// defer exit code (which will actually access it only if the
|
// actually access it only if the associated defer call has been activated).
|
||||||
// associated defer call has been activated).
|
s.defvars[s.f.Entry.ID][memVar] = s.f.Entry.NewValue1A(src.NoXPos, ssa.OpVarDef, types.TypeMem, temp, s.defvars[s.f.Entry.ID][memVar])
|
||||||
s.defvars[s.f.Entry.ID][memVar] = s.f.Entry.NewValue1A(src.NoXPos, ssa.OpVarDef, types.TypeMem, argTemp, s.defvars[s.f.Entry.ID][memVar])
|
s.defvars[s.f.Entry.ID][memVar] = s.f.Entry.NewValue1A(src.NoXPos, ssa.OpVarLive, types.TypeMem, temp, s.defvars[s.f.Entry.ID][memVar])
|
||||||
s.defvars[s.f.Entry.ID][memVar] = s.f.Entry.NewValue1A(src.NoXPos, ssa.OpVarLive, types.TypeMem, argTemp, s.defvars[s.f.Entry.ID][memVar])
|
addrTemp = s.f.Entry.NewValue2A(src.NoXPos, ssa.OpLocalAddr, types.NewPtr(temp.Type()), temp, s.sp, s.defvars[s.f.Entry.ID][memVar])
|
||||||
addrArgTemp = s.f.Entry.NewValue2A(src.NoXPos, ssa.OpLocalAddr, types.NewPtr(argTemp.Type()), argTemp, s.sp, s.defvars[s.f.Entry.ID][memVar])
|
|
||||||
} else {
|
} else {
|
||||||
// Special case if we're still in the entry block. We can't use
|
// Special case if we're still in the entry block. We can't use
|
||||||
// the above code, since s.defvars[s.f.Entry.ID] isn't defined
|
// the above code, since s.defvars[s.f.Entry.ID] isn't defined
|
||||||
// until we end the entry block with s.endBlock().
|
// until we end the entry block with s.endBlock().
|
||||||
s.vars[memVar] = s.newValue1Apos(ssa.OpVarDef, types.TypeMem, argTemp, s.mem(), false)
|
s.vars[memVar] = s.newValue1Apos(ssa.OpVarDef, types.TypeMem, temp, s.mem(), false)
|
||||||
s.vars[memVar] = s.newValue1Apos(ssa.OpVarLive, types.TypeMem, argTemp, s.mem(), false)
|
s.vars[memVar] = s.newValue1Apos(ssa.OpVarLive, types.TypeMem, temp, s.mem(), false)
|
||||||
addrArgTemp = s.newValue2Apos(ssa.OpLocalAddr, types.NewPtr(argTemp.Type()), argTemp, s.sp, s.mem(), false)
|
addrTemp = s.newValue2Apos(ssa.OpLocalAddr, types.NewPtr(temp.Type()), temp, s.sp, s.mem(), false)
|
||||||
}
|
|
||||||
if t.HasPointers() {
|
|
||||||
// Since we may use this argTemp during exit depending on the
|
|
||||||
// deferBits, we must define it unconditionally on entry.
|
|
||||||
// Therefore, we must make sure it is zeroed out in the entry
|
|
||||||
// block if it contains pointers, else GC may wrongly follow an
|
|
||||||
// uninitialized pointer value.
|
|
||||||
argTemp.SetNeedzero(true)
|
|
||||||
}
|
|
||||||
if !canSSA {
|
|
||||||
a := s.addr(n)
|
|
||||||
s.move(t, addrArgTemp, a)
|
|
||||||
return addrArgTemp
|
|
||||||
}
|
}
|
||||||
|
// Since we may use this temp during exit depending on the
|
||||||
|
// deferBits, we must define it unconditionally on entry.
|
||||||
|
// Therefore, we must make sure it is zeroed out in the entry
|
||||||
|
// block if it contains pointers, else GC may wrongly follow an
|
||||||
|
// uninitialized pointer value.
|
||||||
|
temp.SetNeedzero(true)
|
||||||
// We are storing to the stack, hence we can avoid the full checks in
|
// We are storing to the stack, hence we can avoid the full checks in
|
||||||
// storeType() (no write barrier) and do a simple store().
|
// storeType() (no write barrier) and do a simple store().
|
||||||
s.store(t, addrArgTemp, val)
|
s.store(t, addrTemp, val)
|
||||||
return addrArgTemp
|
return addrTemp
|
||||||
}
|
}
|
||||||
|
|
||||||
// openDeferExit generates SSA for processing all the open coded defers at exit.
|
// openDeferExit generates SSA for processing all the open coded defers at exit.
|
||||||
|
|
Loading…
Reference in a new issue