summaryrefslogtreecommitdiff
path: root/src/alloc.c
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2017-08-29 14:20:47 -0700
committerPaul Eggert <eggert@cs.ucla.edu>2017-08-29 14:58:49 -0700
commit9baeed3514fe60189f3bf935c380da92659b7f59 (patch)
treeeb542d01212b4085203456beb62d15e5a2cb0f3d /src/alloc.c
parentf1fdb5bc575728bd6c9f13a18939d9c271a74e83 (diff)
downloademacs-9baeed3514fe60189f3bf935c380da92659b7f59.tar.gz
Improve stack-top heuristic
This is needed for gcc -Os -flto on x86-64; otherwise, GC misses part of the stack when scanning for heap roots, causing Emacs to crash later (Bug#28213). The problem is that Emacs's hack for getting an address near the stack top does not work when link-time optimization moves stack variables around. * configure.ac (HAVE___BUILTIN_FRAME_ADDRESS): New macro. * lib-src/make-docfile.c (DEFUN_noinline): New constant. (write_globals, scan_c_stream): Support noinline. * src/alloc.c (NEAR_STACK_TOP): New macro. (SET_STACK_TOP_ADDRESS): Use it. (flush_stack_call_func, Fgarbage_collect): Now noinline.
Diffstat (limited to 'src/alloc.c')
-rw-r--r--src/alloc.c20
1 files changed, 15 insertions, 5 deletions
diff --git a/src/alloc.c b/src/alloc.c
index 2cee6462564..6e57b2024bc 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -5061,22 +5061,31 @@ typedef union
# endif
#endif
+/* Yield an address close enough to the top of the stack that the
+ garbage collector need not scan above it. Callers should be
+ declared NO_INLINE. */
+#ifdef HAVE___BUILTIN_FRAME_ADDRESS
+# define NEAR_STACK_TOP(addr) ((void) (addr), __builtin_frame_address (0))
+#else
+# define NEAR_STACK_TOP(addr) (addr)
+#endif
+
/* Set *P to the address of the top of the stack. This must be a
macro, not a function, so that it is executed in the caller’s
environment. It is not inside a do-while so that its storage
- survives the macro. */
+ survives the macro. Callers should be declared NO_INLINE. */
#ifdef HAVE___BUILTIN_UNWIND_INIT
# define SET_STACK_TOP_ADDRESS(p) \
stacktop_sentry sentry; \
__builtin_unwind_init (); \
- *(p) = &sentry
+ *(p) = NEAR_STACK_TOP (&sentry)
#else
# define SET_STACK_TOP_ADDRESS(p) \
stacktop_sentry sentry; \
__builtin_unwind_init (); \
test_setjmp (); \
sys_setjmp (sentry.j); \
- *(p) = &sentry + (stack_bottom < &sentry.c)
+ *(p) = NEAR_STACK_TOP (&sentry + (stack_bottom < &sentry.c))
#endif
/* Mark live Lisp objects on the C stack.
@@ -5148,7 +5157,7 @@ mark_stack (char *bottom, char *end)
It is invalid to run any Lisp code or to allocate any GC memory
from FUNC. */
-void
+NO_INLINE void
flush_stack_call_func (void (*func) (void *arg), void *arg)
{
void *end;
@@ -6097,7 +6106,8 @@ where each entry has the form (NAME SIZE USED FREE), where:
to return them to the OS).
However, if there was overflow in pure space, `garbage-collect'
returns nil, because real GC can't be done.
-See Info node `(elisp)Garbage Collection'. */)
+See Info node `(elisp)Garbage Collection'. */
+ attributes: noinline)
(void)
{
void *end;