From: Nikodemus Siivola Date: Mon, 2 Apr 2007 08:37:36 +0000 (+0000) Subject: 1.0.4.16: some GC and interrupt refactoring X-Git-Url: http://repo.macrolet.net/gitweb/?a=commitdiff_plain;h=3be1ab042ab74e008e40626cc6bd5190b27da033;p=sbcl.git 1.0.4.16: some GC and interrupt refactoring * Conditionalize foreign_function_call_active on FOREIGN_FUNCTION_CALL_FLAG for clarity, and excice it from x86 assember code. * Rename interrupt_maybe_gc to cheyneygc_handle_wp_violation, and move it cheyneygc.c. Don't pretend it is a signal handler, but pass in just the context and faulting address it needs. * Make gc_trigger_hit to accept the faulting address directly, since we already have it handy, and move it to cheneygc.c. * Rename interrupt_maybe_gc_int to maybe_gc, and move it to gc-common.c. Don't pretend it is a signal handler, but pass in just the context it needs. * maybe_gc_pending unused, deleted. * Only a single bytes_consed_between_gcs declaration, in gc.h. * Whitespace. No significant functional changes. Tested on x86/GENCGC, PPC/GENCGC, and PPC/Cheney. ...did you know that stepping is broken on PPC/Cheney but not on PPC/GENCGC? --- diff --git a/src/code/hash-table.lisp b/src/code/hash-table.lisp index 8ad97f3..22740e5 100644 --- a/src/code/hash-table.lisp +++ b/src/code/hash-table.lisp @@ -87,7 +87,7 @@ (defmacro-mundanely with-hash-table-iterator ((function hash-table) &body body) #!+sb-doc - "WITH-HASH-TABLE-ITERATOR ((function hash-table) &body body) + "WITH-HASH-TABLE-ITERATOR ((function hash-table) &body body) Provides a method of manually looping over the elements of a hash-table. FUNCTION is bound to a generator-macro that, within the scope of the diff --git a/src/compiler/ppc/insts.lisp b/src/compiler/ppc/insts.lisp index 14563c0..8229af3 100644 --- a/src/compiler/ppc/insts.lisp +++ b/src/compiler/ppc/insts.lisp @@ -640,8 +640,7 @@ (#.fun-end-breakpoint-trap (nt "Function end breakpoint trap")) (#.object-not-instance-trap - (nt "Object not instance trap")) - ))) + (nt "Object not instance trap"))))) (eval-when (:compile-toplevel :execute) diff --git a/src/runtime/bsd-os.c b/src/runtime/bsd-os.c index 1b01396..dffa492 100644 --- a/src/runtime/bsd-os.c +++ b/src/runtime/bsd-os.c @@ -207,7 +207,7 @@ memory_fault_handler(int signal, siginfo_t *siginfo, void *void_context #ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK lisp_memory_fault_error(context, fault_addr); #else - if (!interrupt_maybe_gc_int(signal, siginfo, context)) { + if (!maybe_gc(context)) { interrupt_handle_now(signal, siginfo, context); } #if defined(LISP_FEATURE_DARWIN) @@ -269,9 +269,9 @@ sigsegv_handler(int signal, siginfo_t *info, void* void_context) unsigned int pc = (unsigned int *)(*os_context_pc_addr(context)); os_vm_address_t addr; - addr = arch_get_bad_addr(signal,info,context); - if(!interrupt_maybe_gc(signal, info, context)) - if(!handle_guard_page_triggered(context,addr)) + addr = arch_get_bad_addr(signal, info, context); + if (!cheneygc_handle_wp_violation(context, addr)) + if (!handle_guard_page_triggered(context, addr)) interrupt_handle_now(signal, info, context); /* Work around G5 bug; fix courtesy gbyers */ DARWIN_FIX_CONTEXT(context); diff --git a/src/runtime/cheneygc-internal.h b/src/runtime/cheneygc-internal.h index 874cff6..5b58bf6 100644 --- a/src/runtime/cheneygc-internal.h +++ b/src/runtime/cheneygc-internal.h @@ -48,3 +48,4 @@ new_space_p(lispobj object) #endif +extern boolean cheneygc_handle_wp_violation(os_context_t*, void*); diff --git a/src/runtime/cheneygc.c b/src/runtime/cheneygc.c index 0f7d38b..25e9252 100644 --- a/src/runtime/cheneygc.c +++ b/src/runtime/cheneygc.c @@ -48,8 +48,6 @@ lispobj *new_space_free_pointer; static void scavenge_newspace(void); -extern unsigned long bytes_consed_between_gcs; - /* collecting garbage */ @@ -623,3 +621,42 @@ void clear_auto_gc_trigger(void) current_auto_gc_trigger = NULL; } + +static boolean +gc_trigger_hit(void *addr) +{ + if (current_auto_gc_trigger == NULL) + return 0; + else{ + return (addr >= (void *)current_auto_gc_trigger && + addr <((void *)current_dynamic_space + dynamic_space_size)); + } +} + +boolean +cheneygc_handle_wp_violation(os_context_t *context, void *addr) +{ + if(!foreign_function_call_active && gc_trigger_hit(addr)){ + struct thread *thread=arch_os_get_current_thread(); + clear_auto_gc_trigger(); + /* Don't flood the system with interrupts if the need to gc is + * already noted. This can happen for example when SUB-GC + * allocates or after a gc triggered in a WITHOUT-GCING. */ + if (SymbolValue(GC_PENDING,thread) == NIL) { + if (SymbolValue(GC_INHIBIT,thread) == NIL) { + if (arch_pseudo_atomic_atomic(context)) { + /* set things up so that GC happens when we finish + * the PA section */ + SetSymbolValue(GC_PENDING,T,thread); + arch_set_pseudo_atomic_interrupted(context); + } else { + maybe_gc(context); + } + } else { + SetSymbolValue(GC_PENDING,T,thread); + } + } + return 1; + } + return 0; +} diff --git a/src/runtime/gc-common.c b/src/runtime/gc-common.c index f84d150..4182448 100644 --- a/src/runtime/gc-common.c +++ b/src/runtime/gc-common.c @@ -2435,3 +2435,46 @@ gc_search_space(lispobj *start, size_t words, lispobj *pointer) } return (NULL); } + +boolean +maybe_gc(os_context_t *context) +{ +#ifndef LISP_FEATURE_WIN32 + struct thread *thread = arch_os_get_current_thread(); +#endif + + fake_foreign_function_call(context); + /* SUB-GC may return without GCing if *GC-INHIBIT* is set, in + * which case we will be running with no gc trigger barrier + * thing for a while. But it shouldn't be long until the end + * of WITHOUT-GCING. + * + * FIXME: It would be good to protect the end of dynamic space for + * CheneyGC and signal a storage condition from there. + */ + + /* Restore the signal mask from the interrupted context before + * calling into Lisp if interrupts are enabled. Why not always? + * + * Suppose there is a WITHOUT-INTERRUPTS block far, far out. If an + * interrupt hits while in SUB-GC, it is deferred and the + * os_context_sigmask of that interrupt is set to block further + * deferrable interrupts (until the first one is + * handled). Unfortunately, that context refers to this place and + * when we return from here the signals will not be blocked. + * + * A kludgy alternative is to propagate the sigmask change to the + * outer context. + */ +#ifndef LISP_FEATURE_WIN32 + if(SymbolValue(INTERRUPTS_ENABLED,thread)!=NIL) { + thread_sigmask(SIG_SETMASK, os_context_sigmask_addr(context), 0); + check_gc_signals_unblocked_or_lose(); + } + else + unblock_gc_signals(); +#endif + funcall0(SymbolFunction(SUB_GC)); + undo_fake_foreign_function_call(context); + return 1; +} diff --git a/src/runtime/gc.h b/src/runtime/gc.h index 76a10e1..224ae6c 100644 --- a/src/runtime/gc.h +++ b/src/runtime/gc.h @@ -38,10 +38,12 @@ extern void gc_init_tables(void); extern void set_auto_gc_trigger(os_vm_size_t usage); extern void clear_auto_gc_trigger(void); -extern int maybe_gc_pending; - #include "fixnump.h" #include "pseudo-atomic.h" +extern boolean maybe_gc(os_context_t *context); + +extern unsigned long bytes_consed_between_gcs; + #endif /* _GC_H_ */ diff --git a/src/runtime/gencgc.c b/src/runtime/gencgc.c index 37b8b8e..136e23e 100644 --- a/src/runtime/gencgc.c +++ b/src/runtime/gencgc.c @@ -145,7 +145,6 @@ boolean gencgc_partial_pickup = 0; /* the total bytes allocated. These are seen by Lisp DYNAMIC-USAGE. */ unsigned long bytes_allocated = 0; -extern unsigned long bytes_consed_between_gcs; /* gc-common.c */ unsigned long auto_gc_trigger = 0; /* the source and destination generations. These are set before a GC starts diff --git a/src/runtime/globals.c b/src/runtime/globals.c index 3d0139a..2b397cb 100644 --- a/src/runtime/globals.c +++ b/src/runtime/globals.c @@ -22,7 +22,9 @@ #include "globals.h" #include "validate.h" +#ifdef FOREIGN_FUNCTION_CALL_FLAG int foreign_function_call_active; +#endif lispobj *current_control_stack_pointer; lispobj *current_control_frame_pointer; @@ -65,9 +67,11 @@ void globals_init(void) current_auto_gc_trigger = NULL; #endif - /* Set foreign function call active. */ +#ifdef FOREIGN_FUNCTION_CALL_FLAG foreign_function_call_active = 1; -#if defined(LISP_FEATURE_SB_THREAD) +#endif + +#ifdef LISP_FEATURE_SB_THREAD pthread_key_create(&specials,0); #endif } diff --git a/src/runtime/globals.h b/src/runtime/globals.h index 4d83b31..de4b61f 100644 --- a/src/runtime/globals.h +++ b/src/runtime/globals.h @@ -20,8 +20,18 @@ #include "sbcl.h" +/* Currently threads live only on x86oid platforms, but this thing + * cannot ever work with threads, so... */ +#if !defined(LISP_FEATURE_SB_THREAD) && !defined(LISP_FEATURE_X86) && !defined(LISP_FEATURE_X86_64) +#define FOREIGN_FUNCTION_CALL_FLAG +#endif + #ifndef LANGUAGE_ASSEMBLY + +#ifdef FOREIGN_FUNCTION_CALL_FLAG extern int foreign_function_call_active; +#endif + extern size_t dynamic_space_size; #ifdef LISP_FEATURE_WIN32 @@ -102,7 +112,9 @@ extern void globals_init(void); # define POINTERSIZE 4 # endif +#ifdef FOREIGN_FUNCTION_CALL_FLAG EXTERN(foreign_function_call_active, 4) +#endif EXTERN(current_control_stack_pointer, POINTERSIZE) EXTERN(current_control_frame_pointer, POINTERSIZE) diff --git a/src/runtime/interrupt.c b/src/runtime/interrupt.c index 69e890d..7e278d1 100644 --- a/src/runtime/interrupt.c +++ b/src/runtime/interrupt.c @@ -73,7 +73,6 @@ static void store_signal_data_for_later (struct interrupt_data *data, void *handler, int signal, siginfo_t *info, os_context_t *context); -boolean interrupt_maybe_gc_int(int signal, siginfo_t *info, void *v_context); void sigaddset_deferrable(sigset_t *s) @@ -178,7 +177,7 @@ check_interrupts_enabled_or_lose(os_context_t *context) if (SymbolValue(INTERRUPTS_ENABLED,thread) == NIL) lose("interrupts not enabled\n"); if ( -#if !defined(LISP_FEATURE_X86) && !defined(LISP_FEATURE_X86_64) +#ifdef FOREIGN_FUNCTION_CALL_FLAG (!foreign_function_call_active) && #endif arch_pseudo_atomic_atomic(context)) @@ -330,8 +329,9 @@ fake_foreign_function_call(os_context_t *context) thread->interrupt_contexts[context_index] = context; - /* no longer in Lisp now */ +#ifdef FOREIGN_FUNCTION_CALL_FLAG foreign_function_call_active = 1; +#endif } /* blocks all blockable signals. If you are calling from a signal handler, @@ -344,8 +344,9 @@ undo_fake_foreign_function_call(os_context_t *context) /* Block all blockable signals. */ block_blockable_signals(); - /* going back into Lisp */ +#ifdef FOREIGN_FUNCTION_CALL_FLAG foreign_function_call_active = 0; +#endif /* Undo dynamic binding of FREE_INTERRUPT_CONTEXT_INDEX */ unbind(thread); @@ -432,7 +433,7 @@ interrupt_handle_pending(os_context_t *context) /* GC_PENDING is cleared in SUB-GC, or if another thread * is doing a gc already we will get a SIG_STOP_FOR_GC and * that will clear it. */ - interrupt_maybe_gc_int(0,NULL,context); + maybe_gc(context); } check_blockables_blocked_or_lose(); } @@ -441,7 +442,7 @@ interrupt_handle_pending(os_context_t *context) * enabled run the pending handler */ if (!((SymbolValue(INTERRUPTS_ENABLED,thread) == NIL) || ( -#if !defined(LISP_FEATURE_X86) && !defined(LISP_FEATURE_X86_64) +#ifdef FOREIGN_FUNCTION_CALL_FLAG (!foreign_function_call_active) && #endif arch_pseudo_atomic_atomic(context)))) { @@ -496,7 +497,7 @@ void interrupt_handle_now(int signal, siginfo_t *info, void *void_context) { os_context_t *context = (os_context_t*)void_context; -#if !defined(LISP_FEATURE_X86) && !defined(LISP_FEATURE_X86_64) +#ifndef LISP_FEATURE_SB_THREAD boolean were_in_lisp; #endif union interrupt_handler handler; @@ -523,7 +524,7 @@ interrupt_handle_now(int signal, siginfo_t *info, void *void_context) return; } -#if !defined(LISP_FEATURE_X86) && !defined(LISP_FEATURE_X86_64) +#ifdef FOREIGN_FUNCTION_CALL_FLAG were_in_lisp = !foreign_function_call_active; if (were_in_lisp) #endif @@ -649,7 +650,7 @@ maybe_defer_handler(void *handler, struct interrupt_data *data, * actually use its argument for anything on x86, so this branch * may succeed even when context is null (gencgc alloc()) */ if ( -#if !defined(LISP_FEATURE_X86) && !defined(LISP_FEATURE_X86_64) +#ifdef FOREIGN_FUNCTION_CALL_FLAG /* FIXME: this foreign_function_call_active test is dubious at * best. If a foreign call is made in a pseudo atomic section * (?) or more likely a pseudo atomic section is in a foreign @@ -844,18 +845,6 @@ interrupt_handle_now_handler(int signal, siginfo_t *info, void *void_context) */ #ifndef LISP_FEATURE_GENCGC -/* since GENCGC has its own way to record trigger */ -static boolean -gc_trigger_hit(int signal, siginfo_t *info, os_context_t *context) -{ - if (current_auto_gc_trigger == NULL) - return 0; - else{ - void *badaddr=arch_get_bad_addr(signal,info,context); - return (badaddr >= (void *)current_auto_gc_trigger && - badaddr <((void *)current_dynamic_space + dynamic_space_size)); - } -} #endif /* manipulate the signal context and stack such that when the handler @@ -1105,92 +1094,6 @@ handle_guard_page_triggered(os_context_t *context,os_vm_address_t addr) } else return 0; } - -#ifndef LISP_FEATURE_GENCGC -/* This function gets called from the SIGSEGV (for e.g. Linux, NetBSD, & - * OpenBSD) or SIGBUS (for e.g. FreeBSD) handler. Here we check - * whether the signal was due to treading on the mprotect()ed zone - - * and if so, arrange for a GC to happen. */ -extern unsigned long bytes_consed_between_gcs; /* gc-common.c */ - -boolean -interrupt_maybe_gc(int signal, siginfo_t *info, void *void_context) -{ - os_context_t *context=(os_context_t *) void_context; - - if(!foreign_function_call_active && gc_trigger_hit(signal, info, context)){ - struct thread *thread=arch_os_get_current_thread(); - clear_auto_gc_trigger(); - /* Don't flood the system with interrupts if the need to gc is - * already noted. This can happen for example when SUB-GC - * allocates or after a gc triggered in a WITHOUT-GCING. */ - if (SymbolValue(GC_PENDING,thread) == NIL) { - if (SymbolValue(GC_INHIBIT,thread) == NIL) { - if (arch_pseudo_atomic_atomic(context)) { - /* set things up so that GC happens when we finish - * the PA section */ - SetSymbolValue(GC_PENDING,T,thread); - arch_set_pseudo_atomic_interrupted(context); - } else { - interrupt_maybe_gc_int(signal,info,void_context); - } - } else { - SetSymbolValue(GC_PENDING,T,thread); - } - } - return 1; - } - return 0; -} - -#endif - -/* this is also used by gencgc, in alloc() */ -boolean -interrupt_maybe_gc_int(int signal, siginfo_t *info, void *void_context) -{ - os_context_t *context=(os_context_t *) void_context; -#ifndef LISP_FEATURE_WIN32 - struct thread *thread=arch_os_get_current_thread(); -#endif - - fake_foreign_function_call(context); - - /* SUB-GC may return without GCing if *GC-INHIBIT* is set, in - * which case we will be running with no gc trigger barrier - * thing for a while. But it shouldn't be long until the end - * of WITHOUT-GCING. - * - * FIXME: It would be good to protect the end of dynamic space - * and signal a storage condition from there. - */ - - /* Restore the signal mask from the interrupted context before - * calling into Lisp if interrupts are enabled. Why not always? - * - * Suppose there is a WITHOUT-INTERRUPTS block far, far out. If an - * interrupt hits while in SUB-GC, it is deferred and the - * os_context_sigmask of that interrupt is set to block further - * deferrable interrupts (until the first one is - * handled). Unfortunately, that context refers to this place and - * when we return from here the signals will not be blocked. - * - * A kludgy alternative is to propagate the sigmask change to the - * outer context. - */ -#ifndef LISP_FEATURE_WIN32 - if(SymbolValue(INTERRUPTS_ENABLED,thread)!=NIL) { - thread_sigmask(SIG_SETMASK, os_context_sigmask_addr(context), 0); - check_gc_signals_unblocked_or_lose(); - } - else - unblock_gc_signals(); -#endif - funcall0(SymbolFunction(SUB_GC)); - undo_fake_foreign_function_call(context); - return 1; -} - /* * noise to install handlers diff --git a/src/runtime/interrupt.h b/src/runtime/interrupt.h index ee13671..405b354 100644 --- a/src/runtime/interrupt.h +++ b/src/runtime/interrupt.h @@ -68,8 +68,6 @@ extern void interrupt_handle_now(int, siginfo_t*, void*); extern void interrupt_handle_pending(os_context_t*); extern void interrupt_internal_error(os_context_t*, boolean continuable); extern boolean handle_guard_page_triggered(os_context_t *,os_vm_address_t); -extern boolean interrupt_maybe_gc(int, siginfo_t*, void*); -extern boolean interrupt_maybe_gc_int(int, siginfo_t *, void *); extern boolean maybe_defer_handler(void *handler, struct interrupt_data *data, int signal, siginfo_t *info, os_context_t *context); diff --git a/src/runtime/linux-os.c b/src/runtime/linux-os.c index 6724eb1..236a33e 100644 --- a/src/runtime/linux-os.c +++ b/src/runtime/linux-os.c @@ -389,7 +389,7 @@ sigsegv_handler(int signal, siginfo_t *info, void* void_context) #ifdef LISP_FEATURE_GENCGC if (!gencgc_handle_wp_violation(addr)) #else - if (!interrupt_maybe_gc(signal, info, context)) + if (!cheneygc_handle_wp_violation(context, addr)) #endif if (!handle_guard_page_triggered(context, addr)) #ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK diff --git a/src/runtime/osf1-os.c b/src/runtime/osf1-os.c index f2a40b7..baba3bf 100644 --- a/src/runtime/osf1-os.c +++ b/src/runtime/osf1-os.c @@ -133,7 +133,7 @@ sigsegv_handler(int signal, siginfo_t *info, void* void_context) /* this is lifted from linux-os.c, so violates OOAO */ *os_context_register_addr(context,reg_ALLOC) -= (1L<<63); interrupt_handle_pending(context); - } else if (!interrupt_maybe_gc(signal, info, context)) { + } else if (!cheneygc_handle_wp_violation(context, addr)) { if(!handle_guard_page_triggered(context,addr)) interrupt_handle_now(signal, info, context); } diff --git a/src/runtime/ppc-arch.c b/src/runtime/ppc-arch.c index 35dc843..28c364b 100644 --- a/src/runtime/ppc-arch.c +++ b/src/runtime/ppc-arch.c @@ -99,7 +99,7 @@ arch_clear_pseudo_atomic_interrupted(os_context_t *context) *os_context_register_addr(context,reg_ALLOC) &= ~1; } -unsigned int +unsigned int arch_install_breakpoint(void *pc) { unsigned int *ptr = (unsigned int *)pc; @@ -137,9 +137,9 @@ static unsigned int *skipped_break_addr, displaced_after_inst; static sigset_t orig_sigmask; void -arch_do_displaced_inst(os_context_t *context,unsigned int orig_inst) +arch_do_displaced_inst(os_context_t *context, unsigned int orig_inst) { - /* not sure how we ensure that we get the breakpoint reinstalled + /* not sure how we ensure that we get the breakpoint reinstalled * after doing this -dan */ unsigned int *pc = (unsigned int *)(*os_context_pc_addr(context)); @@ -149,6 +149,10 @@ arch_do_displaced_inst(os_context_t *context,unsigned int orig_inst) *pc = orig_inst; os_flush_icache((os_vm_address_t) pc, sizeof(unsigned int)); skipped_break_addr = pc; + + /* FIXME: we should apparently be installing the after-breakpoint + * here, but would need to find the next instruction address for + * it first. alpha-arch.c shows how to do it. --NS 2007-04-02 */ } #ifdef LISP_FEATURE_GENCGC @@ -231,10 +235,8 @@ handle_allocation_trap(os_context_t * context) fprintf(stderr, "In handle_allocation_trap\n"); #endif - /* - * I don't think it's possible for us NOT to be in lisp when we get - * here. Remove this later? - */ + /* I don't think it's possible for us NOT to be in lisp when we get + * here. Remove this later? */ were_in_lisp = !foreign_function_call_active; if (were_in_lisp) { @@ -387,9 +389,6 @@ arch_handle_fun_end_breakpoint(os_context_t *context) =(int)handle_fun_end_breakpoint(context); } -/* FIXME: AFTER-BREAKPOINT-TRAP is defined for PPC, but never - * emitted as far as I can see. Should it be emitted, do removed - * entirely? */ void arch_handle_after_breakpoint(os_context_t *context) { diff --git a/src/runtime/purify.c b/src/runtime/purify.c index e753c13..91b4232 100644 --- a/src/runtime/purify.c +++ b/src/runtime/purify.c @@ -37,8 +37,6 @@ #define PRINTNOISE -extern unsigned long bytes_consed_between_gcs; - static lispobj *dynamic_space_purify_pointer; diff --git a/src/runtime/sunos-os.c b/src/runtime/sunos-os.c index bc4d397..8d8bb28 100644 --- a/src/runtime/sunos-os.c +++ b/src/runtime/sunos-os.c @@ -217,11 +217,10 @@ static void sigsegv_handler(int signal, siginfo_t *info, void* void_context) { os_context_t *context = arch_os_get_context(&void_context); - os_vm_address_t addr; + os_vm_address_t addr = arch_get_bad_addr(signal, info, context); - addr = arch_get_bad_addr(signal, info, context); - if(!interrupt_maybe_gc(signal, info, context)) { - if(!handle_guard_page_triggered(context,addr)) + if (!cheneygc_handle_wp_violation(context, addr)) { + if (!handle_guard_page_triggered(context,addr)) interrupt_handle_now(signal, info, context); } } diff --git a/src/runtime/x86-assem.S b/src/runtime/x86-assem.S index ca2b2d6..c4d2f5e 100644 --- a/src/runtime/x86-assem.S +++ b/src/runtime/x86-assem.S @@ -88,7 +88,6 @@ #endif .text - .globl GNAME(foreign_function_call_active) .globl GNAME(all_threads) /* @@ -107,8 +106,6 @@ .globl GNAME(call_into_c) TYPE(GNAME(call_into_c)) GNAME(call_into_c): - movl $1,GNAME(foreign_function_call_active) - /* Save the return Lisp address in ebx. */ popl %ebx @@ -154,7 +151,6 @@ GNAME(call_into_c): /* Restore the return value. */ movl %ecx,%eax # maybe return value - movl $0,GNAME(foreign_function_call_active) /* Return. */ jmp *%ebx @@ -172,7 +168,6 @@ Lfp_rtn_value: /* We don't need to restore eax, because the result is in st(0). */ - movl $0,GNAME(foreign_function_call_active) /* Return. */ jmp *%ebx @@ -252,8 +247,6 @@ Lstack: xorl %esi,%esi # third arg /* no longer in function call */ - movl %eax, GNAME(foreign_function_call_active) - movl %esp,%ebx # remember current stack pushl %ebx # Save entry stack on (maybe) new stack. diff --git a/version.lisp-expr b/version.lisp-expr index 1754cd8..4b8e5c5 100644 --- a/version.lisp-expr +++ b/version.lisp-expr @@ -17,4 +17,4 @@ ;;; checkins which aren't released. (And occasionally for internal ;;; versions, especially for internal versions off the main CVS ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".) -"1.0.4.15" +"1.0.4.16"