diff options
| author | Paul Eggert | 2017-08-29 14:20:47 -0700 |
|---|---|---|
| committer | Paul Eggert | 2017-08-29 14:58:49 -0700 |
| commit | 9baeed3514fe60189f3bf935c380da92659b7f59 (patch) | |
| tree | eb542d01212b4085203456beb62d15e5a2cb0f3d /src/alloc.c | |
| parent | f1fdb5bc575728bd6c9f13a18939d9c271a74e83 (diff) | |
| download | emacs-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.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 | |||
| 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 | ||
| 5151 | void | 5160 | NO_INLINE void |
| 5152 | flush_stack_call_func (void (*func) (void *arg), void *arg) | 5161 | flush_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). |
| 6098 | However, if there was overflow in pure space, `garbage-collect' | 6107 | However, if there was overflow in pure space, `garbage-collect' |
| 6099 | returns nil, because real GC can't be done. | 6108 | returns nil, because real GC can't be done. |
| 6100 | See Info node `(elisp)Garbage Collection'. */) | 6109 | See Info node `(elisp)Garbage Collection'. */ |
| 6110 | attributes: noinline) | ||
| 6101 | (void) | 6111 | (void) |
| 6102 | { | 6112 | { |
| 6103 | void *end; | 6113 | void *end; |