mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
runtime: add deletion barriers on gobuf.ctxt
gobuf.ctxt is set to nil from many places in assembly code and these assignments require write barriers with the hybrid barrier. Conveniently, in most of these places ctxt should already be nil, in which case we don't need the barrier. This commit changes these places to assert that ctxt is already nil. gogo is more complicated, since ctxt may not already be nil. For gogo, we manually perform the write barrier if ctxt is not nil. Updates #17503. Change-Id: I9d75e27c75a1b7f8b715ad112fc5d45ffa856d30 Reviewed-on: https://go-review.googlesource.com/31764 Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
parent
8f81dfe8b4
commit
70c107c68d
9 changed files with 186 additions and 25 deletions
|
|
@ -209,7 +209,11 @@ TEXT runtime·gosave(SB), NOSPLIT, $0-4
|
||||||
MOVL 0(SP), BX // caller's PC
|
MOVL 0(SP), BX // caller's PC
|
||||||
MOVL BX, gobuf_pc(AX)
|
MOVL BX, gobuf_pc(AX)
|
||||||
MOVL $0, gobuf_ret(AX)
|
MOVL $0, gobuf_ret(AX)
|
||||||
MOVL $0, gobuf_ctxt(AX)
|
// Assert ctxt is zero. See func save.
|
||||||
|
MOVL gobuf_ctxt(AX), BX
|
||||||
|
TESTL BX, BX
|
||||||
|
JZ 2(PC)
|
||||||
|
CALL runtime·badctxt(SB)
|
||||||
get_tls(CX)
|
get_tls(CX)
|
||||||
MOVL g(CX), BX
|
MOVL g(CX), BX
|
||||||
MOVL BX, gobuf_g(AX)
|
MOVL BX, gobuf_g(AX)
|
||||||
|
|
@ -217,8 +221,20 @@ TEXT runtime·gosave(SB), NOSPLIT, $0-4
|
||||||
|
|
||||||
// void gogo(Gobuf*)
|
// void gogo(Gobuf*)
|
||||||
// restore state from Gobuf; longjmp
|
// restore state from Gobuf; longjmp
|
||||||
TEXT runtime·gogo(SB), NOSPLIT, $0-4
|
TEXT runtime·gogo(SB), NOSPLIT, $8-4
|
||||||
MOVL buf+0(FP), BX // gobuf
|
MOVL buf+0(FP), BX // gobuf
|
||||||
|
|
||||||
|
// If ctxt is not nil, invoke deletion barrier before overwriting.
|
||||||
|
MOVL gobuf_ctxt(BX), DX
|
||||||
|
TESTL DX, DX
|
||||||
|
JZ nilctxt
|
||||||
|
LEAL gobuf_ctxt(BX), AX
|
||||||
|
MOVL AX, 0(SP)
|
||||||
|
MOVL $0, 4(SP)
|
||||||
|
CALL runtime·writebarrierptr_prewrite(SB)
|
||||||
|
MOVL buf+0(FP), BX
|
||||||
|
|
||||||
|
nilctxt:
|
||||||
MOVL gobuf_g(BX), DX
|
MOVL gobuf_g(BX), DX
|
||||||
MOVL 0(DX), CX // make sure g != nil
|
MOVL 0(DX), CX // make sure g != nil
|
||||||
get_tls(CX)
|
get_tls(CX)
|
||||||
|
|
@ -572,7 +588,11 @@ TEXT gosave<>(SB),NOSPLIT,$0
|
||||||
MOVL -4(AX), AX
|
MOVL -4(AX), AX
|
||||||
MOVL AX, (g_sched+gobuf_pc)(BX)
|
MOVL AX, (g_sched+gobuf_pc)(BX)
|
||||||
MOVL $0, (g_sched+gobuf_ret)(BX)
|
MOVL $0, (g_sched+gobuf_ret)(BX)
|
||||||
MOVL $0, (g_sched+gobuf_ctxt)(BX)
|
// Assert ctxt is zero. See func save.
|
||||||
|
MOVL (g_sched+gobuf_ctxt)(BX), AX
|
||||||
|
TESTL AX, AX
|
||||||
|
JZ 2(PC)
|
||||||
|
CALL runtime·badctxt(SB)
|
||||||
POPL BX
|
POPL BX
|
||||||
POPL AX
|
POPL AX
|
||||||
RET
|
RET
|
||||||
|
|
|
||||||
|
|
@ -182,8 +182,12 @@ TEXT runtime·gosave(SB), NOSPLIT, $0-8
|
||||||
MOVQ 0(SP), BX // caller's PC
|
MOVQ 0(SP), BX // caller's PC
|
||||||
MOVQ BX, gobuf_pc(AX)
|
MOVQ BX, gobuf_pc(AX)
|
||||||
MOVQ $0, gobuf_ret(AX)
|
MOVQ $0, gobuf_ret(AX)
|
||||||
MOVQ $0, gobuf_ctxt(AX)
|
|
||||||
MOVQ BP, gobuf_bp(AX)
|
MOVQ BP, gobuf_bp(AX)
|
||||||
|
// Assert ctxt is zero. See func save.
|
||||||
|
MOVQ gobuf_ctxt(AX), BX
|
||||||
|
TESTQ BX, BX
|
||||||
|
JZ 2(PC)
|
||||||
|
CALL runtime·badctxt(SB)
|
||||||
get_tls(CX)
|
get_tls(CX)
|
||||||
MOVQ g(CX), BX
|
MOVQ g(CX), BX
|
||||||
MOVQ BX, gobuf_g(AX)
|
MOVQ BX, gobuf_g(AX)
|
||||||
|
|
@ -191,8 +195,20 @@ TEXT runtime·gosave(SB), NOSPLIT, $0-8
|
||||||
|
|
||||||
// void gogo(Gobuf*)
|
// void gogo(Gobuf*)
|
||||||
// restore state from Gobuf; longjmp
|
// restore state from Gobuf; longjmp
|
||||||
TEXT runtime·gogo(SB), NOSPLIT, $0-8
|
TEXT runtime·gogo(SB), NOSPLIT, $16-8
|
||||||
MOVQ buf+0(FP), BX // gobuf
|
MOVQ buf+0(FP), BX // gobuf
|
||||||
|
|
||||||
|
// If ctxt is not nil, invoke deletion barrier before overwriting.
|
||||||
|
MOVQ gobuf_ctxt(BX), AX
|
||||||
|
TESTQ AX, AX
|
||||||
|
JZ nilctxt
|
||||||
|
LEAQ gobuf_ctxt(BX), AX
|
||||||
|
MOVQ AX, 0(SP)
|
||||||
|
MOVQ $0, 8(SP)
|
||||||
|
CALL runtime·writebarrierptr_prewrite(SB)
|
||||||
|
MOVQ buf+0(FP), BX
|
||||||
|
|
||||||
|
nilctxt:
|
||||||
MOVQ gobuf_g(BX), DX
|
MOVQ gobuf_g(BX), DX
|
||||||
MOVQ 0(DX), CX // make sure g != nil
|
MOVQ 0(DX), CX // make sure g != nil
|
||||||
get_tls(CX)
|
get_tls(CX)
|
||||||
|
|
@ -546,8 +562,12 @@ TEXT gosave<>(SB),NOSPLIT,$0
|
||||||
LEAQ 8(SP), R9
|
LEAQ 8(SP), R9
|
||||||
MOVQ R9, (g_sched+gobuf_sp)(R8)
|
MOVQ R9, (g_sched+gobuf_sp)(R8)
|
||||||
MOVQ $0, (g_sched+gobuf_ret)(R8)
|
MOVQ $0, (g_sched+gobuf_ret)(R8)
|
||||||
MOVQ $0, (g_sched+gobuf_ctxt)(R8)
|
|
||||||
MOVQ BP, (g_sched+gobuf_bp)(R8)
|
MOVQ BP, (g_sched+gobuf_bp)(R8)
|
||||||
|
// Assert ctxt is zero. See func save.
|
||||||
|
MOVQ (g_sched+gobuf_ctxt)(R8), R9
|
||||||
|
TESTQ R9, R9
|
||||||
|
JZ 2(PC)
|
||||||
|
CALL runtime·badctxt(SB)
|
||||||
RET
|
RET
|
||||||
|
|
||||||
// func asmcgocall(fn, arg unsafe.Pointer) int32
|
// func asmcgocall(fn, arg unsafe.Pointer) int32
|
||||||
|
|
|
||||||
|
|
@ -107,8 +107,12 @@ TEXT runtime·gosave(SB), NOSPLIT, $0-4
|
||||||
MOVL BX, gobuf_sp(AX)
|
MOVL BX, gobuf_sp(AX)
|
||||||
MOVL 0(SP), BX // caller's PC
|
MOVL 0(SP), BX // caller's PC
|
||||||
MOVL BX, gobuf_pc(AX)
|
MOVL BX, gobuf_pc(AX)
|
||||||
MOVL $0, gobuf_ctxt(AX)
|
|
||||||
MOVQ $0, gobuf_ret(AX)
|
MOVQ $0, gobuf_ret(AX)
|
||||||
|
// Assert ctxt is zero. See func save.
|
||||||
|
MOVL gobuf_ctxt(AX), BX
|
||||||
|
TESTL BX, BX
|
||||||
|
JZ 2(PC)
|
||||||
|
CALL runtime·badctxt(SB)
|
||||||
get_tls(CX)
|
get_tls(CX)
|
||||||
MOVL g(CX), BX
|
MOVL g(CX), BX
|
||||||
MOVL BX, gobuf_g(AX)
|
MOVL BX, gobuf_g(AX)
|
||||||
|
|
@ -116,8 +120,20 @@ TEXT runtime·gosave(SB), NOSPLIT, $0-4
|
||||||
|
|
||||||
// void gogo(Gobuf*)
|
// void gogo(Gobuf*)
|
||||||
// restore state from Gobuf; longjmp
|
// restore state from Gobuf; longjmp
|
||||||
TEXT runtime·gogo(SB), NOSPLIT, $0-4
|
TEXT runtime·gogo(SB), NOSPLIT, $8-4
|
||||||
MOVL buf+0(FP), BX // gobuf
|
MOVL buf+0(FP), BX // gobuf
|
||||||
|
|
||||||
|
// If ctxt is not nil, invoke deletion barrier before overwriting.
|
||||||
|
MOVL gobuf_ctxt(BX), DX
|
||||||
|
TESTL DX, DX
|
||||||
|
JZ nilctxt
|
||||||
|
LEAL gobuf_ctxt(BX), AX
|
||||||
|
MOVL AX, 0(SP)
|
||||||
|
MOVL $0, 4(SP)
|
||||||
|
CALL runtime·writebarrierptr_prewrite(SB)
|
||||||
|
MOVL buf+0(FP), BX
|
||||||
|
|
||||||
|
nilctxt:
|
||||||
MOVL gobuf_g(BX), DX
|
MOVL gobuf_g(BX), DX
|
||||||
MOVL 0(DX), CX // make sure g != nil
|
MOVL 0(DX), CX // make sure g != nil
|
||||||
get_tls(CX)
|
get_tls(CX)
|
||||||
|
|
|
||||||
|
|
@ -118,13 +118,30 @@ TEXT runtime·gosave(SB),NOSPLIT,$-4-4
|
||||||
MOVW $0, R11
|
MOVW $0, R11
|
||||||
MOVW R11, gobuf_lr(R0)
|
MOVW R11, gobuf_lr(R0)
|
||||||
MOVW R11, gobuf_ret(R0)
|
MOVW R11, gobuf_ret(R0)
|
||||||
MOVW R11, gobuf_ctxt(R0)
|
// Assert ctxt is zero. See func save.
|
||||||
|
MOVW gobuf_ctxt(R0), R0
|
||||||
|
CMP R0, R11
|
||||||
|
B.EQ 2(PC)
|
||||||
|
CALL runtime·badctxt(SB)
|
||||||
RET
|
RET
|
||||||
|
|
||||||
// void gogo(Gobuf*)
|
// void gogo(Gobuf*)
|
||||||
// restore state from Gobuf; longjmp
|
// restore state from Gobuf; longjmp
|
||||||
TEXT runtime·gogo(SB),NOSPLIT,$-4-4
|
TEXT runtime·gogo(SB),NOSPLIT,$8-4
|
||||||
MOVW buf+0(FP), R1
|
MOVW buf+0(FP), R1
|
||||||
|
|
||||||
|
// If ctxt is not nil, invoke deletion barrier before overwriting.
|
||||||
|
MOVW gobuf_ctxt(R1), R0
|
||||||
|
CMP $0, R0
|
||||||
|
B.EQ nilctxt
|
||||||
|
MOVW $gobuf_ctxt(R1), R0
|
||||||
|
MOVW R0, 4(R13)
|
||||||
|
MOVW $0, R0
|
||||||
|
MOVW R0, 8(R13)
|
||||||
|
BL runtime·writebarrierptr_prewrite(SB)
|
||||||
|
MOVW buf+0(FP), R1
|
||||||
|
|
||||||
|
nilctxt:
|
||||||
MOVW gobuf_g(R1), R0
|
MOVW gobuf_g(R1), R0
|
||||||
BL setg<>(SB)
|
BL setg<>(SB)
|
||||||
|
|
||||||
|
|
@ -476,13 +493,18 @@ TEXT runtime·jmpdefer(SB),NOSPLIT,$0-8
|
||||||
B (R1)
|
B (R1)
|
||||||
|
|
||||||
// Save state of caller into g->sched. Smashes R11.
|
// Save state of caller into g->sched. Smashes R11.
|
||||||
TEXT gosave<>(SB),NOSPLIT,$0
|
TEXT gosave<>(SB),NOSPLIT,$-4
|
||||||
MOVW LR, (g_sched+gobuf_pc)(g)
|
MOVW LR, (g_sched+gobuf_pc)(g)
|
||||||
MOVW R13, (g_sched+gobuf_sp)(g)
|
MOVW R13, (g_sched+gobuf_sp)(g)
|
||||||
MOVW $0, R11
|
MOVW $0, R11
|
||||||
MOVW R11, (g_sched+gobuf_lr)(g)
|
MOVW R11, (g_sched+gobuf_lr)(g)
|
||||||
MOVW R11, (g_sched+gobuf_ret)(g)
|
MOVW R11, (g_sched+gobuf_ret)(g)
|
||||||
MOVW R11, (g_sched+gobuf_ctxt)(g)
|
MOVW R11, (g_sched+gobuf_ctxt)(g)
|
||||||
|
// Assert ctxt is zero. See func save.
|
||||||
|
MOVW (g_sched+gobuf_ctxt)(g), R11
|
||||||
|
CMP $0, R11
|
||||||
|
B.EQ 2(PC)
|
||||||
|
CALL runtime·badctxt(SB)
|
||||||
RET
|
RET
|
||||||
|
|
||||||
// func asmcgocall(fn, arg unsafe.Pointer) int32
|
// func asmcgocall(fn, arg unsafe.Pointer) int32
|
||||||
|
|
|
||||||
|
|
@ -111,13 +111,29 @@ TEXT runtime·gosave(SB), NOSPLIT, $-8-8
|
||||||
MOVD g, gobuf_g(R3)
|
MOVD g, gobuf_g(R3)
|
||||||
MOVD ZR, gobuf_lr(R3)
|
MOVD ZR, gobuf_lr(R3)
|
||||||
MOVD ZR, gobuf_ret(R3)
|
MOVD ZR, gobuf_ret(R3)
|
||||||
MOVD ZR, gobuf_ctxt(R3)
|
// Assert ctxt is zero. See func save.
|
||||||
|
MOVD gobuf_ctxt(R3), R0
|
||||||
|
CMP $0, R0
|
||||||
|
BEQ 2(PC)
|
||||||
|
CALL runtime·badctxt(SB)
|
||||||
RET
|
RET
|
||||||
|
|
||||||
// void gogo(Gobuf*)
|
// void gogo(Gobuf*)
|
||||||
// restore state from Gobuf; longjmp
|
// restore state from Gobuf; longjmp
|
||||||
TEXT runtime·gogo(SB), NOSPLIT, $-8-8
|
TEXT runtime·gogo(SB), NOSPLIT, $24-8
|
||||||
MOVD buf+0(FP), R5
|
MOVD buf+0(FP), R5
|
||||||
|
|
||||||
|
// If ctxt is not nil, invoke deletion barrier before overwriting.
|
||||||
|
MOVD gobuf_ctxt(R5), R0
|
||||||
|
CMP $0, R0
|
||||||
|
BEQ nilctxt
|
||||||
|
MOVD $gobuf_ctxt(R5), R0
|
||||||
|
MOVD R0, 8(RSP)
|
||||||
|
MOVD ZR, 16(RSP)
|
||||||
|
BL runtime·writebarrierptr_prewrite(SB)
|
||||||
|
MOVD buf+0(FP), R5
|
||||||
|
|
||||||
|
nilctxt:
|
||||||
MOVD gobuf_g(R5), g
|
MOVD gobuf_g(R5), g
|
||||||
BL runtime·save_g(SB)
|
BL runtime·save_g(SB)
|
||||||
|
|
||||||
|
|
@ -483,7 +499,11 @@ TEXT gosave<>(SB),NOSPLIT,$-8
|
||||||
MOVD R0, (g_sched+gobuf_sp)(g)
|
MOVD R0, (g_sched+gobuf_sp)(g)
|
||||||
MOVD $0, (g_sched+gobuf_lr)(g)
|
MOVD $0, (g_sched+gobuf_lr)(g)
|
||||||
MOVD $0, (g_sched+gobuf_ret)(g)
|
MOVD $0, (g_sched+gobuf_ret)(g)
|
||||||
MOVD $0, (g_sched+gobuf_ctxt)(g)
|
// Assert ctxt is zero. See func save.
|
||||||
|
MOVD (g_sched+gobuf_ctxt)(g), R0
|
||||||
|
CMP $0, R0
|
||||||
|
BEQ 2(PC)
|
||||||
|
CALL runtime·badctxt(SB)
|
||||||
RET
|
RET
|
||||||
|
|
||||||
// func asmcgocall(fn, arg unsafe.Pointer) int32
|
// func asmcgocall(fn, arg unsafe.Pointer) int32
|
||||||
|
|
|
||||||
|
|
@ -98,13 +98,27 @@ TEXT runtime·gosave(SB), NOSPLIT, $-8-8
|
||||||
MOVV g, gobuf_g(R1)
|
MOVV g, gobuf_g(R1)
|
||||||
MOVV R0, gobuf_lr(R1)
|
MOVV R0, gobuf_lr(R1)
|
||||||
MOVV R0, gobuf_ret(R1)
|
MOVV R0, gobuf_ret(R1)
|
||||||
MOVV R0, gobuf_ctxt(R1)
|
// Assert ctxt is zero. See func save.
|
||||||
|
MOVV gobuf_ctxt(R1), R1
|
||||||
|
BEQ R1, 2(PC)
|
||||||
|
JAL runtime·badctxt(SB)
|
||||||
RET
|
RET
|
||||||
|
|
||||||
// void gogo(Gobuf*)
|
// void gogo(Gobuf*)
|
||||||
// restore state from Gobuf; longjmp
|
// restore state from Gobuf; longjmp
|
||||||
TEXT runtime·gogo(SB), NOSPLIT, $-8-8
|
TEXT runtime·gogo(SB), NOSPLIT, $16-8
|
||||||
MOVV buf+0(FP), R3
|
MOVV buf+0(FP), R3
|
||||||
|
|
||||||
|
// If ctxt is not nil, invoke deletion barrier before overwriting.
|
||||||
|
MOVV gobuf_ctxt(R3), R1
|
||||||
|
BEQ R1, nilctxt
|
||||||
|
MOVV $gobuf_ctxt(R3), R1
|
||||||
|
MOVV R1, 8(R29)
|
||||||
|
MOVV R0, 16(R29)
|
||||||
|
JAL runtime·writebarrierptr_prewrite(SB)
|
||||||
|
MOVV buf+0(FP), R3
|
||||||
|
|
||||||
|
nilctxt:
|
||||||
MOVV gobuf_g(R3), g // make sure g is not nil
|
MOVV gobuf_g(R3), g // make sure g is not nil
|
||||||
JAL runtime·save_g(SB)
|
JAL runtime·save_g(SB)
|
||||||
|
|
||||||
|
|
@ -429,13 +443,16 @@ TEXT runtime·jmpdefer(SB), NOSPLIT, $-8-16
|
||||||
MOVV 0(REGCTXT), R4
|
MOVV 0(REGCTXT), R4
|
||||||
JMP (R4)
|
JMP (R4)
|
||||||
|
|
||||||
// Save state of caller into g->sched. Smashes R31.
|
// Save state of caller into g->sched. Smashes R1.
|
||||||
TEXT gosave<>(SB),NOSPLIT,$-8
|
TEXT gosave<>(SB),NOSPLIT,$-8
|
||||||
MOVV R31, (g_sched+gobuf_pc)(g)
|
MOVV R31, (g_sched+gobuf_pc)(g)
|
||||||
MOVV R29, (g_sched+gobuf_sp)(g)
|
MOVV R29, (g_sched+gobuf_sp)(g)
|
||||||
MOVV R0, (g_sched+gobuf_lr)(g)
|
MOVV R0, (g_sched+gobuf_lr)(g)
|
||||||
MOVV R0, (g_sched+gobuf_ret)(g)
|
MOVV R0, (g_sched+gobuf_ret)(g)
|
||||||
MOVV R0, (g_sched+gobuf_ctxt)(g)
|
// Assert ctxt is zero. See func save.
|
||||||
|
MOVV (g_sched+gobuf_ctxt)(g), R1
|
||||||
|
BEQ R1, 2(PC)
|
||||||
|
JAL runtime·badctxt(SB)
|
||||||
RET
|
RET
|
||||||
|
|
||||||
// func asmcgocall(fn, arg unsafe.Pointer) int32
|
// func asmcgocall(fn, arg unsafe.Pointer) int32
|
||||||
|
|
|
||||||
|
|
@ -122,13 +122,29 @@ TEXT runtime·gosave(SB), NOSPLIT|NOFRAME, $0-8
|
||||||
MOVD g, gobuf_g(R3)
|
MOVD g, gobuf_g(R3)
|
||||||
MOVD R0, gobuf_lr(R3)
|
MOVD R0, gobuf_lr(R3)
|
||||||
MOVD R0, gobuf_ret(R3)
|
MOVD R0, gobuf_ret(R3)
|
||||||
MOVD R0, gobuf_ctxt(R3)
|
// Assert ctxt is zero. See func save.
|
||||||
|
MOVD gobuf_ctxt(R3), R3
|
||||||
|
CMP R0, R3
|
||||||
|
BEQ 2(PC)
|
||||||
|
BL runtime·badctxt(SB)
|
||||||
RET
|
RET
|
||||||
|
|
||||||
// void gogo(Gobuf*)
|
// void gogo(Gobuf*)
|
||||||
// restore state from Gobuf; longjmp
|
// restore state from Gobuf; longjmp
|
||||||
TEXT runtime·gogo(SB), NOSPLIT|NOFRAME, $0-8
|
TEXT runtime·gogo(SB), NOSPLIT, $16-8
|
||||||
MOVD buf+0(FP), R5
|
MOVD buf+0(FP), R5
|
||||||
|
|
||||||
|
// If ctxt is not nil, invoke deletion barrier before overwriting.
|
||||||
|
MOVD gobuf_ctxt(R5), R3
|
||||||
|
CMP R0, R3
|
||||||
|
BEQ nilctxt
|
||||||
|
MOVD $gobuf_ctxt(R5), R3
|
||||||
|
MOVD R3, FIXED_FRAME+0(R1)
|
||||||
|
MOVD R0, FIXED_FRAME+8(R1)
|
||||||
|
BL runtime·writebarrierptr_prewrite(SB)
|
||||||
|
MOVD buf+0(FP), R5
|
||||||
|
|
||||||
|
nilctxt:
|
||||||
MOVD gobuf_g(R5), g // make sure g is not nil
|
MOVD gobuf_g(R5), g // make sure g is not nil
|
||||||
BL runtime·save_g(SB)
|
BL runtime·save_g(SB)
|
||||||
|
|
||||||
|
|
@ -497,7 +513,11 @@ TEXT gosave<>(SB),NOSPLIT|NOFRAME,$0
|
||||||
MOVD R1, (g_sched+gobuf_sp)(g)
|
MOVD R1, (g_sched+gobuf_sp)(g)
|
||||||
MOVD R0, (g_sched+gobuf_lr)(g)
|
MOVD R0, (g_sched+gobuf_lr)(g)
|
||||||
MOVD R0, (g_sched+gobuf_ret)(g)
|
MOVD R0, (g_sched+gobuf_ret)(g)
|
||||||
MOVD R0, (g_sched+gobuf_ctxt)(g)
|
// Assert ctxt is zero. See func save.
|
||||||
|
MOVD (g_sched+gobuf_ctxt)(g), R31
|
||||||
|
CMP R0, R31
|
||||||
|
BEQ 2(PC)
|
||||||
|
BL runtime·badctxt(SB)
|
||||||
RET
|
RET
|
||||||
|
|
||||||
// func asmcgocall(fn, arg unsafe.Pointer) int32
|
// func asmcgocall(fn, arg unsafe.Pointer) int32
|
||||||
|
|
|
||||||
|
|
@ -106,13 +106,27 @@ TEXT runtime·gosave(SB), NOSPLIT, $-8-8
|
||||||
MOVD g, gobuf_g(R3)
|
MOVD g, gobuf_g(R3)
|
||||||
MOVD $0, gobuf_lr(R3)
|
MOVD $0, gobuf_lr(R3)
|
||||||
MOVD $0, gobuf_ret(R3)
|
MOVD $0, gobuf_ret(R3)
|
||||||
MOVD $0, gobuf_ctxt(R3)
|
// Assert ctxt is zero. See func save.
|
||||||
|
MOVD gobuf_ctxt(R3), R3
|
||||||
|
CMPBEQ R3, $0, 2(PC)
|
||||||
|
BL runtime·badctxt(SB)
|
||||||
RET
|
RET
|
||||||
|
|
||||||
// void gogo(Gobuf*)
|
// void gogo(Gobuf*)
|
||||||
// restore state from Gobuf; longjmp
|
// restore state from Gobuf; longjmp
|
||||||
TEXT runtime·gogo(SB), NOSPLIT, $-8-8
|
TEXT runtime·gogo(SB), NOSPLIT, $16-8
|
||||||
MOVD buf+0(FP), R5
|
MOVD buf+0(FP), R5
|
||||||
|
|
||||||
|
// If ctxt is not nil, invoke deletion barrier before overwriting.
|
||||||
|
MOVD gobuf_ctxt(R5), R1
|
||||||
|
CMPBEQ R1, $0, nilctxt
|
||||||
|
MOVD $gobuf_ctxt(R5), R1
|
||||||
|
MOVD R1, 8(R15)
|
||||||
|
MOVD R0, 16(R15)
|
||||||
|
BL runtime·writebarrierptr_prewrite(SB)
|
||||||
|
MOVD buf+0(FP), R5
|
||||||
|
|
||||||
|
nilctxt:
|
||||||
MOVD gobuf_g(R5), g // make sure g is not nil
|
MOVD gobuf_g(R5), g // make sure g is not nil
|
||||||
BL runtime·save_g(SB)
|
BL runtime·save_g(SB)
|
||||||
|
|
||||||
|
|
@ -447,13 +461,16 @@ TEXT runtime·jmpdefer(SB),NOSPLIT|NOFRAME,$0-16
|
||||||
MOVD 0(R12), R3
|
MOVD 0(R12), R3
|
||||||
BR (R3)
|
BR (R3)
|
||||||
|
|
||||||
// Save state of caller into g->sched. Smashes R31.
|
// Save state of caller into g->sched. Smashes R1.
|
||||||
TEXT gosave<>(SB),NOSPLIT|NOFRAME,$0
|
TEXT gosave<>(SB),NOSPLIT|NOFRAME,$0
|
||||||
MOVD LR, (g_sched+gobuf_pc)(g)
|
MOVD LR, (g_sched+gobuf_pc)(g)
|
||||||
MOVD R15, (g_sched+gobuf_sp)(g)
|
MOVD R15, (g_sched+gobuf_sp)(g)
|
||||||
MOVD $0, (g_sched+gobuf_lr)(g)
|
MOVD $0, (g_sched+gobuf_lr)(g)
|
||||||
MOVD $0, (g_sched+gobuf_ret)(g)
|
MOVD $0, (g_sched+gobuf_ret)(g)
|
||||||
MOVD $0, (g_sched+gobuf_ctxt)(g)
|
// Assert ctxt is zero. See func save.
|
||||||
|
MOVD (g_sched+gobuf_ctxt)(g), R1
|
||||||
|
CMPBEQ R1, $0, 2(PC)
|
||||||
|
BL runtime·badctxt(SB)
|
||||||
RET
|
RET
|
||||||
|
|
||||||
// func asmcgocall(fn, arg unsafe.Pointer) int32
|
// func asmcgocall(fn, arg unsafe.Pointer) int32
|
||||||
|
|
|
||||||
|
|
@ -239,6 +239,15 @@ func setMNoWB(mp **m, new *m) {
|
||||||
|
|
||||||
type gobuf struct {
|
type gobuf struct {
|
||||||
// The offsets of sp, pc, and g are known to (hard-coded in) libmach.
|
// The offsets of sp, pc, and g are known to (hard-coded in) libmach.
|
||||||
|
//
|
||||||
|
// ctxt is unusual with respect to GC: it may be a
|
||||||
|
// heap-allocated funcval so write require a write barrier,
|
||||||
|
// but gobuf needs to be cleared from assembly. We take
|
||||||
|
// advantage of the fact that the only path that uses a
|
||||||
|
// non-nil ctxt is morestack. As a result, gogo is the only
|
||||||
|
// place where it may not already be nil, so gogo uses an
|
||||||
|
// explicit write barrier. Everywhere else that resets the
|
||||||
|
// gobuf asserts that ctxt is already nil.
|
||||||
sp uintptr
|
sp uintptr
|
||||||
pc uintptr
|
pc uintptr
|
||||||
g guintptr
|
g guintptr
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue