mirror of
https://github.com/golang/go.git
synced 2026-04-02 09:20:29 +09:00
runtime: return the error code as a return value in asmstdcall
This shaves off 8 bytes from the syscall_syscalln stack frame, which is significant as that call path is almost over the nosplit limit. Also, it follows the cgocall convention of returning the error code as a return value, making it easier to reason about. Cq-Include-Trybots: luci.golang.try:gotip-windows-amd64-longtest,gotip-windows-arm64,gotip-windows-386 Change-Id: I62acdb7c0d4cf9cb928bf3974d3300dd752f6c29 Reviewed-on: https://go-review.googlesource.com/c/go/+/751861 Reviewed-by: Cherry Mui <cherryyz@google.com> Reviewed-by: Carlos Amedee <carlos@golang.org> Reviewed-by: Alex Brainman <alex.brainman@gmail.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
@@ -5,10 +5,14 @@
|
||||
#include "go_asm.h"
|
||||
#include "textflag.h"
|
||||
|
||||
TEXT ·StdCall<ABIInternal>(SB),NOSPLIT,$0
|
||||
JMP ·asmstdcall(SB)
|
||||
TEXT ·StdCall<ABIInternal>(SB),NOSPLIT,$4-8
|
||||
MOVL fn+0(FP), AX
|
||||
MOVL AX, 0(SP)
|
||||
CALL ·asmstdcall(SB)
|
||||
MOVL AX, ret+4(FP)
|
||||
RET
|
||||
|
||||
TEXT ·asmstdcall(SB),NOSPLIT,$0
|
||||
TEXT ·asmstdcall(SB),NOSPLIT,$0-4
|
||||
MOVL fn+0(FP), BX
|
||||
MOVL SP, BP // save stack pointer
|
||||
|
||||
@@ -43,6 +47,5 @@ docall:
|
||||
|
||||
// GetLastError().
|
||||
MOVL 0x34(FS), AX
|
||||
MOVL AX, StdCallInfo_Err(BX)
|
||||
|
||||
RET
|
||||
|
||||
@@ -79,6 +79,5 @@ _0args:
|
||||
// GetLastError().
|
||||
MOVQ 0x30(GS), DI
|
||||
MOVL 0x68(DI), AX
|
||||
MOVQ AX, StdCallInfo_Err(CX)
|
||||
|
||||
RET
|
||||
|
||||
@@ -83,7 +83,6 @@ _0args:
|
||||
|
||||
// GetLastError
|
||||
MOVD TEB_error(R18_PLATFORM), R0
|
||||
MOVD R0, StdCallInfo_Err(R19)
|
||||
|
||||
// Restore callee-saved registers.
|
||||
LDP 16(RSP), (R19, R20)
|
||||
|
||||
@@ -24,15 +24,20 @@ type StdCallInfo struct {
|
||||
Args uintptr // parameters
|
||||
R1 uintptr // return values
|
||||
R2 uintptr
|
||||
Err uintptr // error number
|
||||
}
|
||||
|
||||
// StdCall calls a function using Windows' stdcall convention.
|
||||
// The calling thread's last-error code value is cleared before calling the function,
|
||||
// and stored in the return value.
|
||||
//
|
||||
//go:noescape
|
||||
func StdCall(fn *StdCallInfo)
|
||||
func StdCall(fn *StdCallInfo) uint32
|
||||
|
||||
// asmstdcall is the function pointer for [AsmStdCallAddr].
|
||||
// The calling thread's last-error code value is cleared before calling the function,
|
||||
// and returned in the C ABI return register (not via Go stack convention).
|
||||
// This function is not called directly from Go; it is either jumped to from
|
||||
// [StdCall] or called from C via [AsmStdCallAddr].
|
||||
func asmstdcall(fn *StdCallInfo)
|
||||
|
||||
// AsmStdCallAddr is the address of a function that accepts a pointer
|
||||
|
||||
@@ -428,10 +428,10 @@ func syscall_syscalln(fn, n uintptr, args ...uintptr) (r1, r2, err uintptr) {
|
||||
if c.N != 0 {
|
||||
c.Args = uintptr(noescape(unsafe.Pointer(&args[0])))
|
||||
}
|
||||
cgocall(asmstdcallAddr, unsafe.Pointer(c))
|
||||
errno := cgocall(asmstdcallAddr, unsafe.Pointer(c))
|
||||
// cgocall may reschedule us on to a different M,
|
||||
// but it copies the return values into the new M's
|
||||
// so we can read them from there.
|
||||
c = &getg().m.winsyscall
|
||||
return c.R1, c.R2, c.Err
|
||||
return c.R1, c.R2, uintptr(errno)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user