diff options
| author | Paul Eggert | 2017-02-02 21:28:45 -0800 |
|---|---|---|
| committer | Paul Eggert | 2017-02-02 22:58:20 -0800 |
| commit | e080d019f41d2738ba0db721c1b89ea57413439b (patch) | |
| tree | 0112d0f4515e2b2bb2aa599ad9137c309d34cc14 /src/alloc.c | |
| parent | ce88155d83ba84e84321ed69a39c82f40117dd1f (diff) | |
| download | emacs-e080d019f41d2738ba0db721c1b89ea57413439b.tar.gz emacs-e080d019f41d2738ba0db721c1b89ea57413439b.zip | |
Re-port alloc.c to Solaris sparc and simplify
alloc.c had bitrotted a bit, and used an undefined symbol
stack_base when Emacs was built on Solaris sparc, leading to
compilation failures. Also, code related to __builtin_unwind_init
was unnecessarily duplicated. Fix the bitrot and remove some
duplication.
* src/alloc.c: Remove uses of GC_SAVE_REGISTERS_ON_STACK, since it
is never defined.
(test_setjmp) [!HAVE___BUILTIN_UNWIND_INIT && GC_SETJMP_WORKS]:
Define a no-op dummy, to simplify use.
(test_setjmp) [!GC_SETJMP_WORKS]: Test setjmp_tested_p here rather
than in the caller, to simplify use.
(stacktop_sentry): New type.
(__builtin_unwind_init) [!HAVE___BUILTIN_UNWIND_INIT]: New macro.
(SET_STACK_TOP_ADDRESS): New macro, containing code that was duplicated.
(flush_stack_call_func, Fgarbage_collect): Use it.
(init_alloc): Omit unnecessary initialization.
After dumping, Emacs need not re-test setjmp.
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 189 |
1 files changed, 69 insertions, 120 deletions
diff --git a/src/alloc.c b/src/alloc.c index e909d312c4e..62f43669f2a 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -4887,12 +4887,19 @@ mark_memory (void *start, void *end) | |||
| 4887 | } | 4887 | } |
| 4888 | } | 4888 | } |
| 4889 | 4889 | ||
| 4890 | #if !defined GC_SAVE_REGISTERS_ON_STACK && !defined GC_SETJMP_WORKS | 4890 | #ifndef HAVE___BUILTIN_UNWIND_INIT |
| 4891 | |||
| 4892 | # ifdef GC_SETJMP_WORKS | ||
| 4893 | static void | ||
| 4894 | test_setjmp (void) | ||
| 4895 | { | ||
| 4896 | } | ||
| 4897 | # else | ||
| 4891 | 4898 | ||
| 4892 | static bool setjmp_tested_p; | 4899 | static bool setjmp_tested_p; |
| 4893 | static int longjmps_done; | 4900 | static int longjmps_done; |
| 4894 | 4901 | ||
| 4895 | #define SETJMP_WILL_LIKELY_WORK "\ | 4902 | # define SETJMP_WILL_LIKELY_WORK "\ |
| 4896 | \n\ | 4903 | \n\ |
| 4897 | Emacs garbage collector has been changed to use conservative stack\n\ | 4904 | Emacs garbage collector has been changed to use conservative stack\n\ |
| 4898 | marking. Emacs has determined that the method it uses to do the\n\ | 4905 | marking. Emacs has determined that the method it uses to do the\n\ |
| @@ -4905,7 +4912,7 @@ verify that the methods used are appropriate for your system.\n\ | |||
| 4905 | Please mail the result to <emacs-devel@gnu.org>.\n\ | 4912 | Please mail the result to <emacs-devel@gnu.org>.\n\ |
| 4906 | " | 4913 | " |
| 4907 | 4914 | ||
| 4908 | #define SETJMP_WILL_NOT_WORK "\ | 4915 | # define SETJMP_WILL_NOT_WORK "\ |
| 4909 | \n\ | 4916 | \n\ |
| 4910 | Emacs garbage collector has been changed to use conservative stack\n\ | 4917 | Emacs garbage collector has been changed to use conservative stack\n\ |
| 4911 | marking. Emacs has determined that the default method it uses to do the\n\ | 4918 | marking. Emacs has determined that the default method it uses to do the\n\ |
| @@ -4931,6 +4938,9 @@ Please mail the result to <emacs-devel@gnu.org>.\n\ | |||
| 4931 | static void | 4938 | static void |
| 4932 | test_setjmp (void) | 4939 | test_setjmp (void) |
| 4933 | { | 4940 | { |
| 4941 | if (setjmp_tested_p) | ||
| 4942 | return; | ||
| 4943 | setjmp_tested_p = true; | ||
| 4934 | char buf[10]; | 4944 | char buf[10]; |
| 4935 | register int x; | 4945 | register int x; |
| 4936 | sys_jmp_buf jbuf; | 4946 | sys_jmp_buf jbuf; |
| @@ -4967,9 +4977,60 @@ test_setjmp (void) | |||
| 4967 | if (longjmps_done == 1) | 4977 | if (longjmps_done == 1) |
| 4968 | sys_longjmp (jbuf, 1); | 4978 | sys_longjmp (jbuf, 1); |
| 4969 | } | 4979 | } |
| 4980 | # endif /* ! GC_SETJMP_WORKS */ | ||
| 4981 | #endif /* ! HAVE___BUILTIN_UNWIND_INIT */ | ||
| 4970 | 4982 | ||
| 4971 | #endif /* not GC_SAVE_REGISTERS_ON_STACK && not GC_SETJMP_WORKS */ | 4983 | /* The type of an object near the stack top, whose address can be used |
| 4984 | as a stack scan limit. */ | ||
| 4985 | typedef union | ||
| 4986 | { | ||
| 4987 | /* Align the stack top properly. Even if !HAVE___BUILTIN_UNWIND_INIT, | ||
| 4988 | jmp_buf may not be aligned enough on darwin-ppc64. */ | ||
| 4989 | max_align_t o; | ||
| 4990 | #ifndef HAVE___BUILTIN_UNWIND_INIT | ||
| 4991 | sys_jmp_buf j; | ||
| 4992 | char c; | ||
| 4993 | #endif | ||
| 4994 | } stacktop_sentry; | ||
| 4995 | |||
| 4996 | /* Force callee-saved registers and register windows onto the stack. | ||
| 4997 | Use the platform-defined __builtin_unwind_init if available, | ||
| 4998 | obviating the need for machine dependent methods. */ | ||
| 4999 | #ifndef HAVE___BUILTIN_UNWIND_INIT | ||
| 5000 | # ifdef __sparc__ | ||
| 5001 | /* This trick flushes the register windows so that all the state of | ||
| 5002 | the process is contained in the stack. | ||
| 5003 | FreeBSD does not have a ta 3 handler, so handle it specially. | ||
| 5004 | FIXME: Code in the Boehm GC suggests flushing (with 'flushrs') is | ||
| 5005 | needed on ia64 too. See mach_dep.c, where it also says inline | ||
| 5006 | assembler doesn't work with relevant proprietary compilers. */ | ||
| 5007 | # if defined __sparc64__ && defined __FreeBSD__ | ||
| 5008 | # define __builtin_unwind_init() asm ("flushw") | ||
| 5009 | # else | ||
| 5010 | # define __builtin_unwind_init() asm ("ta 3") | ||
| 5011 | # endif | ||
| 5012 | # else | ||
| 5013 | # define __builtin_unwind_init() ((void) 0) | ||
| 5014 | # endif | ||
| 5015 | #endif | ||
| 4972 | 5016 | ||
| 5017 | /* Set *P to the address of the top of the stack. This must be a | ||
| 5018 | macro, not a function, so that it is executed in the caller’s | ||
| 5019 | environment. It is not inside a do-while so that its storage | ||
| 5020 | survives the macro. */ | ||
| 5021 | #ifdef HAVE___BUILTIN_UNWIND_INIT | ||
| 5022 | # define SET_STACK_TOP_ADDRESS(p) \ | ||
| 5023 | stacktop_sentry sentry; \ | ||
| 5024 | __builtin_unwind_init (); \ | ||
| 5025 | *(p) = &sentry | ||
| 5026 | #else | ||
| 5027 | # define SET_STACK_TOP_ADDRESS(p) \ | ||
| 5028 | stacktop_sentry sentry; \ | ||
| 5029 | __builtin_unwind_init (); \ | ||
| 5030 | test_setjmp (); \ | ||
| 5031 | sys_setjmp (sentry.j); \ | ||
| 5032 | *(p) = &sentry + (stack_bottom < &sentry.c) | ||
| 5033 | #endif | ||
| 4973 | 5034 | ||
| 4974 | /* Mark live Lisp objects on the C stack. | 5035 | /* Mark live Lisp objects on the C stack. |
| 4975 | 5036 | ||
| @@ -4981,12 +5042,7 @@ test_setjmp (void) | |||
| 4981 | We have to mark Lisp objects in CPU registers that can hold local | 5042 | We have to mark Lisp objects in CPU registers that can hold local |
| 4982 | variables or are used to pass parameters. | 5043 | variables or are used to pass parameters. |
| 4983 | 5044 | ||
| 4984 | If GC_SAVE_REGISTERS_ON_STACK is defined, it should expand to | 5045 | This code assumes that calling setjmp saves registers we need |
| 4985 | something that either saves relevant registers on the stack, or | ||
| 4986 | calls mark_maybe_object passing it each register's contents. | ||
| 4987 | |||
| 4988 | If GC_SAVE_REGISTERS_ON_STACK is not defined, the current | ||
| 4989 | implementation assumes that calling setjmp saves registers we need | ||
| 4990 | to see in a jmp_buf which itself lies on the stack. This doesn't | 5046 | to see in a jmp_buf which itself lies on the stack. This doesn't |
| 4991 | have to be true! It must be verified for each system, possibly | 5047 | have to be true! It must be verified for each system, possibly |
| 4992 | by taking a look at the source code of setjmp. | 5048 | by taking a look at the source code of setjmp. |
| @@ -5050,62 +5106,9 @@ flush_stack_call_func (void (*func) (void *arg), void *arg) | |||
| 5050 | { | 5106 | { |
| 5051 | void *end; | 5107 | void *end; |
| 5052 | struct thread_state *self = current_thread; | 5108 | struct thread_state *self = current_thread; |
| 5053 | 5109 | SET_STACK_TOP_ADDRESS (&end); | |
| 5054 | #ifdef HAVE___BUILTIN_UNWIND_INIT | ||
| 5055 | /* Force callee-saved registers and register windows onto the stack. | ||
| 5056 | This is the preferred method if available, obviating the need for | ||
| 5057 | machine dependent methods. */ | ||
| 5058 | __builtin_unwind_init (); | ||
| 5059 | end = &end; | ||
| 5060 | #else /* not HAVE___BUILTIN_UNWIND_INIT */ | ||
| 5061 | #ifndef GC_SAVE_REGISTERS_ON_STACK | ||
| 5062 | /* jmp_buf may not be aligned enough on darwin-ppc64 */ | ||
| 5063 | union aligned_jmpbuf { | ||
| 5064 | Lisp_Object o; | ||
| 5065 | sys_jmp_buf j; | ||
| 5066 | } j; | ||
| 5067 | volatile bool stack_grows_down_p = (char *) &j > (char *) stack_bottom; | ||
| 5068 | #endif | ||
| 5069 | /* This trick flushes the register windows so that all the state of | ||
| 5070 | the process is contained in the stack. */ | ||
| 5071 | /* Fixme: Code in the Boehm GC suggests flushing (with `flushrs') is | ||
| 5072 | needed on ia64 too. See mach_dep.c, where it also says inline | ||
| 5073 | assembler doesn't work with relevant proprietary compilers. */ | ||
| 5074 | #ifdef __sparc__ | ||
| 5075 | #if defined (__sparc64__) && defined (__FreeBSD__) | ||
| 5076 | /* FreeBSD does not have a ta 3 handler. */ | ||
| 5077 | asm ("flushw"); | ||
| 5078 | #else | ||
| 5079 | asm ("ta 3"); | ||
| 5080 | #endif | ||
| 5081 | #endif | ||
| 5082 | |||
| 5083 | /* Save registers that we need to see on the stack. We need to see | ||
| 5084 | registers used to hold register variables and registers used to | ||
| 5085 | pass parameters. */ | ||
| 5086 | #ifdef GC_SAVE_REGISTERS_ON_STACK | ||
| 5087 | GC_SAVE_REGISTERS_ON_STACK (end); | ||
| 5088 | #else /* not GC_SAVE_REGISTERS_ON_STACK */ | ||
| 5089 | |||
| 5090 | #ifndef GC_SETJMP_WORKS /* If it hasn't been checked yet that | ||
| 5091 | setjmp will definitely work, test it | ||
| 5092 | and print a message with the result | ||
| 5093 | of the test. */ | ||
| 5094 | if (!setjmp_tested_p) | ||
| 5095 | { | ||
| 5096 | setjmp_tested_p = 1; | ||
| 5097 | test_setjmp (); | ||
| 5098 | } | ||
| 5099 | #endif /* GC_SETJMP_WORKS */ | ||
| 5100 | |||
| 5101 | sys_setjmp (j.j); | ||
| 5102 | end = stack_grows_down_p ? (char *) &j + sizeof j : (char *) &j; | ||
| 5103 | #endif /* not GC_SAVE_REGISTERS_ON_STACK */ | ||
| 5104 | #endif /* not HAVE___BUILTIN_UNWIND_INIT */ | ||
| 5105 | |||
| 5106 | self->stack_top = end; | 5110 | self->stack_top = end; |
| 5107 | (*func) (arg); | 5111 | func (arg); |
| 5108 | |||
| 5109 | eassert (current_thread == self); | 5112 | eassert (current_thread == self); |
| 5110 | } | 5113 | } |
| 5111 | 5114 | ||
| @@ -6047,58 +6050,7 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 6047 | (void) | 6050 | (void) |
| 6048 | { | 6051 | { |
| 6049 | void *end; | 6052 | void *end; |
| 6050 | 6053 | SET_STACK_TOP_ADDRESS (&end); | |
| 6051 | #ifdef HAVE___BUILTIN_UNWIND_INIT | ||
| 6052 | /* Force callee-saved registers and register windows onto the stack. | ||
| 6053 | This is the preferred method if available, obviating the need for | ||
| 6054 | machine dependent methods. */ | ||
| 6055 | __builtin_unwind_init (); | ||
| 6056 | end = &end; | ||
| 6057 | #else /* not HAVE___BUILTIN_UNWIND_INIT */ | ||
| 6058 | #ifndef GC_SAVE_REGISTERS_ON_STACK | ||
| 6059 | /* jmp_buf may not be aligned enough on darwin-ppc64 */ | ||
| 6060 | union aligned_jmpbuf { | ||
| 6061 | Lisp_Object o; | ||
| 6062 | sys_jmp_buf j; | ||
| 6063 | } j; | ||
| 6064 | volatile bool stack_grows_down_p = (char *) &j > (char *) stack_base; | ||
| 6065 | #endif | ||
| 6066 | /* This trick flushes the register windows so that all the state of | ||
| 6067 | the process is contained in the stack. */ | ||
| 6068 | /* Fixme: Code in the Boehm GC suggests flushing (with `flushrs') is | ||
| 6069 | needed on ia64 too. See mach_dep.c, where it also says inline | ||
| 6070 | assembler doesn't work with relevant proprietary compilers. */ | ||
| 6071 | #ifdef __sparc__ | ||
| 6072 | #if defined (__sparc64__) && defined (__FreeBSD__) | ||
| 6073 | /* FreeBSD does not have a ta 3 handler. */ | ||
| 6074 | asm ("flushw"); | ||
| 6075 | #else | ||
| 6076 | asm ("ta 3"); | ||
| 6077 | #endif | ||
| 6078 | #endif | ||
| 6079 | |||
| 6080 | /* Save registers that we need to see on the stack. We need to see | ||
| 6081 | registers used to hold register variables and registers used to | ||
| 6082 | pass parameters. */ | ||
| 6083 | #ifdef GC_SAVE_REGISTERS_ON_STACK | ||
| 6084 | GC_SAVE_REGISTERS_ON_STACK (end); | ||
| 6085 | #else /* not GC_SAVE_REGISTERS_ON_STACK */ | ||
| 6086 | |||
| 6087 | #ifndef GC_SETJMP_WORKS /* If it hasn't been checked yet that | ||
| 6088 | setjmp will definitely work, test it | ||
| 6089 | and print a message with the result | ||
| 6090 | of the test. */ | ||
| 6091 | if (!setjmp_tested_p) | ||
| 6092 | { | ||
| 6093 | setjmp_tested_p = 1; | ||
| 6094 | test_setjmp (); | ||
| 6095 | } | ||
| 6096 | #endif /* GC_SETJMP_WORKS */ | ||
| 6097 | |||
| 6098 | sys_setjmp (j.j); | ||
| 6099 | end = stack_grows_down_p ? (char *) &j + sizeof j : (char *) &j; | ||
| 6100 | #endif /* not GC_SAVE_REGISTERS_ON_STACK */ | ||
| 6101 | #endif /* not HAVE___BUILTIN_UNWIND_INIT */ | ||
| 6102 | return garbage_collect_1 (end); | 6054 | return garbage_collect_1 (end); |
| 6103 | } | 6055 | } |
| 6104 | 6056 | ||
| @@ -7408,9 +7360,6 @@ init_alloc_once (void) | |||
| 7408 | void | 7360 | void |
| 7409 | init_alloc (void) | 7361 | init_alloc (void) |
| 7410 | { | 7362 | { |
| 7411 | #if !defined GC_SAVE_REGISTERS_ON_STACK && !defined GC_SETJMP_WORKS | ||
| 7412 | setjmp_tested_p = longjmps_done = 0; | ||
| 7413 | #endif | ||
| 7414 | Vgc_elapsed = make_float (0.0); | 7363 | Vgc_elapsed = make_float (0.0); |
| 7415 | gcs_done = 0; | 7364 | gcs_done = 0; |
| 7416 | 7365 | ||