p.To.Type = obj.TYPE_REG
p.To.Reg = REG_R1
+ // Mark the stack bound check and morestack call async nonpreemptible.
+ // If we get preempted here, when resumed the preemption request is
+ // cleared, but we'll still call morestack, which will double the stack
+ // unnecessarily. See issue #35470.
+ p = c.ctxt.StartUnsafePoint(p, c.newprog)
+
if framesize <= objabi.StackSmall {
// small stack: SP < stackguard
// CMP stackguard, SP
bls.As = ABLS
bls.To.Type = obj.TYPE_BRANCH
+ end := c.ctxt.EndUnsafePoint(bls, c.newprog, -1)
+
var last *obj.Prog
for last = c.cursym.Func.Text; last.Link != nil; last = last.Link {
}
spfix.As = obj.ANOP
spfix.Spadj = -framesize
- pcdata := c.ctxt.EmitEntryLiveness(c.cursym, spfix, c.newprog)
+ pcdata := c.ctxt.EmitEntryStackMap(c.cursym, spfix, c.newprog)
+ pcdata = c.ctxt.StartUnsafePoint(pcdata, c.newprog)
// MOVW LR, R3
movw := obj.Appendp(pcdata, c.newprog)
}
call.To.Sym = c.ctxt.Lookup(morestack)
+ pcdata = c.ctxt.EndUnsafePoint(call, c.newprog, -1)
+
// B start
- b := obj.Appendp(call, c.newprog)
+ b := obj.Appendp(pcdata, c.newprog)
b.As = obj.AJMP
b.To.Type = obj.TYPE_BRANCH
b.Pcond = c.cursym.Func.Text.Link
b.Spadj = +framesize
- return bls
+ return end
}
var unaryDst = map[obj.As]bool{
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_R1
+ // Mark the stack bound check and morestack call async nonpreemptible.
+ // If we get preempted here, when resumed the preemption request is
+ // cleared, but we'll still call morestack, which will double the stack
+ // unnecessarily. See issue #35470.
+ p = c.ctxt.StartUnsafePoint(p, c.newprog)
+
q := (*obj.Prog)(nil)
if framesize <= objabi.StackSmall {
// small stack: SP < stackguard
bls.As = ABLS
bls.To.Type = obj.TYPE_BRANCH
+ end := c.ctxt.EndUnsafePoint(bls, c.newprog, -1)
+
var last *obj.Prog
for last = c.cursym.Func.Text; last.Link != nil; last = last.Link {
}
spfix.As = obj.ANOP
spfix.Spadj = -framesize
- pcdata := c.ctxt.EmitEntryLiveness(c.cursym, spfix, c.newprog)
+ pcdata := c.ctxt.EmitEntryStackMap(c.cursym, spfix, c.newprog)
+ pcdata = c.ctxt.StartUnsafePoint(pcdata, c.newprog)
// MOV LR, R3
movlr := obj.Appendp(pcdata, c.newprog)
}
call.To.Sym = c.ctxt.Lookup(morestack)
+ pcdata = c.ctxt.EndUnsafePoint(call, c.newprog, -1)
+
// B start
- jmp := obj.Appendp(call, c.newprog)
+ jmp := obj.Appendp(pcdata, c.newprog)
jmp.As = AB
jmp.To.Type = obj.TYPE_BRANCH
jmp.Pcond = c.cursym.Func.Text.Link
jmp.Spadj = +framesize
- // placeholder for bls's jump target
- // p = obj.Appendp(ctxt, p)
- // p.As = obj.ANOP
-
- return bls
+ return end
}
func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_R1
+ // Mark the stack bound check and morestack call async nonpreemptible.
+ // If we get preempted here, when resumed the preemption request is
+ // cleared, but we'll still call morestack, which will double the stack
+ // unnecessarily. See issue #35470.
+ p = c.ctxt.StartUnsafePoint(p, c.newprog)
+
var q *obj.Prog
if framesize <= objabi.StackSmall {
// small stack: SP < stackguard
p.Mark |= LABEL
}
- p = c.ctxt.EmitEntryLiveness(c.cursym, p, c.newprog)
+ p = c.ctxt.EmitEntryStackMap(c.cursym, p, c.newprog)
// JAL runtime.morestack(SB)
p = obj.Appendp(p, c.newprog)
}
p.Mark |= BRANCH
+ p = c.ctxt.EndUnsafePoint(p, c.newprog, -1)
+
// JMP start
p = obj.Appendp(p, c.newprog)
// liveness map active at the entry of function s. It returns the last
// Prog generated.
func (ctxt *Link) EmitEntryLiveness(s *LSym, p *Prog, newprog ProgAlloc) *Prog {
+ pcdata := ctxt.EmitEntryStackMap(s, p, newprog)
+ pcdata = ctxt.EmitEntryRegMap(s, pcdata, newprog)
+ return pcdata
+}
+
+// Similar to EmitEntryLiveness, but just emit stack map.
+func (ctxt *Link) EmitEntryStackMap(s *LSym, p *Prog, newprog ProgAlloc) *Prog {
pcdata := Appendp(p, newprog)
pcdata.Pos = s.Func.Text.Pos
pcdata.As = APCDATA
pcdata.To.Type = TYPE_CONST
pcdata.To.Offset = -1 // pcdata starts at -1 at function entry
- // Same, with register map.
- pcdata = Appendp(pcdata, newprog)
+ return pcdata
+}
+
+// Similar to EmitEntryLiveness, but just emit register map.
+func (ctxt *Link) EmitEntryRegMap(s *LSym, p *Prog, newprog ProgAlloc) *Prog {
+ pcdata := Appendp(p, newprog)
pcdata.Pos = s.Func.Text.Pos
pcdata.As = APCDATA
pcdata.From.Type = TYPE_CONST
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_R3
+ // Mark the stack bound check and morestack call async nonpreemptible.
+ // If we get preempted here, when resumed the preemption request is
+ // cleared, but we'll still call morestack, which will double the stack
+ // unnecessarily. See issue #35470.
+ p = c.ctxt.StartUnsafePoint(p, c.newprog)
+
var q *obj.Prog
if framesize <= objabi.StackSmall {
// small stack: SP < stackguard
q.Pcond = p
}
- p = c.ctxt.EmitEntryLiveness(c.cursym, p, c.newprog)
+ p = c.ctxt.EmitEntryStackMap(c.cursym, p, c.newprog)
var morestacksym *obj.LSym
if c.cursym.CFunc() {
p.To.Reg = REG_R2
}
+ p = c.ctxt.EndUnsafePoint(p, c.newprog, -1)
+
// BR start
p = obj.Appendp(p, c.newprog)
p.As = ABR
if !p.From.Sym.NoSplit() {
p, pPreempt = c.stacksplitPre(p, autosize) // emit pre part of split check
pPre = p
+ p = c.ctxt.EndUnsafePoint(p, c.newprog, -1)
wasSplit = true //need post part of split
}
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_R3
+ // Mark the stack bound check and morestack call async nonpreemptible.
+ // If we get preempted here, when resumed the preemption request is
+ // cleared, but we'll still call morestack, which will double the stack
+ // unnecessarily. See issue #35470.
+ p = c.ctxt.StartUnsafePoint(p, c.newprog)
+
q = nil
if framesize <= objabi.StackSmall {
// small stack: SP < stackguard
- // CMP stackguard, SP
-
- //p.To.Type = obj.TYPE_REG
- //p.To.Reg = REGSP
-
- // q1: BLT done
+ // CMPUBGE stackguard, SP, label-of-call-to-morestack
p = obj.Appendp(p, c.newprog)
//q1 = p
p.Reg = REGSP
p.As = ACMPUBGE
p.To.Type = obj.TYPE_BRANCH
- //p = obj.Appendp(ctxt, p)
-
- //p.As = ACMPU
- //p.From.Type = obj.TYPE_REG
- //p.From.Reg = REG_R3
- //p.To.Type = obj.TYPE_REG
- //p.To.Reg = REGSP
-
- //p = obj.Appendp(ctxt, p)
- //p.As = ABGE
- //p.To.Type = obj.TYPE_BRANCH
} else if framesize <= objabi.StackBig {
// large stack: SP-framesize < stackguard-StackSmall
// ADD $-(framesize-StackSmall), SP, R4
- // CMP stackguard, R4
+ // CMPUBGE stackguard, R4, label-of-call-to-morestack
p = obj.Appendp(p, c.newprog)
p.As = AADD
// ADD $StackGuard, SP, R4
// SUB R3, R4
// MOVD $(framesize+(StackGuard-StackSmall)), TEMP
- // CMPUBGE TEMP, R4
+ // CMPUBGE TEMP, R4, label-of-call-to-morestack
p = obj.Appendp(p, c.newprog)
p.As = ACMP
spfix.As = obj.ANOP
spfix.Spadj = -framesize
- pcdata := c.ctxt.EmitEntryLiveness(c.cursym, spfix, c.newprog)
+ pcdata := c.ctxt.EmitEntryStackMap(c.cursym, spfix, c.newprog)
+ pcdata = c.ctxt.StartUnsafePoint(pcdata, c.newprog)
// MOVD LR, R5
p = obj.Appendp(pcdata, c.newprog)
p.To.Sym = c.ctxt.Lookup("runtime.morestack")
}
+ p = c.ctxt.EndUnsafePoint(p, c.newprog, -1)
+
// BR start
p = obj.Appendp(p, c.newprog)
if cursym.CFunc() {
p.To.Offset = 3 * int64(ctxt.Arch.PtrSize) // G.stackguard1
}
+
+ // Mark the stack bound check and morestack call async nonpreemptible.
+ // If we get preempted here, when resumed the preemption request is
+ // cleared, but we'll still call morestack, which will double the stack
+ // unnecessarily. See issue #35470.
+ p = ctxt.StartUnsafePoint(p, newprog)
} else if framesize <= objabi.StackBig {
// large stack: SP-framesize <= stackguard-StackSmall
// LEAQ -xxx(SP), AX
if cursym.CFunc() {
p.To.Offset = 3 * int64(ctxt.Arch.PtrSize) // G.stackguard1
}
+
+ p = ctxt.StartUnsafePoint(p, newprog) // see the comment above
} else {
// Such a large stack we need to protect against wraparound.
// If SP is close to zero:
//
// Preemption sets stackguard to StackPreempt, a very large value.
// That breaks the math above, so we have to check for that explicitly.
- // MOVQ stackguard, CX
- // CMPQ CX, $StackPreempt
+ // MOVQ stackguard, SI
+ // CMPQ SI, $StackPreempt
// JEQ label-of-call-to-morestack
// LEAQ StackGuard(SP), AX
- // SUBQ CX, AX
+ // SUBQ SI, AX
// CMPQ AX, $(framesize+(StackGuard-StackSmall))
p = obj.Appendp(p, newprog)
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_SI
+ p = ctxt.StartUnsafePoint(p, newprog) // see the comment above
+
p = obj.Appendp(p, newprog)
p.As = cmp
p.From.Type = obj.TYPE_REG
jls.As = AJLS
jls.To.Type = obj.TYPE_BRANCH
+ end := ctxt.EndUnsafePoint(jls, newprog, -1)
+
var last *obj.Prog
for last = cursym.Func.Text; last.Link != nil; last = last.Link {
}
spfix.As = obj.ANOP
spfix.Spadj = -framesize
- pcdata := ctxt.EmitEntryLiveness(cursym, spfix, newprog)
+ pcdata := ctxt.EmitEntryStackMap(cursym, spfix, newprog)
+ pcdata = ctxt.StartUnsafePoint(pcdata, newprog)
call := obj.Appendp(pcdata, newprog)
call.Pos = cursym.Func.Text.Pos
progedit(ctxt, callend.Link, newprog)
}
- jmp := obj.Appendp(callend, newprog)
+ pcdata = ctxt.EndUnsafePoint(callend, newprog, -1)
+
+ jmp := obj.Appendp(pcdata, newprog)
jmp.As = obj.AJMP
jmp.To.Type = obj.TYPE_BRANCH
jmp.Pcond = cursym.Func.Text.Link
q1.Pcond = call
}
- return jls
+ return end
}
var unaryDst = map[obj.As]bool{