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.
This commit is contained in:
Paul Eggert 2017-02-02 21:28:45 -08:00
parent ce88155d83
commit e080d019f4

View file

@ -4887,12 +4887,19 @@ mark_memory (void *start, void *end)
}
}
#if !defined GC_SAVE_REGISTERS_ON_STACK && !defined GC_SETJMP_WORKS
#ifndef HAVE___BUILTIN_UNWIND_INIT
# ifdef GC_SETJMP_WORKS
static void
test_setjmp (void)
{
}
# else
static bool setjmp_tested_p;
static int longjmps_done;
#define SETJMP_WILL_LIKELY_WORK "\
# define SETJMP_WILL_LIKELY_WORK "\
\n\
Emacs garbage collector has been changed to use conservative stack\n\
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\
Please mail the result to <emacs-devel@gnu.org>.\n\
"
#define SETJMP_WILL_NOT_WORK "\
# define SETJMP_WILL_NOT_WORK "\
\n\
Emacs garbage collector has been changed to use conservative stack\n\
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\
static void
test_setjmp (void)
{
if (setjmp_tested_p)
return;
setjmp_tested_p = true;
char buf[10];
register int x;
sys_jmp_buf jbuf;
@ -4967,9 +4977,60 @@ test_setjmp (void)
if (longjmps_done == 1)
sys_longjmp (jbuf, 1);
}
# endif /* ! GC_SETJMP_WORKS */
#endif /* ! HAVE___BUILTIN_UNWIND_INIT */
#endif /* not GC_SAVE_REGISTERS_ON_STACK && not GC_SETJMP_WORKS */
/* The type of an object near the stack top, whose address can be used
as a stack scan limit. */
typedef union
{
/* Align the stack top properly. Even if !HAVE___BUILTIN_UNWIND_INIT,
jmp_buf may not be aligned enough on darwin-ppc64. */
max_align_t o;
#ifndef HAVE___BUILTIN_UNWIND_INIT
sys_jmp_buf j;
char c;
#endif
} stacktop_sentry;
/* Force callee-saved registers and register windows onto the stack.
Use the platform-defined __builtin_unwind_init if available,
obviating the need for machine dependent methods. */
#ifndef HAVE___BUILTIN_UNWIND_INIT
# ifdef __sparc__
/* This trick flushes the register windows so that all the state of
the process is contained in the stack.
FreeBSD does not have a ta 3 handler, so handle it specially.
FIXME: Code in the Boehm GC suggests flushing (with 'flushrs') is
needed on ia64 too. See mach_dep.c, where it also says inline
assembler doesn't work with relevant proprietary compilers. */
# if defined __sparc64__ && defined __FreeBSD__
# define __builtin_unwind_init() asm ("flushw")
# else
# define __builtin_unwind_init() asm ("ta 3")
# endif
# else
# define __builtin_unwind_init() ((void) 0)
# endif
#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 callers
environment. It is not inside a do-while so that its storage
survives the macro. */
#ifdef HAVE___BUILTIN_UNWIND_INIT
# define SET_STACK_TOP_ADDRESS(p) \
stacktop_sentry sentry; \
__builtin_unwind_init (); \
*(p) = &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)
#endif
/* Mark live Lisp objects on the C stack.
@ -4981,12 +5042,7 @@ test_setjmp (void)
We have to mark Lisp objects in CPU registers that can hold local
variables or are used to pass parameters.
If GC_SAVE_REGISTERS_ON_STACK is defined, it should expand to
something that either saves relevant registers on the stack, or
calls mark_maybe_object passing it each register's contents.
If GC_SAVE_REGISTERS_ON_STACK is not defined, the current
implementation assumes that calling setjmp saves registers we need
This code assumes that calling setjmp saves registers we need
to see in a jmp_buf which itself lies on the stack. This doesn't
have to be true! It must be verified for each system, possibly
by taking a look at the source code of setjmp.
@ -5050,62 +5106,9 @@ flush_stack_call_func (void (*func) (void *arg), void *arg)
{
void *end;
struct thread_state *self = current_thread;
#ifdef HAVE___BUILTIN_UNWIND_INIT
/* Force callee-saved registers and register windows onto the stack.
This is the preferred method if available, obviating the need for
machine dependent methods. */
__builtin_unwind_init ();
end = &end;
#else /* not HAVE___BUILTIN_UNWIND_INIT */
#ifndef GC_SAVE_REGISTERS_ON_STACK
/* jmp_buf may not be aligned enough on darwin-ppc64 */
union aligned_jmpbuf {
Lisp_Object o;
sys_jmp_buf j;
} j;
volatile bool stack_grows_down_p = (char *) &j > (char *) stack_bottom;
#endif
/* This trick flushes the register windows so that all the state of
the process is contained in the stack. */
/* Fixme: Code in the Boehm GC suggests flushing (with `flushrs') is
needed on ia64 too. See mach_dep.c, where it also says inline
assembler doesn't work with relevant proprietary compilers. */
#ifdef __sparc__
#if defined (__sparc64__) && defined (__FreeBSD__)
/* FreeBSD does not have a ta 3 handler. */
asm ("flushw");
#else
asm ("ta 3");
#endif
#endif
/* Save registers that we need to see on the stack. We need to see
registers used to hold register variables and registers used to
pass parameters. */
#ifdef GC_SAVE_REGISTERS_ON_STACK
GC_SAVE_REGISTERS_ON_STACK (end);
#else /* not GC_SAVE_REGISTERS_ON_STACK */
#ifndef GC_SETJMP_WORKS /* If it hasn't been checked yet that
setjmp will definitely work, test it
and print a message with the result
of the test. */
if (!setjmp_tested_p)
{
setjmp_tested_p = 1;
test_setjmp ();
}
#endif /* GC_SETJMP_WORKS */
sys_setjmp (j.j);
end = stack_grows_down_p ? (char *) &j + sizeof j : (char *) &j;
#endif /* not GC_SAVE_REGISTERS_ON_STACK */
#endif /* not HAVE___BUILTIN_UNWIND_INIT */
SET_STACK_TOP_ADDRESS (&end);
self->stack_top = end;
(*func) (arg);
func (arg);
eassert (current_thread == self);
}
@ -6047,58 +6050,7 @@ See Info node `(elisp)Garbage Collection'. */)
(void)
{
void *end;
#ifdef HAVE___BUILTIN_UNWIND_INIT
/* Force callee-saved registers and register windows onto the stack.
This is the preferred method if available, obviating the need for
machine dependent methods. */
__builtin_unwind_init ();
end = &end;
#else /* not HAVE___BUILTIN_UNWIND_INIT */
#ifndef GC_SAVE_REGISTERS_ON_STACK
/* jmp_buf may not be aligned enough on darwin-ppc64 */
union aligned_jmpbuf {
Lisp_Object o;
sys_jmp_buf j;
} j;
volatile bool stack_grows_down_p = (char *) &j > (char *) stack_base;
#endif
/* This trick flushes the register windows so that all the state of
the process is contained in the stack. */
/* Fixme: Code in the Boehm GC suggests flushing (with `flushrs') is
needed on ia64 too. See mach_dep.c, where it also says inline
assembler doesn't work with relevant proprietary compilers. */
#ifdef __sparc__
#if defined (__sparc64__) && defined (__FreeBSD__)
/* FreeBSD does not have a ta 3 handler. */
asm ("flushw");
#else
asm ("ta 3");
#endif
#endif
/* Save registers that we need to see on the stack. We need to see
registers used to hold register variables and registers used to
pass parameters. */
#ifdef GC_SAVE_REGISTERS_ON_STACK
GC_SAVE_REGISTERS_ON_STACK (end);
#else /* not GC_SAVE_REGISTERS_ON_STACK */
#ifndef GC_SETJMP_WORKS /* If it hasn't been checked yet that
setjmp will definitely work, test it
and print a message with the result
of the test. */
if (!setjmp_tested_p)
{
setjmp_tested_p = 1;
test_setjmp ();
}
#endif /* GC_SETJMP_WORKS */
sys_setjmp (j.j);
end = stack_grows_down_p ? (char *) &j + sizeof j : (char *) &j;
#endif /* not GC_SAVE_REGISTERS_ON_STACK */
#endif /* not HAVE___BUILTIN_UNWIND_INIT */
SET_STACK_TOP_ADDRESS (&end);
return garbage_collect_1 (end);
}
@ -7408,9 +7360,6 @@ init_alloc_once (void)
void
init_alloc (void)
{
#if !defined GC_SAVE_REGISTERS_ON_STACK && !defined GC_SETJMP_WORKS
setjmp_tested_p = longjmps_done = 0;
#endif
Vgc_elapsed = make_float (0.0);
gcs_done = 0;