]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj/mips: mark restartable sequences
authorCherry Zhang <cherryyz@google.com>
Thu, 21 Nov 2019 01:12:38 +0000 (20:12 -0500)
committerCherry Zhang <cherryyz@google.com>
Wed, 6 May 2020 15:41:25 +0000 (15:41 +0000)
Following CL 208126, do the same for MIPS.

Change-Id: I95f8fc99a234524119a4d29c7695676dc0ea1025
Reviewed-on: https://go-review.googlesource.com/c/go/+/208217
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
src/cmd/internal/obj/mips/asm0.go

index 957f2d5c93d04fa4034f1fd47fec5b312e277099..faa12bf133a190fea7d390a1a03dfd1339563ae7 100644 (file)
@@ -526,16 +526,29 @@ func span0(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
        // We use REGTMP as a scratch register during call injection,
        // so instruction sequences that use REGTMP are unsafe to
        // preempt asynchronously.
-       obj.MarkUnsafePoints(c.ctxt, c.cursym.Func.Text, c.newprog, c.isUnsafePoint, nil)
+       obj.MarkUnsafePoints(c.ctxt, c.cursym.Func.Text, c.newprog, c.isUnsafePoint, c.isRestartable)
 }
 
-// Return whether p is an unsafe point.
+// isUnsafePoint returns whether p is an unsafe point.
 func (c *ctxt0) isUnsafePoint(p *obj.Prog) bool {
-       if p.From.Reg == REGTMP || p.To.Reg == REGTMP || p.Reg == REGTMP {
-               return true
+       // If p explicitly uses REGTMP, it's unsafe to preempt, because the
+       // preemption sequence clobbers REGTMP.
+       return p.From.Reg == REGTMP || p.To.Reg == REGTMP || p.Reg == REGTMP
+}
+
+// isRestartable returns whether p is a multi-instruction sequence that,
+// if preempted, can be restarted.
+func (c *ctxt0) isRestartable(p *obj.Prog) bool {
+       if c.isUnsafePoint(p) {
+               return false
        }
-       // Most of the multi-instruction sequence uses REGTMP, except
-       // ones marked safe.
+       // If p is a multi-instruction sequence with uses REGTMP inserted by
+       // the assembler in order to materialize a large constant/offset, we
+       // can restart p (at the start of the instruction sequence), recompute
+       // the content of REGTMP, upon async preemption. Currently, all cases
+       // of assembler-inserted REGTMP fall into this category.
+       // If p doesn't use REGTMP, it can be simply preempted, so we don't
+       // mark it.
        o := c.oplook(p)
        return o.size > 4 && o.flag&NOTUSETMP == 0
 }