aboutsummaryrefslogtreecommitdiffstats
path: root/src/alloc.c
diff options
context:
space:
mode:
authorPaul Eggert2017-08-29 14:20:47 -0700
committerPaul Eggert2017-08-29 14:58:49 -0700
commit9baeed3514fe60189f3bf935c380da92659b7f59 (patch)
treeeb542d01212b4085203456beb62d15e5a2cb0f3d /src/alloc.c
parentf1fdb5bc575728bd6c9f13a18939d9c271a74e83 (diff)
downloademacs-9baeed3514fe60189f3bf935c380da92659b7f59.tar.gz
emacs-9baeed3514fe60189f3bf935c380da92659b7f59.zip
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
5061# endif 5061# endif
5062#endif 5062#endif
5063 5063
5064/* Yield an address close enough to the top of the stack that the
5065 garbage collector need not scan above it. Callers should be
5066 declared NO_INLINE. */
5067#ifdef HAVE___BUILTIN_FRAME_ADDRESS
5068# define NEAR_STACK_TOP(addr) ((void) (addr), __builtin_frame_address (0))
5069#else
5070# define NEAR_STACK_TOP(addr) (addr)
5071#endif
5072
5064/* Set *P to the address of the top of the stack. This must be a 5073/* Set *P to the address of the top of the stack. This must be a
5065 macro, not a function, so that it is executed in the caller’s 5074 macro, not a function, so that it is executed in the caller’s
5066 environment. It is not inside a do-while so that its storage 5075 environment. It is not inside a do-while so that its storage
5067 survives the macro. */ 5076 survives the macro. Callers should be declared NO_INLINE. */
5068#ifdef HAVE___BUILTIN_UNWIND_INIT 5077#ifdef HAVE___BUILTIN_UNWIND_INIT
5069# define SET_STACK_TOP_ADDRESS(p) \ 5078# define SET_STACK_TOP_ADDRESS(p) \
5070 stacktop_sentry sentry; \ 5079 stacktop_sentry sentry; \
5071 __builtin_unwind_init (); \ 5080 __builtin_unwind_init (); \
5072 *(p) = &sentry 5081 *(p) = NEAR_STACK_TOP (&sentry)
5073#else 5082#else
5074# define SET_STACK_TOP_ADDRESS(p) \ 5083# define SET_STACK_TOP_ADDRESS(p) \
5075 stacktop_sentry sentry; \ 5084 stacktop_sentry sentry; \
5076 __builtin_unwind_init (); \ 5085 __builtin_unwind_init (); \
5077 test_setjmp (); \ 5086 test_setjmp (); \
5078 sys_setjmp (sentry.j); \ 5087 sys_setjmp (sentry.j); \
5079 *(p) = &sentry + (stack_bottom < &sentry.c) 5088 *(p) = NEAR_STACK_TOP (&sentry + (stack_bottom < &sentry.c))
5080#endif 5089#endif
5081 5090
5082/* Mark live Lisp objects on the C stack. 5091/* Mark live Lisp objects on the C stack.
@@ -5148,7 +5157,7 @@ mark_stack (char *bottom, char *end)
5148 It is invalid to run any Lisp code or to allocate any GC memory 5157 It is invalid to run any Lisp code or to allocate any GC memory
5149 from FUNC. */ 5158 from FUNC. */
5150 5159
5151void 5160NO_INLINE void
5152flush_stack_call_func (void (*func) (void *arg), void *arg) 5161flush_stack_call_func (void (*func) (void *arg), void *arg)
5153{ 5162{
5154 void *end; 5163 void *end;
@@ -6097,7 +6106,8 @@ where each entry has the form (NAME SIZE USED FREE), where:
6097 to return them to the OS). 6106 to return them to the OS).
6098However, if there was overflow in pure space, `garbage-collect' 6107However, if there was overflow in pure space, `garbage-collect'
6099returns nil, because real GC can't be done. 6108returns nil, because real GC can't be done.
6100See Info node `(elisp)Garbage Collection'. */) 6109See Info node `(elisp)Garbage Collection'. */
6110 attributes: noinline)
6101 (void) 6111 (void)
6102{ 6112{
6103 void *end; 6113 void *end;