From ef3571bf076f4255579bedb3409bdccc91555b86 Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Wed, 20 Nov 2019 20:12:38 -0500 Subject: [PATCH] cmd/internal/obj/mips: mark restartable sequences 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 TryBot-Result: Gobot Gobot Reviewed-by: Austin Clements --- src/cmd/internal/obj/mips/asm0.go | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/cmd/internal/obj/mips/asm0.go b/src/cmd/internal/obj/mips/asm0.go index 957f2d5c93..faa12bf133 100644 --- a/src/cmd/internal/obj/mips/asm0.go +++ b/src/cmd/internal/obj/mips/asm0.go @@ -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 } -- 2.50.0