Commit cb767247 authored by Russ Cox's avatar Russ Cox

runtime: refactor/fix asmcgocall/asmcgocall_errno

Instead of making asmcgocall call asmcgocall_errno,
make both load args into registers and call a shared
assembly function.

On amd64, this costs 1 word in the asmcgocall_errno path
but saves 3 words in the asmcgocall path, and the latter
is what happens on critical nosplit paths on Windows.

On arm, this fixes build failures: asmcgocall was writing
the arguments for asmcgocall_errno into the wrong
place on the stack. Passing them in registers avoids the
decision entirely.

On 386, this isn't really needed, since the nosplit paths
have twice as many words to work with, but do it for consistency.

Update #8635
Fixes arm build (except GOARM=5).

TBR=iant
CC=golang-codereviews
https://golang.org/cl/134390043
parent f4034164
...@@ -156,6 +156,7 @@ func testCallbackCallers(t *testing.T) { ...@@ -156,6 +156,7 @@ func testCallbackCallers(t *testing.T) {
"runtime.cgocallbackg1", "runtime.cgocallbackg1",
"runtime.cgocallbackg", "runtime.cgocallbackg",
"runtime.cgocallback_gofunc", "runtime.cgocallback_gofunc",
"asmcgocall",
"runtime.asmcgocall_errno", "runtime.asmcgocall_errno",
"runtime.cgocall_errno", "runtime.cgocall_errno",
"test._Cfunc_callback", "test._Cfunc_callback",
...@@ -182,8 +183,12 @@ func testCallbackCallers(t *testing.T) { ...@@ -182,8 +183,12 @@ func testCallbackCallers(t *testing.T) {
if strings.HasPrefix(fname, "_") { if strings.HasPrefix(fname, "_") {
fname = path.Base(f.Name()[1:]) fname = path.Base(f.Name()[1:])
} }
if fname != name[i] { namei := ""
t.Errorf("expected function name %s, got %s", name[i], fname) if i < len(name) {
namei = name[i]
}
if fname != namei {
t.Errorf("stk[%d] = %q, want %q", i, fname, namei)
} }
} }
} }
......
...@@ -680,17 +680,21 @@ TEXT gosave<>(SB),NOSPLIT,$0 ...@@ -680,17 +680,21 @@ TEXT gosave<>(SB),NOSPLIT,$0
// Call fn(arg) on the scheduler stack, // Call fn(arg) on the scheduler stack,
// aligned appropriately for the gcc ABI. // aligned appropriately for the gcc ABI.
// See cgocall.c for more details. // See cgocall.c for more details.
TEXT runtime·asmcgocall(SB),NOSPLIT,$12-8 TEXT runtime·asmcgocall(SB),NOSPLIT,$0-8
MOVL fn+0(FP), AX MOVL fn+0(FP), AX
MOVL arg+4(FP), BX MOVL arg+4(FP), BX
MOVL AX, 0(SP) CALL asmcgocall<>(SB)
MOVL BX, 4(SP)
CALL runtime·asmcgocall_errno(SB)
RET RET
TEXT runtime·asmcgocall_errno(SB),NOSPLIT,$0-12 TEXT runtime·asmcgocall_errno(SB),NOSPLIT,$0-12
MOVL fn+0(FP), AX MOVL fn+0(FP), AX
MOVL arg+4(FP), BX MOVL arg+4(FP), BX
CALL asmcgocall<>(SB)
MOVL AX, ret+8(FP)
RET
TEXT asmcgocall<>(SB),NOSPLIT,$0-12
// fn in AX, arg in BX
MOVL SP, DX MOVL SP, DX
// Figure out if we need to switch to m->g0 stack. // Figure out if we need to switch to m->g0 stack.
...@@ -720,7 +724,6 @@ TEXT runtime·asmcgocall_errno(SB),NOSPLIT,$0-12 ...@@ -720,7 +724,6 @@ TEXT runtime·asmcgocall_errno(SB),NOSPLIT,$0-12
MOVL 8(SP), DI MOVL 8(SP), DI
MOVL DI, g(CX) MOVL DI, g(CX)
MOVL 4(SP), SP MOVL 4(SP), SP
MOVL AX, ret+8(FP)
RET RET
// cgocallback(void (*fn)(void*), void *frame, uintptr framesize) // cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
......
...@@ -764,17 +764,21 @@ TEXT gosave<>(SB),NOSPLIT,$0 ...@@ -764,17 +764,21 @@ TEXT gosave<>(SB),NOSPLIT,$0
// Call fn(arg) on the scheduler stack, // Call fn(arg) on the scheduler stack,
// aligned appropriately for the gcc ABI. // aligned appropriately for the gcc ABI.
// See cgocall.c for more details. // See cgocall.c for more details.
TEXT runtime·asmcgocall(SB),NOSPLIT,$24-16 TEXT runtime·asmcgocall(SB),NOSPLIT,$0-16
MOVQ fn+0(FP), AX MOVQ fn+0(FP), AX
MOVQ arg+8(FP), BX MOVQ arg+8(FP), BX
MOVQ AX, 0(SP) CALL asmcgocall<>(SB)
MOVQ BX, 8(SP)
CALL runtime·asmcgocall_errno(SB)
RET RET
TEXT runtime·asmcgocall_errno(SB),NOSPLIT,$0-20 TEXT runtime·asmcgocall_errno(SB),NOSPLIT,$0-20
MOVQ fn+0(FP), AX MOVQ fn+0(FP), AX
MOVQ arg+8(FP), BX MOVQ arg+8(FP), BX
CALL asmcgocall<>(SB)
MOVL AX, ret+16(FP)
RET
// asmcgocall common code. fn in AX, arg in BX. returns errno in AX.
TEXT asmcgocall<>(SB),NOSPLIT,$0-0
MOVQ SP, DX MOVQ SP, DX
// Figure out if we need to switch to m->g0 stack. // Figure out if we need to switch to m->g0 stack.
...@@ -813,7 +817,6 @@ nosave: ...@@ -813,7 +817,6 @@ nosave:
MOVQ 48(SP), DI MOVQ 48(SP), DI
MOVQ DI, g(CX) MOVQ DI, g(CX)
MOVQ 40(SP), SP MOVQ 40(SP), SP
MOVL AX, ret+16(FP)
RET RET
// cgocallback(void (*fn)(void*), void *frame, uintptr framesize) // cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
......
...@@ -493,17 +493,21 @@ TEXT gosave<>(SB),NOSPLIT,$0 ...@@ -493,17 +493,21 @@ TEXT gosave<>(SB),NOSPLIT,$0
// Call fn(arg) on the scheduler stack, // Call fn(arg) on the scheduler stack,
// aligned appropriately for the gcc ABI. // aligned appropriately for the gcc ABI.
// See cgocall.c for more details. // See cgocall.c for more details.
TEXT runtime·asmcgocall(SB),NOSPLIT,$12-8 TEXT runtime·asmcgocall(SB),NOSPLIT,$0-8
MOVW fn+0(FP), R1 MOVW fn+0(FP), R1
MOVW arg+4(FP), R2 MOVW arg+4(FP), R0
MOVW R1, 0(R13) BL asmcgocall<>(SB)
MOVW R2, 4(R13)
BL runtime·asmcgocall_errno(SB)
RET RET
TEXT runtime·asmcgocall_errno(SB),NOSPLIT,$0-12 TEXT runtime·asmcgocall_errno(SB),NOSPLIT,$0-12
MOVW fn+0(FP), R1 MOVW fn+0(FP), R1
MOVW arg+4(FP), R0 MOVW arg+4(FP), R0
BL asmcgocall<>(SB)
MOVW R0, ret+8(FP)
RET
TEXT asmcgocall<>(SB),NOSPLIT,$0-0
// fn in R1, arg in R0.
MOVW R13, R2 MOVW R13, R2
MOVW g, R5 MOVW g, R5
...@@ -529,7 +533,6 @@ TEXT runtime·asmcgocall_errno(SB),NOSPLIT,$0-12 ...@@ -529,7 +533,6 @@ TEXT runtime·asmcgocall_errno(SB),NOSPLIT,$0-12
// Restore registers, g, stack pointer. // Restore registers, g, stack pointer.
MOVW 20(R13), g MOVW 20(R13), g
MOVW 16(R13), R13 MOVW 16(R13), R13
MOVW R0, ret+8(FP)
RET RET
// cgocallback(void (*fn)(void*), void *frame, uintptr framesize) // cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment