mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-16 00:30:21 +02:00
make catch cache and restore vm regs, not the vm itself -- speedy speedy
* libguile/throw.c (scm_c_catch): Stash away the current vm's regs, and restore them if there's a nonlocal exit. There is a terrible case we have to handle if we catch from when the vm smob type isn't registered but the throw has the vm registered, but I think we handle this fine. * libguile/vm-engine.c (vm_run): * libguile/vm-i-system.c (halt): Don't make a dynwind context, so that entering the VM doesn't cons at all, except for the arg list. Maybe we can fix that bit too. * libguile/vm.c (vm_reset_stack): Remove, as there is no more dynwind. (make_vm): Return #f if the tc16 hasn't yet been registered.
This commit is contained in:
parent
f775e51bce
commit
747a163532
4 changed files with 39 additions and 35 deletions
|
@ -41,6 +41,7 @@
|
|||
#include "libguile/throw.h"
|
||||
#include "libguile/init.h"
|
||||
#include "libguile/strings.h"
|
||||
#include "libguile/vm.h"
|
||||
|
||||
#include "libguile/private-options.h"
|
||||
|
||||
|
@ -169,8 +170,17 @@ scm_c_catch (SCM tag,
|
|||
struct jmp_buf_and_retval jbr;
|
||||
SCM jmpbuf;
|
||||
SCM answer;
|
||||
SCM vm;
|
||||
SCM *sp = NULL, *fp = NULL; /* to reset the vm */
|
||||
struct pre_unwind_data pre_unwind;
|
||||
|
||||
vm = scm_the_vm ();
|
||||
if (SCM_NFALSEP (vm))
|
||||
{
|
||||
sp = SCM_VM_DATA (vm)->sp;
|
||||
fp = SCM_VM_DATA (vm)->fp;
|
||||
}
|
||||
|
||||
jmpbuf = make_jmpbuf ();
|
||||
answer = SCM_EOL;
|
||||
scm_i_set_dynwinds (scm_acons (tag, jmpbuf, scm_i_dynwinds ()));
|
||||
|
@ -199,6 +209,30 @@ scm_c_catch (SCM tag,
|
|||
throw_tag = jbr.throw_tag;
|
||||
jbr.throw_tag = SCM_EOL;
|
||||
jbr.retval = SCM_EOL;
|
||||
if (SCM_NFALSEP (vm))
|
||||
{
|
||||
SCM_VM_DATA (vm)->sp = sp;
|
||||
SCM_VM_DATA (vm)->fp = fp;
|
||||
#ifdef VM_ENABLE_STACK_NULLING
|
||||
/* see vm.c -- you'll have to enable this manually */
|
||||
memset (sp + 1, 0,
|
||||
(SCM_VM_DATA (vm)->stack_size
|
||||
- (sp + 1 - SCM_VM_DATA (vm)->stack_base)) * sizeof(SCM));
|
||||
#endif
|
||||
}
|
||||
else if (SCM_NFALSEP ((vm = scm_the_vm ())))
|
||||
{
|
||||
/* oof, it's possible this catch was called before the vm was
|
||||
booted... yick. anyway, try to reset the vm stack. */
|
||||
SCM_VM_DATA (vm)->sp = SCM_VM_DATA (vm)->stack_base - 1;
|
||||
SCM_VM_DATA (vm)->fp = NULL;
|
||||
#ifdef VM_ENABLE_STACK_NULLING
|
||||
/* see vm.c -- you'll have to enable this manually */
|
||||
memset (SCM_VM_DATA (vm)->stack_base, 0,
|
||||
SCM_VM_DATA (vm)->stack_size * sizeof(SCM));
|
||||
#endif
|
||||
}
|
||||
|
||||
answer = handler (handler_data, throw_tag, throw_args);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -72,7 +72,6 @@ vm_run (SCM vm, SCM program, SCM args)
|
|||
#if VM_USE_HOOKS
|
||||
SCM hook_args = SCM_LIST1 (vm);
|
||||
#endif
|
||||
struct vm_unwind_data wind_data;
|
||||
|
||||
#ifdef HAVE_LABELS_AS_VALUES
|
||||
static void **jump_table = NULL;
|
||||
|
@ -92,19 +91,6 @@ vm_run (SCM vm, SCM program, SCM args)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* dynwind ended in the halt instruction */
|
||||
scm_dynwind_begin (SCM_F_DYNWIND_REWINDABLE);
|
||||
wind_data.vp = vp;
|
||||
wind_data.sp = vp->sp;
|
||||
wind_data.fp = vp->fp;
|
||||
scm_dynwind_unwind_handler (vm_reset_stack, &wind_data, 0);
|
||||
|
||||
/* could do this if we reified all vm stacks -- for now, don't bother changing
|
||||
*the-vm*
|
||||
if (scm_fluid_ref (scm_the_vm_fluid) != vm)
|
||||
scm_dynwind_fluid (scm_the_vm_fluid, vm);
|
||||
*/
|
||||
|
||||
/* Initialization */
|
||||
{
|
||||
SCM prog = program;
|
||||
|
|
|
@ -56,7 +56,6 @@ VM_DEFINE_INSTRUCTION (1, halt, "halt", 0, 0, 0)
|
|||
NULLSTACK (stack_base - sp);
|
||||
}
|
||||
SYNC_ALL ();
|
||||
scm_dynwind_end ();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -67,6 +67,7 @@
|
|||
are NULL. This is useful for checking the internal consistency of the VM's
|
||||
assumptions and its operators, but isn't necessary for normal operation. It
|
||||
will ensure that assertions are enabled. Slows down the VM by about 30%. */
|
||||
/* NB! If you enable this, search for NULLING in throw.c */
|
||||
/* #define VM_ENABLE_STACK_NULLING */
|
||||
|
||||
/* #define VM_ENABLE_PARANOID_ASSERTIONS */
|
||||
|
@ -208,26 +209,6 @@ scm_vm_reinstate_continuations (SCM conts)
|
|||
reinstate_vm_cont (SCM_VM_DATA (SCM_CAAR (conts)), SCM_CDAR (conts));
|
||||
}
|
||||
|
||||
struct vm_unwind_data
|
||||
{
|
||||
struct scm_vm *vp;
|
||||
SCM *sp;
|
||||
SCM *fp;
|
||||
};
|
||||
|
||||
static void
|
||||
vm_reset_stack (void *data)
|
||||
{
|
||||
struct vm_unwind_data *w = data;
|
||||
struct scm_vm *vp = w->vp;
|
||||
|
||||
vp->sp = w->sp;
|
||||
vp->fp = w->fp;
|
||||
#ifdef VM_ENABLE_STACK_NULLING
|
||||
memset (vp->sp + 1, 0, (vp->stack_size - (vp->sp + 1 - vp->stack_base)) * sizeof(SCM));
|
||||
#endif
|
||||
}
|
||||
|
||||
static void enfalsen_frame (void *p)
|
||||
{
|
||||
struct scm_vm *vp = p;
|
||||
|
@ -331,6 +312,10 @@ make_vm (void)
|
|||
#define FUNC_NAME "make_vm"
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!scm_tc16_vm)
|
||||
return SCM_BOOL_F; /* not booted yet */
|
||||
|
||||
struct scm_vm *vp = scm_gc_malloc (sizeof (struct scm_vm), "vm");
|
||||
|
||||
vp->stack_size = VM_DEFAULT_STACK_SIZE;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue