diff --git a/mps/code/config.h b/mps/code/config.h index d30ff3d9211..f959ce46c31 100644 --- a/mps/code/config.h +++ b/mps/code/config.h @@ -278,8 +278,20 @@ #define ATTRIBUTE_NO_SANITIZE_ADDRESS #endif +/* Attribute for functions that must not be inlined. + * GCC: + * MSVC: + */ +#if defined(MPS_BUILD_GC) || defined(MPS_BUILD_LL) +#define ATTRIBUTE_NOINLINE __attribute__((__noinline__)) +#elif defined(MPS_BUILD_MV) +#define ATTRIBUTE_NOINLINE __declspec(noinline) +#else +#define ATTRIBUTE_NOINLINE +#endif + /* Attribute for functions that do not return. - * GCC: + * GCC: * Clang: */ #if defined(MPS_BUILD_GC) || defined(MPS_BUILD_LL) @@ -289,7 +301,7 @@ #endif /* Attribute for functions that may be unused in some build configurations. - * GCC: + * GCC: * * This attribute must be applied to all Check functions, otherwise * the RASH variety fails to compile with -Wunused-function. (It diff --git a/mps/code/ss.c b/mps/code/ss.c index 2916794ebd7..bc6e469f037 100644 --- a/mps/code/ss.c +++ b/mps/code/ss.c @@ -32,6 +32,7 @@ SRCID(ss, "$Id$"); * is a hot stack pointer. See design.mps.ss.sol.stack.hot. */ +ATTRIBUTE_NOINLINE void StackHot(void **stackOut) { *stackOut = &stackOut; diff --git a/mps/design/stack-scan.txt b/mps/design/stack-scan.txt index 14960e5c051..05e6dbccbd0 100644 --- a/mps/design/stack-scan.txt +++ b/mps/design/stack-scan.txt @@ -138,9 +138,17 @@ being saved by callees. _`.sol.stack.hot`: We could decode the frame of the function that invokes ``setjmp()`` from the jump buffer in a platform-specific way, but we can do something simpler (if more hacky) by calling the stub -function ``StackHot()`` which takes the address of its argument. On -all supported platforms this will yield a pointer that is pretty much -at the hot end of the frame. +function ``StackHot()`` which takes the address of its argument. So +long as this stub function is not inlined into the caller, then on all +supported platforms this yields a pointer that is pretty much at the +hot end of the frame. + +_`.sol.stack.hot.noinline`: The reason that ``StackHot()`` must not be +inlined is that after inlining, the compiler might place ``stackOut`` +at a colder stack address than the ``StackContextStruct``, causing the +latter not to be scanned. See `mail.gdr.2018-07-11.09-48`_. + +.. _mail.gdr.2018-07-11.09-48: https://info.ravenbrook.com/mail/2018/07/11/09-48-49/0/ _`.sol.stack.nest`: We can take care of scanning the jump buffer itself by storing it in the same stack frame. That way a scan from the