diff options
| author | Paul Eggert <eggert@cs.ucla.edu> | 2017-08-29 14:20:47 -0700 |
|---|---|---|
| committer | Paul Eggert <eggert@cs.ucla.edu> | 2017-08-29 14:58:49 -0700 |
| commit | 9baeed3514fe60189f3bf935c380da92659b7f59 (patch) | |
| tree | eb542d01212b4085203456beb62d15e5a2cb0f3d /src/alloc.c | |
| parent | f1fdb5bc575728bd6c9f13a18939d9c271a74e83 (diff) | |
| download | emacs-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.c | 20 |
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; |
