diff --git a/src/common.h b/src/common.h index 02818f567c..bc8d0a9e27 100644 --- a/src/common.h +++ b/src/common.h @@ -47,6 +47,22 @@ GAP_STATIC_ASSERT(sizeof(void *) == SIZEOF_VOID_P, "sizeof(void *) is wrong"); #endif +// GAP_SETJMP and GAP_LONGJMP are used for error handling and for GASMAN's +// register capture. On POSIX systems we use _setjmp/_longjmp, which do not +// save and restore the signal mask and thus are much faster. On native +// Windows those names do not exist (mingw's two-argument _setjmp intrinsic +// is something else entirely), so use plain setjmp/longjmp there. +// TODO(windows-port): Windows longjmp performs SEH stack unwinding; if that +// misbehaves across GAP stack frames, switch to mingw's _setjmp(env, NULL). +// Callers must include themselves. +#ifdef SYS_IS_WINDOWS +#define GAP_SETJMP(env) setjmp(env) +#define GAP_LONGJMP(env, val) longjmp(env, val) +#else +#define GAP_SETJMP(env) _setjmp(env) +#define GAP_LONGJMP(env, val) _longjmp(env, val) +#endif + #ifdef USE_GASMAN #define GAP_ENABLE_SAVELOAD #endif diff --git a/src/gasman.c b/src/gasman.c index 0575a384b7..1978d1133c 100644 --- a/src/gasman.c +++ b/src/gasman.c @@ -2009,7 +2009,7 @@ static UInt CollectBags_Mark(UInt FullBags) } // mark from the stack - _setjmp(RegsBags); + GAP_SETJMP(RegsBags); #if defined(SYS_IS_SPARC) SparcStackFuncBags(); #endif diff --git a/src/julia_gc.c b/src/julia_gc.c index f04d51e918..8955b997ee 100644 --- a/src/julia_gc.c +++ b/src/julia_gc.c @@ -579,7 +579,7 @@ static void GapRootScanner(int full) // towards the stack bottom, ensuring that we also scan any // references stored in registers. jmp_buf registers; - _setjmp(registers); + GAP_SETJMP(registers); TryMarkRange(ptls, registers, (char *)registers + sizeof(jmp_buf)); TryMarkRange(ptls, (char *)registers + sizeof(jmp_buf), stackend); diff --git a/src/libgap-api.h b/src/libgap-api.h index 6e90be5652..0480568078 100644 --- a/src/libgap-api.h +++ b/src/libgap-api.h @@ -104,7 +104,7 @@ static inline int GAP_Error_Postjmp_(int JumpRet) #define GAP_Error_Setjmp() \ (GAP_unlikely(GAP_Error_Prejmp_(__FILE__, __LINE__)) || \ - GAP_Error_Postjmp_(_setjmp(*GAP_GetReadJmpError()))) + GAP_Error_Postjmp_(GAP_SETJMP(*GAP_GetReadJmpError()))) // Code which uses the GAP API exposed by this header file should sandwich diff --git a/src/read.c b/src/read.c index 437302919e..7559ea60f2 100644 --- a/src/read.c +++ b/src/read.c @@ -77,7 +77,7 @@ #define TRY_IF_NO_ERROR \ if (!rs->s.NrError) { \ volatile Int recursionDepth = GetRecursionDepth(); \ - if (_setjmp(STATE(ReadJmpError))) { \ + if (GAP_SETJMP(STATE(ReadJmpError))) { \ SetRecursionDepth(recursionDepth); \ rs->s.NrError++; \ } \ diff --git a/src/trycatch.c b/src/trycatch.c index 12a68deb2e..419be4783a 100644 --- a/src/trycatch.c +++ b/src/trycatch.c @@ -58,5 +58,5 @@ void GAP_THROW(void) int depth = STATE(TryCatchDepth); for (int i = 0; i < ARRAY_SIZE(throwObservers) && throwObservers[i]; ++i) (throwObservers[i])(depth); - _longjmp(STATE(ReadJmpError), 1); + GAP_LONGJMP(STATE(ReadJmpError), 1); } diff --git a/src/trycatch.h b/src/trycatch.h index 939432cb82..a6a255654c 100644 --- a/src/trycatch.h +++ b/src/trycatch.h @@ -87,7 +87,7 @@ void InvokeTryCatchHandler(TryCatchMode mode); GAP_TryCatchEnv gap__env; \ gap_safe_trycatch(&gap__env); \ InvokeTryCatchHandler(TryEnter); \ - if (!_setjmp(STATE(ReadJmpError))) \ + if (!GAP_SETJMP(STATE(ReadJmpError))) \ for (gap__i = 1; gap__i; gap__i = 0, \ InvokeTryCatchHandler(TryLeave), \ gap_restore_trycatch(&gap__env))