guile/libguile/vm.c

799 lines
19 KiB
C
Raw Normal View History

2001-04-16 03:43:48 +00:00
/* Copyright (C) 2001 Free Software Foundation, Inc.
2000-08-22 15:54:19 +00:00
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307 USA
*
* As a special exception, the Free Software Foundation gives permission
* for additional uses of the text contained in its release of GUILE.
*
* The exception is that, if you link the GUILE library with other files
* to produce an executable, this does not by itself cause the
* resulting executable to be covered by the GNU General Public License.
* Your use of that executable is in no way restricted on account of
* linking the GUILE library code into it.
*
* This exception does not however invalidate any other reasons why
* the executable file might be covered by the GNU General Public License.
*
* This exception applies only to the code released by the
* Free Software Foundation under the name GUILE. If you copy
* code from other Free Software Foundation releases into a copy of
* GUILE, as the General Public License permits, the exception does
* not apply to the code that you add in this way. To avoid misleading
* anyone as to the status of such modified files, you must delete
* this exception notice from them.
*
* If you write modifications of your own for GUILE, it is your choice
* whether to permit this exception to apply to your modifications.
* If you do not wish that, delete this exception notice. */
#if HAVE_CONFIG_H
# include <config.h>
#endif
2001-04-01 05:03:41 +00:00
#include <string.h>
merge guile-vm into libguile itself * ice-9/boot-9.scm: Only define load-compiled as #f if it's not already defined, which won't normally be the case. * libguile/guile-vm.c: Removed, there's no more guile-vm binary. * libguile/frames.c: (with change frame? -> heap-frame?) * libguile/frames.h: * libguile/instructions.c: * libguile/instructions.h: * libguile/objcodes.c: * libguile/objcodes.h: * libguile/programs.c: * libguile/programs.h: * libguile/vm-bootstrap.h: (was bootstrap.h) * libguile/vm-engine.c: (was vm_engine.c) * libguile/vm-engine.h: (was vm_engine.h) * libguile/vm-expand.h: (was vm_expand.h) * libguile/vm-i-loader.c: (was vm_loader.c) * libguile/vm-i-scheme.c: (was vm_scheme.c) * libguile/vm-i-system.c: (was vm_system.c) * libguile/vm.c: * libguile/vm.h: These files moved here from src/, as guile-vm is now a part of libguile. * libguile/init.c: Bootstrap the VM. Yay! * libguile/Makefile.am: The necessary chicanery here. * module/system/vm/Makefile.am: * module/system/vm/bootstrap.scm: * module/system/vm/frame.scm: * module/system/vm/instruction.scm: * module/system/vm/objcode.scm: * module/system/vm/program.scm: * module/system/vm/vm.scm: * pre-inst-guile-env.in: Add builddirs to the load path; add module/ to the path in the empty-$GUILE_LOAD_PATH case as well. * src/Makefile.am: Moved out everything except guilec and guile-disasm, which probably should be moved to the scripts directory? * testsuite/Makefile.am: Update to find guile-vm in the right place. * module/system/vm/Makefile.am: * module/system/vm/bootstrap.scm: Removed bootstrap.scm, scm_init_guile handles the bootstrapping for us. * module/system/vm/frame.scm: * module/system/vm/instruction.scm: * module/system/vm/objcode.scm: * module/system/vm/program.scm: * module/system/vm/vm.scm: Call the init functions in libguile; should fix at some point to avoid the dlopen?
2008-08-21 18:39:30 -07:00
#include "vm-bootstrap.h"
2001-04-22 02:13:48 +00:00
#include "frames.h"
2001-04-01 05:03:41 +00:00
#include "instructions.h"
2001-04-16 03:43:48 +00:00
#include "objcodes.h"
2001-04-22 02:13:48 +00:00
#include "programs.h"
2000-08-22 15:54:19 +00:00
#include "vm.h"
/* I sometimes use this for debugging. */
#define vm_puts(OBJ) \
{ \
enable inlining; speed! * module/system/il/inline.scm: New module, implements generic inlining of scheme functions. It even does the right thing regarding (define arity:nopt caddr) and such. So now there are many more inlines: the arithmetics, `apply', the caddr family, etc. This makes the benchmarks *much* faster. * module/language/scheme/translate.scm (trans): Remove the %scheme-primitives code in favor of the generic (scheme il inline) code. Adds inlining for +, -, =, etc. * src/vm.c (vm_puts): Fix to work. * module/system/base/compile.scm (system): Export load/compile also. * module/system/il/compile.scm (optimize): Further debitrotting, but I haven't tried this function yet. It seems that <ghil-inst> was what <ghil-inline> is. * module/system/il/ghil.scm (*core-primitives*, *macro-module*) (ghil-primitive-macro?, ghil-macro-expander, ghil-primitive?): Remove these unused things. * module/system/il/macros.scm: Removed, replaced with inline.scm. * module/system/vm/assemble.scm (stack->bytes): Before, the final serialization code did an (apply u8vector (apply append (map u8vector->list ...))). Aside from the misspelling of append-map, this ends up pushing all elements of the u8vector on the stack -- assuredly not what you want. But besides even that, I think that pushing more than 32k arguments on the stack brings out some other bug that I think was hidden before, because now we actually use the `apply' VM instruction. Further testing is needed here, I think. Fixed the code to be more efficient, which fixes the manifestation of this particular bug: a failure to self-compile after inlining was enabled. * module/system/vm/bootstrap.scm: New module, serves to bootstrap boot-9's `load-compiled'. That way when we load (system vm core), we're loading compiled code already. * module/system/vm/core.scm: Use (system vm bootstrap). * src/guilec.in: Use the bootstrap code, so that we really are compiling with an entirely compiled compiler. * module/system/repl/repl.scm (default-catch-handler): An attempt at making the repl print a backtrace; more work needed here. * module/system/vm/frame.scm (make-frame-chain): Fix some misspellings -- I think, anyway.
2008-05-25 13:13:15 +02:00
scm_display (OBJ, scm_current_error_port ()); \
scm_newline (scm_current_error_port ()); \
2000-08-22 15:54:19 +00:00
}
precise stack marking, fix some missed references, still imperfect * libguile/vm-engine.h (CHECK_STACK_LEAK, NULLSTACK): Add a new mode, VM_ENABLE_STACK_NULLING, that tries to ensure that all stack data past the top of the stack is NULL. This helps to verify the VM's consistency. If VM_ENABLE_STACK_NULLING is not defined, there is no overhead. (DROP, DROPN): Hook into NULLSTACK. (POP_LIST): Hoo, fix a good bug: if CONS triggered a GC, the elements of the list that had not yet been consed would not be marked, because the sp was already below them. (NEXT): Hook into CHECK_STACK_LEAK. (INIT_ARGS): Add a note that consing the rest arg can cause GC. (NEW_FRAME): Cons up the external data after initializing the frame, so that if GC is triggered, the precise marker sees a well-formed frame. * libguile/vm-i-loader.c (load-program): In the four-integers case, use the POP macro so that we can hook into NULLSTACK (if necessary). * libguile/vm-i-scheme.c (ARGS2, ARGS3): Hook into NULLSTACK. * libguile/vm-i-system.c (halt): Null the nvalues. Rework some asserts into using ASSERT, and null the stack when we free the frame. (variable-set): Use DROPN instead of sp -= 2. (BR): Hook into NULLSTACK. (goto/args): Hook into NULLSTACK. In the non-self case, delay updating the frame until after INIT_ARGS so that GC sees a well-formed frame. Delay consing the externals until after the frame is set up, as in NEW_FRAME. (call/cc): Add some asserts. (return): Rework some asserts into ASSERT, and hook into NULLSTACK. (return/values): Hook into NULLSTACK, and use ASSERT. (return/values*) Use ASSERT. * libguile/vm.c (VM_ENABLE_ASSERTIONS, VM_ENABLE_STACK_NULLING): These are the variables that control assertions and nulling. Perhaps we can do these per-engine when we start compiling the debug engine separate from a speedy engine. (vm_mark_stack): Add a precise stack marker. Yay! (vm_cont_mark): Mark the continuation stack precisely. (capture_vm_cont): Record the difference from the vp's stack_base too, so that we can translate the dynamic links when marking the continuation stack. Memset the stack to NULL if we are doing nulling. (reinstate_vm_cont): If we are nulling, null out the relevant part of the stack. (vm_reset_stack): When resetting sp due to a nonlocal exit, null out the stack too. (vm_mark): If we are nulling, assert that there are no extra values on the stack. Mark the stack precisely.
2008-10-03 16:00:30 +02:00
/* The VM has a number of internal assertions that shouldn't normally be
necessary, but might be if you think you found a bug in the VM. */
#define VM_ENABLE_ASSERTIONS
/* We can add a mode that ensures that all stack items above the stack pointer
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. */
#define VM_ENABLE_STACK_NULLING
#if defined (VM_ENABLE_STACK_NULLING) && !defined (VM_ENABLE_ASSERTIONS)
#define VM_ENABLE_ASSERTIONS
#endif
2000-08-22 15:54:19 +00:00
/*
* VM Continuation
*/
scm_t_bits scm_tc16_vm_cont;
2001-04-01 05:03:41 +00:00
struct scm_vm_cont {
scm_byte_t *ip;
scm_t_ptrdiff sp;
scm_t_ptrdiff fp;
scm_t_ptrdiff stack_size;
SCM *stack_base;
precise stack marking, fix some missed references, still imperfect * libguile/vm-engine.h (CHECK_STACK_LEAK, NULLSTACK): Add a new mode, VM_ENABLE_STACK_NULLING, that tries to ensure that all stack data past the top of the stack is NULL. This helps to verify the VM's consistency. If VM_ENABLE_STACK_NULLING is not defined, there is no overhead. (DROP, DROPN): Hook into NULLSTACK. (POP_LIST): Hoo, fix a good bug: if CONS triggered a GC, the elements of the list that had not yet been consed would not be marked, because the sp was already below them. (NEXT): Hook into CHECK_STACK_LEAK. (INIT_ARGS): Add a note that consing the rest arg can cause GC. (NEW_FRAME): Cons up the external data after initializing the frame, so that if GC is triggered, the precise marker sees a well-formed frame. * libguile/vm-i-loader.c (load-program): In the four-integers case, use the POP macro so that we can hook into NULLSTACK (if necessary). * libguile/vm-i-scheme.c (ARGS2, ARGS3): Hook into NULLSTACK. * libguile/vm-i-system.c (halt): Null the nvalues. Rework some asserts into using ASSERT, and null the stack when we free the frame. (variable-set): Use DROPN instead of sp -= 2. (BR): Hook into NULLSTACK. (goto/args): Hook into NULLSTACK. In the non-self case, delay updating the frame until after INIT_ARGS so that GC sees a well-formed frame. Delay consing the externals until after the frame is set up, as in NEW_FRAME. (call/cc): Add some asserts. (return): Rework some asserts into ASSERT, and hook into NULLSTACK. (return/values): Hook into NULLSTACK, and use ASSERT. (return/values*) Use ASSERT. * libguile/vm.c (VM_ENABLE_ASSERTIONS, VM_ENABLE_STACK_NULLING): These are the variables that control assertions and nulling. Perhaps we can do these per-engine when we start compiling the debug engine separate from a speedy engine. (vm_mark_stack): Add a precise stack marker. Yay! (vm_cont_mark): Mark the continuation stack precisely. (capture_vm_cont): Record the difference from the vp's stack_base too, so that we can translate the dynamic links when marking the continuation stack. Memset the stack to NULL if we are doing nulling. (reinstate_vm_cont): If we are nulling, null out the relevant part of the stack. (vm_reset_stack): When resetting sp due to a nonlocal exit, null out the stack too. (vm_mark): If we are nulling, assert that there are no extra values on the stack. Mark the stack precisely.
2008-10-03 16:00:30 +02:00
scm_t_ptrdiff reloc;
};
2001-04-01 05:03:41 +00:00
#define SCM_VM_CONT_P(OBJ) SCM_SMOB_PREDICATE (scm_tc16_vm_cont, OBJ)
#define SCM_VM_CONT_DATA(CONT) ((struct scm_vm_cont *) SCM_CELL_WORD_1 (CONT))
precise stack marking, fix some missed references, still imperfect * libguile/vm-engine.h (CHECK_STACK_LEAK, NULLSTACK): Add a new mode, VM_ENABLE_STACK_NULLING, that tries to ensure that all stack data past the top of the stack is NULL. This helps to verify the VM's consistency. If VM_ENABLE_STACK_NULLING is not defined, there is no overhead. (DROP, DROPN): Hook into NULLSTACK. (POP_LIST): Hoo, fix a good bug: if CONS triggered a GC, the elements of the list that had not yet been consed would not be marked, because the sp was already below them. (NEXT): Hook into CHECK_STACK_LEAK. (INIT_ARGS): Add a note that consing the rest arg can cause GC. (NEW_FRAME): Cons up the external data after initializing the frame, so that if GC is triggered, the precise marker sees a well-formed frame. * libguile/vm-i-loader.c (load-program): In the four-integers case, use the POP macro so that we can hook into NULLSTACK (if necessary). * libguile/vm-i-scheme.c (ARGS2, ARGS3): Hook into NULLSTACK. * libguile/vm-i-system.c (halt): Null the nvalues. Rework some asserts into using ASSERT, and null the stack when we free the frame. (variable-set): Use DROPN instead of sp -= 2. (BR): Hook into NULLSTACK. (goto/args): Hook into NULLSTACK. In the non-self case, delay updating the frame until after INIT_ARGS so that GC sees a well-formed frame. Delay consing the externals until after the frame is set up, as in NEW_FRAME. (call/cc): Add some asserts. (return): Rework some asserts into ASSERT, and hook into NULLSTACK. (return/values): Hook into NULLSTACK, and use ASSERT. (return/values*) Use ASSERT. * libguile/vm.c (VM_ENABLE_ASSERTIONS, VM_ENABLE_STACK_NULLING): These are the variables that control assertions and nulling. Perhaps we can do these per-engine when we start compiling the debug engine separate from a speedy engine. (vm_mark_stack): Add a precise stack marker. Yay! (vm_cont_mark): Mark the continuation stack precisely. (capture_vm_cont): Record the difference from the vp's stack_base too, so that we can translate the dynamic links when marking the continuation stack. Memset the stack to NULL if we are doing nulling. (reinstate_vm_cont): If we are nulling, null out the relevant part of the stack. (vm_reset_stack): When resetting sp due to a nonlocal exit, null out the stack too. (vm_mark): If we are nulling, assert that there are no extra values on the stack. Mark the stack precisely.
2008-10-03 16:00:30 +02:00
static void
vm_mark_stack (SCM *base, scm_t_ptrdiff size, SCM *fp, scm_t_ptrdiff reloc)
{
SCM *sp, *upper, *lower;
sp = base + size - 1;
while (sp > base && fp)
{
upper = SCM_FRAME_UPPER_ADDRESS (fp);
lower = SCM_FRAME_LOWER_ADDRESS (fp);
for (; sp >= upper; sp--)
if (SCM_NIMP (*sp))
{
if (scm_in_heap_p (*sp))
scm_gc_mark (*sp);
else
fprintf (stderr, "BADNESS: crap on the stack: %p\n", *sp);
}
/* skip ra, mvra */
sp -= 2;
/* update fp from the dynamic link */
fp = (SCM*)*sp-- + reloc;
/* mark from the hl down to the lower address */
for (; sp >= lower; sp--)
if (*sp && SCM_NIMP (*sp))
scm_gc_mark (*sp);
}
}
static SCM
vm_cont_mark (SCM obj)
{
precise stack marking, fix some missed references, still imperfect * libguile/vm-engine.h (CHECK_STACK_LEAK, NULLSTACK): Add a new mode, VM_ENABLE_STACK_NULLING, that tries to ensure that all stack data past the top of the stack is NULL. This helps to verify the VM's consistency. If VM_ENABLE_STACK_NULLING is not defined, there is no overhead. (DROP, DROPN): Hook into NULLSTACK. (POP_LIST): Hoo, fix a good bug: if CONS triggered a GC, the elements of the list that had not yet been consed would not be marked, because the sp was already below them. (NEXT): Hook into CHECK_STACK_LEAK. (INIT_ARGS): Add a note that consing the rest arg can cause GC. (NEW_FRAME): Cons up the external data after initializing the frame, so that if GC is triggered, the precise marker sees a well-formed frame. * libguile/vm-i-loader.c (load-program): In the four-integers case, use the POP macro so that we can hook into NULLSTACK (if necessary). * libguile/vm-i-scheme.c (ARGS2, ARGS3): Hook into NULLSTACK. * libguile/vm-i-system.c (halt): Null the nvalues. Rework some asserts into using ASSERT, and null the stack when we free the frame. (variable-set): Use DROPN instead of sp -= 2. (BR): Hook into NULLSTACK. (goto/args): Hook into NULLSTACK. In the non-self case, delay updating the frame until after INIT_ARGS so that GC sees a well-formed frame. Delay consing the externals until after the frame is set up, as in NEW_FRAME. (call/cc): Add some asserts. (return): Rework some asserts into ASSERT, and hook into NULLSTACK. (return/values): Hook into NULLSTACK, and use ASSERT. (return/values*) Use ASSERT. * libguile/vm.c (VM_ENABLE_ASSERTIONS, VM_ENABLE_STACK_NULLING): These are the variables that control assertions and nulling. Perhaps we can do these per-engine when we start compiling the debug engine separate from a speedy engine. (vm_mark_stack): Add a precise stack marker. Yay! (vm_cont_mark): Mark the continuation stack precisely. (capture_vm_cont): Record the difference from the vp's stack_base too, so that we can translate the dynamic links when marking the continuation stack. Memset the stack to NULL if we are doing nulling. (reinstate_vm_cont): If we are nulling, null out the relevant part of the stack. (vm_reset_stack): When resetting sp due to a nonlocal exit, null out the stack too. (vm_mark): If we are nulling, assert that there are no extra values on the stack. Mark the stack precisely.
2008-10-03 16:00:30 +02:00
struct scm_vm_cont *p = SCM_VM_CONT_DATA (obj);
precise stack marking, fix some missed references, still imperfect * libguile/vm-engine.h (CHECK_STACK_LEAK, NULLSTACK): Add a new mode, VM_ENABLE_STACK_NULLING, that tries to ensure that all stack data past the top of the stack is NULL. This helps to verify the VM's consistency. If VM_ENABLE_STACK_NULLING is not defined, there is no overhead. (DROP, DROPN): Hook into NULLSTACK. (POP_LIST): Hoo, fix a good bug: if CONS triggered a GC, the elements of the list that had not yet been consed would not be marked, because the sp was already below them. (NEXT): Hook into CHECK_STACK_LEAK. (INIT_ARGS): Add a note that consing the rest arg can cause GC. (NEW_FRAME): Cons up the external data after initializing the frame, so that if GC is triggered, the precise marker sees a well-formed frame. * libguile/vm-i-loader.c (load-program): In the four-integers case, use the POP macro so that we can hook into NULLSTACK (if necessary). * libguile/vm-i-scheme.c (ARGS2, ARGS3): Hook into NULLSTACK. * libguile/vm-i-system.c (halt): Null the nvalues. Rework some asserts into using ASSERT, and null the stack when we free the frame. (variable-set): Use DROPN instead of sp -= 2. (BR): Hook into NULLSTACK. (goto/args): Hook into NULLSTACK. In the non-self case, delay updating the frame until after INIT_ARGS so that GC sees a well-formed frame. Delay consing the externals until after the frame is set up, as in NEW_FRAME. (call/cc): Add some asserts. (return): Rework some asserts into ASSERT, and hook into NULLSTACK. (return/values): Hook into NULLSTACK, and use ASSERT. (return/values*) Use ASSERT. * libguile/vm.c (VM_ENABLE_ASSERTIONS, VM_ENABLE_STACK_NULLING): These are the variables that control assertions and nulling. Perhaps we can do these per-engine when we start compiling the debug engine separate from a speedy engine. (vm_mark_stack): Add a precise stack marker. Yay! (vm_cont_mark): Mark the continuation stack precisely. (capture_vm_cont): Record the difference from the vp's stack_base too, so that we can translate the dynamic links when marking the continuation stack. Memset the stack to NULL if we are doing nulling. (reinstate_vm_cont): If we are nulling, null out the relevant part of the stack. (vm_reset_stack): When resetting sp due to a nonlocal exit, null out the stack too. (vm_mark): If we are nulling, assert that there are no extra values on the stack. Mark the stack precisely.
2008-10-03 16:00:30 +02:00
vm_mark_stack (p->stack_base, p->stack_size, p->stack_base + p->fp, p->reloc);
return SCM_BOOL_F;
}
static scm_sizet
vm_cont_free (SCM obj)
{
struct scm_vm_cont *p = SCM_VM_CONT_DATA (obj);
scm_gc_free (p->stack_base, p->stack_size * sizeof (SCM), "stack-base");
scm_gc_free (p, sizeof (struct scm_vm), "vm");
return 0;
}
2000-08-22 15:54:19 +00:00
static SCM
2001-04-06 00:17:39 +00:00
capture_vm_cont (struct scm_vm *vp)
2000-08-22 15:54:19 +00:00
{
struct scm_vm_cont *p = scm_gc_malloc (sizeof (*p), "capture_vm_cont");
p->stack_size = vp->sp - vp->stack_base + 1;
p->stack_base = scm_gc_malloc (p->stack_size * sizeof (SCM),
"capture_vm_cont");
precise stack marking, fix some missed references, still imperfect * libguile/vm-engine.h (CHECK_STACK_LEAK, NULLSTACK): Add a new mode, VM_ENABLE_STACK_NULLING, that tries to ensure that all stack data past the top of the stack is NULL. This helps to verify the VM's consistency. If VM_ENABLE_STACK_NULLING is not defined, there is no overhead. (DROP, DROPN): Hook into NULLSTACK. (POP_LIST): Hoo, fix a good bug: if CONS triggered a GC, the elements of the list that had not yet been consed would not be marked, because the sp was already below them. (NEXT): Hook into CHECK_STACK_LEAK. (INIT_ARGS): Add a note that consing the rest arg can cause GC. (NEW_FRAME): Cons up the external data after initializing the frame, so that if GC is triggered, the precise marker sees a well-formed frame. * libguile/vm-i-loader.c (load-program): In the four-integers case, use the POP macro so that we can hook into NULLSTACK (if necessary). * libguile/vm-i-scheme.c (ARGS2, ARGS3): Hook into NULLSTACK. * libguile/vm-i-system.c (halt): Null the nvalues. Rework some asserts into using ASSERT, and null the stack when we free the frame. (variable-set): Use DROPN instead of sp -= 2. (BR): Hook into NULLSTACK. (goto/args): Hook into NULLSTACK. In the non-self case, delay updating the frame until after INIT_ARGS so that GC sees a well-formed frame. Delay consing the externals until after the frame is set up, as in NEW_FRAME. (call/cc): Add some asserts. (return): Rework some asserts into ASSERT, and hook into NULLSTACK. (return/values): Hook into NULLSTACK, and use ASSERT. (return/values*) Use ASSERT. * libguile/vm.c (VM_ENABLE_ASSERTIONS, VM_ENABLE_STACK_NULLING): These are the variables that control assertions and nulling. Perhaps we can do these per-engine when we start compiling the debug engine separate from a speedy engine. (vm_mark_stack): Add a precise stack marker. Yay! (vm_cont_mark): Mark the continuation stack precisely. (capture_vm_cont): Record the difference from the vp's stack_base too, so that we can translate the dynamic links when marking the continuation stack. Memset the stack to NULL if we are doing nulling. (reinstate_vm_cont): If we are nulling, null out the relevant part of the stack. (vm_reset_stack): When resetting sp due to a nonlocal exit, null out the stack too. (vm_mark): If we are nulling, assert that there are no extra values on the stack. Mark the stack precisely.
2008-10-03 16:00:30 +02:00
#ifdef VM_ENABLE_STACK_NULLING
if (vp->sp >= vp->stack_base)
if (!vp->sp[0] || vp->sp[1])
abort ();
precise stack marking, fix some missed references, still imperfect * libguile/vm-engine.h (CHECK_STACK_LEAK, NULLSTACK): Add a new mode, VM_ENABLE_STACK_NULLING, that tries to ensure that all stack data past the top of the stack is NULL. This helps to verify the VM's consistency. If VM_ENABLE_STACK_NULLING is not defined, there is no overhead. (DROP, DROPN): Hook into NULLSTACK. (POP_LIST): Hoo, fix a good bug: if CONS triggered a GC, the elements of the list that had not yet been consed would not be marked, because the sp was already below them. (NEXT): Hook into CHECK_STACK_LEAK. (INIT_ARGS): Add a note that consing the rest arg can cause GC. (NEW_FRAME): Cons up the external data after initializing the frame, so that if GC is triggered, the precise marker sees a well-formed frame. * libguile/vm-i-loader.c (load-program): In the four-integers case, use the POP macro so that we can hook into NULLSTACK (if necessary). * libguile/vm-i-scheme.c (ARGS2, ARGS3): Hook into NULLSTACK. * libguile/vm-i-system.c (halt): Null the nvalues. Rework some asserts into using ASSERT, and null the stack when we free the frame. (variable-set): Use DROPN instead of sp -= 2. (BR): Hook into NULLSTACK. (goto/args): Hook into NULLSTACK. In the non-self case, delay updating the frame until after INIT_ARGS so that GC sees a well-formed frame. Delay consing the externals until after the frame is set up, as in NEW_FRAME. (call/cc): Add some asserts. (return): Rework some asserts into ASSERT, and hook into NULLSTACK. (return/values): Hook into NULLSTACK, and use ASSERT. (return/values*) Use ASSERT. * libguile/vm.c (VM_ENABLE_ASSERTIONS, VM_ENABLE_STACK_NULLING): These are the variables that control assertions and nulling. Perhaps we can do these per-engine when we start compiling the debug engine separate from a speedy engine. (vm_mark_stack): Add a precise stack marker. Yay! (vm_cont_mark): Mark the continuation stack precisely. (capture_vm_cont): Record the difference from the vp's stack_base too, so that we can translate the dynamic links when marking the continuation stack. Memset the stack to NULL if we are doing nulling. (reinstate_vm_cont): If we are nulling, null out the relevant part of the stack. (vm_reset_stack): When resetting sp due to a nonlocal exit, null out the stack too. (vm_mark): If we are nulling, assert that there are no extra values on the stack. Mark the stack precisely.
2008-10-03 16:00:30 +02:00
memset (p->stack_base, 0, p->stack_size * sizeof (SCM));
#endif
2001-04-06 00:17:39 +00:00
p->ip = vp->ip;
p->sp = vp->sp - vp->stack_base;
p->fp = vp->fp - vp->stack_base;
memcpy (p->stack_base, vp->stack_base, p->stack_size * sizeof (SCM));
precise stack marking, fix some missed references, still imperfect * libguile/vm-engine.h (CHECK_STACK_LEAK, NULLSTACK): Add a new mode, VM_ENABLE_STACK_NULLING, that tries to ensure that all stack data past the top of the stack is NULL. This helps to verify the VM's consistency. If VM_ENABLE_STACK_NULLING is not defined, there is no overhead. (DROP, DROPN): Hook into NULLSTACK. (POP_LIST): Hoo, fix a good bug: if CONS triggered a GC, the elements of the list that had not yet been consed would not be marked, because the sp was already below them. (NEXT): Hook into CHECK_STACK_LEAK. (INIT_ARGS): Add a note that consing the rest arg can cause GC. (NEW_FRAME): Cons up the external data after initializing the frame, so that if GC is triggered, the precise marker sees a well-formed frame. * libguile/vm-i-loader.c (load-program): In the four-integers case, use the POP macro so that we can hook into NULLSTACK (if necessary). * libguile/vm-i-scheme.c (ARGS2, ARGS3): Hook into NULLSTACK. * libguile/vm-i-system.c (halt): Null the nvalues. Rework some asserts into using ASSERT, and null the stack when we free the frame. (variable-set): Use DROPN instead of sp -= 2. (BR): Hook into NULLSTACK. (goto/args): Hook into NULLSTACK. In the non-self case, delay updating the frame until after INIT_ARGS so that GC sees a well-formed frame. Delay consing the externals until after the frame is set up, as in NEW_FRAME. (call/cc): Add some asserts. (return): Rework some asserts into ASSERT, and hook into NULLSTACK. (return/values): Hook into NULLSTACK, and use ASSERT. (return/values*) Use ASSERT. * libguile/vm.c (VM_ENABLE_ASSERTIONS, VM_ENABLE_STACK_NULLING): These are the variables that control assertions and nulling. Perhaps we can do these per-engine when we start compiling the debug engine separate from a speedy engine. (vm_mark_stack): Add a precise stack marker. Yay! (vm_cont_mark): Mark the continuation stack precisely. (capture_vm_cont): Record the difference from the vp's stack_base too, so that we can translate the dynamic links when marking the continuation stack. Memset the stack to NULL if we are doing nulling. (reinstate_vm_cont): If we are nulling, null out the relevant part of the stack. (vm_reset_stack): When resetting sp due to a nonlocal exit, null out the stack too. (vm_mark): If we are nulling, assert that there are no extra values on the stack. Mark the stack precisely.
2008-10-03 16:00:30 +02:00
p->reloc = p->stack_base - vp->stack_base;
2001-04-01 05:03:41 +00:00
SCM_RETURN_NEWSMOB (scm_tc16_vm_cont, p);
2000-08-22 15:54:19 +00:00
}
static void
2001-04-06 00:17:39 +00:00
reinstate_vm_cont (struct scm_vm *vp, SCM cont)
2000-08-22 15:54:19 +00:00
{
struct scm_vm_cont *p = SCM_VM_CONT_DATA (cont);
2001-04-06 00:17:39 +00:00
if (vp->stack_size < p->stack_size)
2000-08-22 15:54:19 +00:00
{
2001-04-01 05:03:41 +00:00
/* puts ("FIXME: Need to expand"); */
2000-08-22 15:54:19 +00:00
abort ();
}
precise stack marking, fix some missed references, still imperfect * libguile/vm-engine.h (CHECK_STACK_LEAK, NULLSTACK): Add a new mode, VM_ENABLE_STACK_NULLING, that tries to ensure that all stack data past the top of the stack is NULL. This helps to verify the VM's consistency. If VM_ENABLE_STACK_NULLING is not defined, there is no overhead. (DROP, DROPN): Hook into NULLSTACK. (POP_LIST): Hoo, fix a good bug: if CONS triggered a GC, the elements of the list that had not yet been consed would not be marked, because the sp was already below them. (NEXT): Hook into CHECK_STACK_LEAK. (INIT_ARGS): Add a note that consing the rest arg can cause GC. (NEW_FRAME): Cons up the external data after initializing the frame, so that if GC is triggered, the precise marker sees a well-formed frame. * libguile/vm-i-loader.c (load-program): In the four-integers case, use the POP macro so that we can hook into NULLSTACK (if necessary). * libguile/vm-i-scheme.c (ARGS2, ARGS3): Hook into NULLSTACK. * libguile/vm-i-system.c (halt): Null the nvalues. Rework some asserts into using ASSERT, and null the stack when we free the frame. (variable-set): Use DROPN instead of sp -= 2. (BR): Hook into NULLSTACK. (goto/args): Hook into NULLSTACK. In the non-self case, delay updating the frame until after INIT_ARGS so that GC sees a well-formed frame. Delay consing the externals until after the frame is set up, as in NEW_FRAME. (call/cc): Add some asserts. (return): Rework some asserts into ASSERT, and hook into NULLSTACK. (return/values): Hook into NULLSTACK, and use ASSERT. (return/values*) Use ASSERT. * libguile/vm.c (VM_ENABLE_ASSERTIONS, VM_ENABLE_STACK_NULLING): These are the variables that control assertions and nulling. Perhaps we can do these per-engine when we start compiling the debug engine separate from a speedy engine. (vm_mark_stack): Add a precise stack marker. Yay! (vm_cont_mark): Mark the continuation stack precisely. (capture_vm_cont): Record the difference from the vp's stack_base too, so that we can translate the dynamic links when marking the continuation stack. Memset the stack to NULL if we are doing nulling. (reinstate_vm_cont): If we are nulling, null out the relevant part of the stack. (vm_reset_stack): When resetting sp due to a nonlocal exit, null out the stack too. (vm_mark): If we are nulling, assert that there are no extra values on the stack. Mark the stack precisely.
2008-10-03 16:00:30 +02:00
#ifdef VM_ENABLE_STACK_NULLING
{
scm_t_ptrdiff nzero = (vp->sp - vp->stack_base) - p->sp;
if (nzero > 0)
memset (vp->stack_base + p->stack_size, 0, nzero * sizeof (SCM));
/* actually nzero should always be negative, because vm_reset_stack will
unwind the stack to some point *below* this continuation */
precise stack marking, fix some missed references, still imperfect * libguile/vm-engine.h (CHECK_STACK_LEAK, NULLSTACK): Add a new mode, VM_ENABLE_STACK_NULLING, that tries to ensure that all stack data past the top of the stack is NULL. This helps to verify the VM's consistency. If VM_ENABLE_STACK_NULLING is not defined, there is no overhead. (DROP, DROPN): Hook into NULLSTACK. (POP_LIST): Hoo, fix a good bug: if CONS triggered a GC, the elements of the list that had not yet been consed would not be marked, because the sp was already below them. (NEXT): Hook into CHECK_STACK_LEAK. (INIT_ARGS): Add a note that consing the rest arg can cause GC. (NEW_FRAME): Cons up the external data after initializing the frame, so that if GC is triggered, the precise marker sees a well-formed frame. * libguile/vm-i-loader.c (load-program): In the four-integers case, use the POP macro so that we can hook into NULLSTACK (if necessary). * libguile/vm-i-scheme.c (ARGS2, ARGS3): Hook into NULLSTACK. * libguile/vm-i-system.c (halt): Null the nvalues. Rework some asserts into using ASSERT, and null the stack when we free the frame. (variable-set): Use DROPN instead of sp -= 2. (BR): Hook into NULLSTACK. (goto/args): Hook into NULLSTACK. In the non-self case, delay updating the frame until after INIT_ARGS so that GC sees a well-formed frame. Delay consing the externals until after the frame is set up, as in NEW_FRAME. (call/cc): Add some asserts. (return): Rework some asserts into ASSERT, and hook into NULLSTACK. (return/values): Hook into NULLSTACK, and use ASSERT. (return/values*) Use ASSERT. * libguile/vm.c (VM_ENABLE_ASSERTIONS, VM_ENABLE_STACK_NULLING): These are the variables that control assertions and nulling. Perhaps we can do these per-engine when we start compiling the debug engine separate from a speedy engine. (vm_mark_stack): Add a precise stack marker. Yay! (vm_cont_mark): Mark the continuation stack precisely. (capture_vm_cont): Record the difference from the vp's stack_base too, so that we can translate the dynamic links when marking the continuation stack. Memset the stack to NULL if we are doing nulling. (reinstate_vm_cont): If we are nulling, null out the relevant part of the stack. (vm_reset_stack): When resetting sp due to a nonlocal exit, null out the stack too. (vm_mark): If we are nulling, assert that there are no extra values on the stack. Mark the stack precisely.
2008-10-03 16:00:30 +02:00
}
#endif
2001-04-06 00:17:39 +00:00
vp->ip = p->ip;
vp->sp = vp->stack_base + p->sp;
vp->fp = vp->stack_base + p->fp;
memcpy (vp->stack_base, p->stack_base, p->stack_size * sizeof (SCM));
}
/* In theory, a number of vm instances can be active in the call trace, and we
only want to reify the continuations of those in the current continuation
root. I don't see a nice way to do this -- ideally it would involve dynwinds,
and previous values of the *the-vm* fluid within the current continuation
root. But we don't have access to continuation roots in the dynwind stack.
So, just punt for now -- take the current value of *the-vm*.
While I'm on the topic, ideally we could avoid copying the C stack if the
continuation root is inside VM code, and call/cc was invoked within that same
call to vm_run; but that's currently not implemented.
*/
SCM
scm_vm_capture_continuations (void)
{
SCM vm = scm_the_vm ();
return scm_acons (vm, capture_vm_cont (SCM_VM_DATA (vm)), SCM_EOL);
}
void
scm_vm_reinstate_continuations (SCM conts)
{
for (; conts != SCM_EOL; conts = SCM_CDR (conts))
reinstate_vm_cont (SCM_VM_DATA (SCM_CAAR (conts)), SCM_CDAR (conts));
2000-08-22 15:54:19 +00:00
}
struct vm_unwind_data
{
struct scm_vm *vp;
SCM *sp;
SCM *fp;
SCM this_frame;
};
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;
vp->this_frame = w->this_frame;
precise stack marking, fix some missed references, still imperfect * libguile/vm-engine.h (CHECK_STACK_LEAK, NULLSTACK): Add a new mode, VM_ENABLE_STACK_NULLING, that tries to ensure that all stack data past the top of the stack is NULL. This helps to verify the VM's consistency. If VM_ENABLE_STACK_NULLING is not defined, there is no overhead. (DROP, DROPN): Hook into NULLSTACK. (POP_LIST): Hoo, fix a good bug: if CONS triggered a GC, the elements of the list that had not yet been consed would not be marked, because the sp was already below them. (NEXT): Hook into CHECK_STACK_LEAK. (INIT_ARGS): Add a note that consing the rest arg can cause GC. (NEW_FRAME): Cons up the external data after initializing the frame, so that if GC is triggered, the precise marker sees a well-formed frame. * libguile/vm-i-loader.c (load-program): In the four-integers case, use the POP macro so that we can hook into NULLSTACK (if necessary). * libguile/vm-i-scheme.c (ARGS2, ARGS3): Hook into NULLSTACK. * libguile/vm-i-system.c (halt): Null the nvalues. Rework some asserts into using ASSERT, and null the stack when we free the frame. (variable-set): Use DROPN instead of sp -= 2. (BR): Hook into NULLSTACK. (goto/args): Hook into NULLSTACK. In the non-self case, delay updating the frame until after INIT_ARGS so that GC sees a well-formed frame. Delay consing the externals until after the frame is set up, as in NEW_FRAME. (call/cc): Add some asserts. (return): Rework some asserts into ASSERT, and hook into NULLSTACK. (return/values): Hook into NULLSTACK, and use ASSERT. (return/values*) Use ASSERT. * libguile/vm.c (VM_ENABLE_ASSERTIONS, VM_ENABLE_STACK_NULLING): These are the variables that control assertions and nulling. Perhaps we can do these per-engine when we start compiling the debug engine separate from a speedy engine. (vm_mark_stack): Add a precise stack marker. Yay! (vm_cont_mark): Mark the continuation stack precisely. (capture_vm_cont): Record the difference from the vp's stack_base too, so that we can translate the dynamic links when marking the continuation stack. Memset the stack to NULL if we are doing nulling. (reinstate_vm_cont): If we are nulling, null out the relevant part of the stack. (vm_reset_stack): When resetting sp due to a nonlocal exit, null out the stack too. (vm_mark): If we are nulling, assert that there are no extra values on the stack. Mark the stack precisely.
2008-10-03 16:00:30 +02:00
#ifdef VM_ENABLE_STACK_NULLING
memset (vp->sp + 1, 0, (vp->stack_size - (vp->sp + 1 - vp->stack_base)) * sizeof(SCM));
precise stack marking, fix some missed references, still imperfect * libguile/vm-engine.h (CHECK_STACK_LEAK, NULLSTACK): Add a new mode, VM_ENABLE_STACK_NULLING, that tries to ensure that all stack data past the top of the stack is NULL. This helps to verify the VM's consistency. If VM_ENABLE_STACK_NULLING is not defined, there is no overhead. (DROP, DROPN): Hook into NULLSTACK. (POP_LIST): Hoo, fix a good bug: if CONS triggered a GC, the elements of the list that had not yet been consed would not be marked, because the sp was already below them. (NEXT): Hook into CHECK_STACK_LEAK. (INIT_ARGS): Add a note that consing the rest arg can cause GC. (NEW_FRAME): Cons up the external data after initializing the frame, so that if GC is triggered, the precise marker sees a well-formed frame. * libguile/vm-i-loader.c (load-program): In the four-integers case, use the POP macro so that we can hook into NULLSTACK (if necessary). * libguile/vm-i-scheme.c (ARGS2, ARGS3): Hook into NULLSTACK. * libguile/vm-i-system.c (halt): Null the nvalues. Rework some asserts into using ASSERT, and null the stack when we free the frame. (variable-set): Use DROPN instead of sp -= 2. (BR): Hook into NULLSTACK. (goto/args): Hook into NULLSTACK. In the non-self case, delay updating the frame until after INIT_ARGS so that GC sees a well-formed frame. Delay consing the externals until after the frame is set up, as in NEW_FRAME. (call/cc): Add some asserts. (return): Rework some asserts into ASSERT, and hook into NULLSTACK. (return/values): Hook into NULLSTACK, and use ASSERT. (return/values*) Use ASSERT. * libguile/vm.c (VM_ENABLE_ASSERTIONS, VM_ENABLE_STACK_NULLING): These are the variables that control assertions and nulling. Perhaps we can do these per-engine when we start compiling the debug engine separate from a speedy engine. (vm_mark_stack): Add a precise stack marker. Yay! (vm_cont_mark): Mark the continuation stack precisely. (capture_vm_cont): Record the difference from the vp's stack_base too, so that we can translate the dynamic links when marking the continuation stack. Memset the stack to NULL if we are doing nulling. (reinstate_vm_cont): If we are nulling, null out the relevant part of the stack. (vm_reset_stack): When resetting sp due to a nonlocal exit, null out the stack too. (vm_mark): If we are nulling, assert that there are no extra values on the stack. Mark the stack precisely.
2008-10-03 16:00:30 +02:00
#endif
}
2001-04-01 05:03:41 +00:00
/*
* VM Internal functions
*/
static SCM sym_vm_run;
static SCM sym_vm_error;
static SCM sym_debug;
2001-04-01 05:03:41 +00:00
static scm_byte_t *
vm_fetch_length (scm_byte_t *ip, size_t *lenp)
2000-08-22 15:54:19 +00:00
{
2001-04-06 23:15:53 +00:00
/* NOTE: format defined in system/vm/conv.scm */
2001-04-01 05:03:41 +00:00
*lenp = *ip++;
if (*lenp < 254)
return ip;
else if (*lenp == 254)
2001-04-05 05:48:59 +00:00
{
int b1 = *ip++;
int b2 = *ip++;
*lenp = (b1 << 8) + b2;
}
2001-04-01 05:03:41 +00:00
else
2001-04-05 05:48:59 +00:00
{
int b1 = *ip++;
int b2 = *ip++;
int b3 = *ip++;
int b4 = *ip++;
*lenp = (b1 << 24) + (b2 << 16) + (b3 << 8) + b4;
}
2001-04-01 05:03:41 +00:00
return ip;
2000-08-22 15:54:19 +00:00
}
2001-04-23 04:28:13 +00:00
static SCM
2001-04-23 06:17:52 +00:00
vm_heapify_frames_1 (struct scm_vm *vp, SCM *fp, SCM *sp, SCM **destp)
2001-04-23 04:28:13 +00:00
{
2001-04-23 06:17:52 +00:00
SCM frame;
2001-04-23 04:28:13 +00:00
SCM *dl = SCM_FRAME_DYNAMIC_LINK (fp);
#if 0
2001-04-23 06:17:52 +00:00
SCM *src = SCM_FRAME_UPPER_ADDRESS (fp);
#endif
2001-04-23 06:17:52 +00:00
SCM *dest = SCM_FRAME_LOWER_ADDRESS (fp);
2001-04-23 04:28:13 +00:00
if (!dl)
{
/* The top frame */
frame = scm_c_make_heap_frame (fp);
fp = SCM_HEAP_FRAME_POINTER (frame);
SCM_FRAME_HEAP_LINK (fp) = SCM_BOOL_T;
}
else
{
2001-04-23 06:17:52 +00:00
/* Child frames */
2001-04-23 04:28:13 +00:00
SCM link = SCM_FRAME_HEAP_LINK (dl);
if (!SCM_FALSEP (link))
2001-04-23 06:17:52 +00:00
link = SCM_FRAME_LOWER_ADDRESS (dl)[-1]; /* self link */
2001-04-23 04:28:13 +00:00
else
2001-04-23 06:17:52 +00:00
link = vm_heapify_frames_1 (vp, dl, dest - 1, &dest);
2001-04-23 04:28:13 +00:00
frame = scm_c_make_heap_frame (fp);
fp = SCM_HEAP_FRAME_POINTER (frame);
/* FIXME: I don't think we should be storing heap links on the stack. */
2001-04-23 04:28:13 +00:00
SCM_FRAME_HEAP_LINK (fp) = link;
SCM_FRAME_SET_DYNAMIC_LINK (fp, SCM_HEAP_FRAME_POINTER (link));
2001-04-23 04:28:13 +00:00
}
/* Apparently the intention here is to be able to have a frame on the heap,
but data on the stack, so that you can push as much as you want on the
stack; but I think that it's currently causing borkage with nonlocal exits
and the unwind handler, which reinstates the sp and fp, but it's no longer
pointing at a valid stack frame. So disable for now, we'll get back to
this later. */
#if 0
2001-04-23 04:28:13 +00:00
/* Move stack data */
2001-04-23 06:17:52 +00:00
for (; src <= sp; src++, dest++)
*dest = *src;
*destp = dest;
#endif
2001-04-23 04:28:13 +00:00
return frame;
}
static SCM
vm_heapify_frames (SCM vm)
{
struct scm_vm *vp = SCM_VM_DATA (vm);
if (SCM_FALSEP (SCM_FRAME_HEAP_LINK (vp->fp)))
{
2001-04-23 06:17:52 +00:00
SCM *dest;
vp->this_frame = vm_heapify_frames_1 (vp, vp->fp, vp->sp, &dest);
2001-04-23 04:28:13 +00:00
vp->fp = SCM_HEAP_FRAME_POINTER (vp->this_frame);
2001-04-23 06:17:52 +00:00
vp->sp = dest - 1;
2001-04-23 04:28:13 +00:00
}
return vp->this_frame;
}
2000-08-22 15:54:19 +00:00
/*
* VM
*/
2001-04-07 11:54:36 +00:00
#define VM_DEFAULT_STACK_SIZE (16 * 1024)
2001-04-01 05:03:41 +00:00
#define VM_REGULAR_ENGINE 0
#define VM_DEBUG_ENGINE 1
#if 0
#define VM_NAME vm_regular_engine
#define VM_ENGINE VM_REGULAR_ENGINE
merge guile-vm into libguile itself * ice-9/boot-9.scm: Only define load-compiled as #f if it's not already defined, which won't normally be the case. * libguile/guile-vm.c: Removed, there's no more guile-vm binary. * libguile/frames.c: (with change frame? -> heap-frame?) * libguile/frames.h: * libguile/instructions.c: * libguile/instructions.h: * libguile/objcodes.c: * libguile/objcodes.h: * libguile/programs.c: * libguile/programs.h: * libguile/vm-bootstrap.h: (was bootstrap.h) * libguile/vm-engine.c: (was vm_engine.c) * libguile/vm-engine.h: (was vm_engine.h) * libguile/vm-expand.h: (was vm_expand.h) * libguile/vm-i-loader.c: (was vm_loader.c) * libguile/vm-i-scheme.c: (was vm_scheme.c) * libguile/vm-i-system.c: (was vm_system.c) * libguile/vm.c: * libguile/vm.h: These files moved here from src/, as guile-vm is now a part of libguile. * libguile/init.c: Bootstrap the VM. Yay! * libguile/Makefile.am: The necessary chicanery here. * module/system/vm/Makefile.am: * module/system/vm/bootstrap.scm: * module/system/vm/frame.scm: * module/system/vm/instruction.scm: * module/system/vm/objcode.scm: * module/system/vm/program.scm: * module/system/vm/vm.scm: * pre-inst-guile-env.in: Add builddirs to the load path; add module/ to the path in the empty-$GUILE_LOAD_PATH case as well. * src/Makefile.am: Moved out everything except guilec and guile-disasm, which probably should be moved to the scripts directory? * testsuite/Makefile.am: Update to find guile-vm in the right place. * module/system/vm/Makefile.am: * module/system/vm/bootstrap.scm: Removed bootstrap.scm, scm_init_guile handles the bootstrapping for us. * module/system/vm/frame.scm: * module/system/vm/instruction.scm: * module/system/vm/objcode.scm: * module/system/vm/program.scm: * module/system/vm/vm.scm: Call the init functions in libguile; should fix at some point to avoid the dlopen?
2008-08-21 18:39:30 -07:00
#include "vm-engine.c"
2001-04-01 05:03:41 +00:00
#undef VM_NAME
#undef VM_ENGINE
#endif
#define VM_NAME vm_debug_engine
#define VM_ENGINE VM_DEBUG_ENGINE
merge guile-vm into libguile itself * ice-9/boot-9.scm: Only define load-compiled as #f if it's not already defined, which won't normally be the case. * libguile/guile-vm.c: Removed, there's no more guile-vm binary. * libguile/frames.c: (with change frame? -> heap-frame?) * libguile/frames.h: * libguile/instructions.c: * libguile/instructions.h: * libguile/objcodes.c: * libguile/objcodes.h: * libguile/programs.c: * libguile/programs.h: * libguile/vm-bootstrap.h: (was bootstrap.h) * libguile/vm-engine.c: (was vm_engine.c) * libguile/vm-engine.h: (was vm_engine.h) * libguile/vm-expand.h: (was vm_expand.h) * libguile/vm-i-loader.c: (was vm_loader.c) * libguile/vm-i-scheme.c: (was vm_scheme.c) * libguile/vm-i-system.c: (was vm_system.c) * libguile/vm.c: * libguile/vm.h: These files moved here from src/, as guile-vm is now a part of libguile. * libguile/init.c: Bootstrap the VM. Yay! * libguile/Makefile.am: The necessary chicanery here. * module/system/vm/Makefile.am: * module/system/vm/bootstrap.scm: * module/system/vm/frame.scm: * module/system/vm/instruction.scm: * module/system/vm/objcode.scm: * module/system/vm/program.scm: * module/system/vm/vm.scm: * pre-inst-guile-env.in: Add builddirs to the load path; add module/ to the path in the empty-$GUILE_LOAD_PATH case as well. * src/Makefile.am: Moved out everything except guilec and guile-disasm, which probably should be moved to the scripts directory? * testsuite/Makefile.am: Update to find guile-vm in the right place. * module/system/vm/Makefile.am: * module/system/vm/bootstrap.scm: Removed bootstrap.scm, scm_init_guile handles the bootstrapping for us. * module/system/vm/frame.scm: * module/system/vm/instruction.scm: * module/system/vm/objcode.scm: * module/system/vm/program.scm: * module/system/vm/vm.scm: Call the init functions in libguile; should fix at some point to avoid the dlopen?
2008-08-21 18:39:30 -07:00
#include "vm-engine.c"
2001-04-01 05:03:41 +00:00
#undef VM_NAME
#undef VM_ENGINE
scm_t_bits scm_tc16_vm;
2000-08-22 15:54:19 +00:00
static SCM
2001-04-01 05:03:41 +00:00
make_vm (void)
#define FUNC_NAME "make_vm"
2000-08-22 15:54:19 +00:00
{
2001-04-01 05:03:41 +00:00
int i;
struct scm_vm *vp = scm_gc_malloc (sizeof (struct scm_vm), "vm");
2001-04-06 00:17:39 +00:00
vp->stack_size = VM_DEFAULT_STACK_SIZE;
vp->stack_base = scm_gc_malloc (vp->stack_size * sizeof (SCM),
"stack-base");
#ifdef VM_ENABLE_STACK_NULLING
memset (vp->stack_base, 0, vp->stack_size * sizeof (SCM));
#endif
2001-04-07 09:39:38 +00:00
vp->stack_limit = vp->stack_base + vp->stack_size - 3;
vp->ip = NULL;
vp->sp = vp->stack_base - 1;
vp->fp = NULL;
2001-04-06 00:17:39 +00:00
vp->time = 0;
vp->clock = 0;
vp->options = SCM_EOL;
2001-04-23 04:28:13 +00:00
vp->this_frame = SCM_BOOL_F;
2001-04-22 02:13:48 +00:00
vp->last_frame = SCM_BOOL_F;
vp->last_ip = NULL;
2001-04-01 05:03:41 +00:00
for (i = 0; i < SCM_VM_NUM_HOOKS; i++)
2001-04-06 00:17:39 +00:00
vp->hooks[i] = SCM_BOOL_F;
SCM_RETURN_NEWSMOB (scm_tc16_vm, vp);
2000-08-22 15:54:19 +00:00
}
2001-04-01 05:03:41 +00:00
#undef FUNC_NAME
2000-08-22 15:54:19 +00:00
static SCM
2001-04-01 05:03:41 +00:00
vm_mark (SCM obj)
2000-08-22 15:54:19 +00:00
{
2001-04-01 05:03:41 +00:00
int i;
2001-04-06 00:17:39 +00:00
struct scm_vm *vp = SCM_VM_DATA (obj);
2001-04-01 05:03:41 +00:00
precise stack marking, fix some missed references, still imperfect * libguile/vm-engine.h (CHECK_STACK_LEAK, NULLSTACK): Add a new mode, VM_ENABLE_STACK_NULLING, that tries to ensure that all stack data past the top of the stack is NULL. This helps to verify the VM's consistency. If VM_ENABLE_STACK_NULLING is not defined, there is no overhead. (DROP, DROPN): Hook into NULLSTACK. (POP_LIST): Hoo, fix a good bug: if CONS triggered a GC, the elements of the list that had not yet been consed would not be marked, because the sp was already below them. (NEXT): Hook into CHECK_STACK_LEAK. (INIT_ARGS): Add a note that consing the rest arg can cause GC. (NEW_FRAME): Cons up the external data after initializing the frame, so that if GC is triggered, the precise marker sees a well-formed frame. * libguile/vm-i-loader.c (load-program): In the four-integers case, use the POP macro so that we can hook into NULLSTACK (if necessary). * libguile/vm-i-scheme.c (ARGS2, ARGS3): Hook into NULLSTACK. * libguile/vm-i-system.c (halt): Null the nvalues. Rework some asserts into using ASSERT, and null the stack when we free the frame. (variable-set): Use DROPN instead of sp -= 2. (BR): Hook into NULLSTACK. (goto/args): Hook into NULLSTACK. In the non-self case, delay updating the frame until after INIT_ARGS so that GC sees a well-formed frame. Delay consing the externals until after the frame is set up, as in NEW_FRAME. (call/cc): Add some asserts. (return): Rework some asserts into ASSERT, and hook into NULLSTACK. (return/values): Hook into NULLSTACK, and use ASSERT. (return/values*) Use ASSERT. * libguile/vm.c (VM_ENABLE_ASSERTIONS, VM_ENABLE_STACK_NULLING): These are the variables that control assertions and nulling. Perhaps we can do these per-engine when we start compiling the debug engine separate from a speedy engine. (vm_mark_stack): Add a precise stack marker. Yay! (vm_cont_mark): Mark the continuation stack precisely. (capture_vm_cont): Record the difference from the vp's stack_base too, so that we can translate the dynamic links when marking the continuation stack. Memset the stack to NULL if we are doing nulling. (reinstate_vm_cont): If we are nulling, null out the relevant part of the stack. (vm_reset_stack): When resetting sp due to a nonlocal exit, null out the stack too. (vm_mark): If we are nulling, assert that there are no extra values on the stack. Mark the stack precisely.
2008-10-03 16:00:30 +02:00
#ifdef VM_ENABLE_STACK_NULLING
if (vp->sp >= vp->stack_base)
if (!vp->sp[0] || vp->sp[1])
abort ();
#endif
/* mark the stack, precisely */
vm_mark_stack (vp->stack_base, vp->sp + 1 - vp->stack_base, vp->fp, 0);
2000-08-22 15:54:19 +00:00
2001-04-23 04:28:13 +00:00
/* mark other objects */
2001-04-01 05:03:41 +00:00
for (i = 0; i < SCM_VM_NUM_HOOKS; i++)
2001-04-06 00:17:39 +00:00
scm_gc_mark (vp->hooks[i]);
2001-04-23 04:28:13 +00:00
scm_gc_mark (vp->this_frame);
2001-04-22 02:13:48 +00:00
scm_gc_mark (vp->last_frame);
2001-04-06 00:17:39 +00:00
return vp->options;
2000-08-22 15:54:19 +00:00
}
2001-04-01 05:03:41 +00:00
static scm_sizet
vm_free (SCM obj)
{
2001-04-06 00:17:39 +00:00
struct scm_vm *vp = SCM_VM_DATA (obj);
scm_gc_free (vp->stack_base, vp->stack_size * sizeof (SCM),
"stack-base");
scm_gc_free (vp, sizeof (struct scm_vm), "vm");
return 0;
2001-04-01 05:03:41 +00:00
}
SCM
scm_vm_apply (SCM vm, SCM program, SCM args)
#define FUNC_NAME "scm_vm_apply"
2000-08-22 15:54:19 +00:00
{
2001-04-01 05:03:41 +00:00
SCM_VALIDATE_PROGRAM (1, program);
2001-04-11 20:57:44 +00:00
return vm_run (vm, program, args);
2000-08-22 15:54:19 +00:00
}
2001-04-01 05:03:41 +00:00
#undef FUNC_NAME
2000-08-22 15:54:19 +00:00
/* Scheme interface */
SCM_DEFINE (scm_vm_version, "vm-version", 0, 0, 0,
2001-04-01 05:03:41 +00:00
(void),
"")
2000-08-22 15:54:19 +00:00
#define FUNC_NAME s_scm_vm_version
{
return scm_from_locale_string (PACKAGE_VERSION);
2000-08-22 15:54:19 +00:00
}
#undef FUNC_NAME
2001-04-06 05:00:10 +00:00
SCM_DEFINE (scm_the_vm, "the-vm", 0, 0, 0,
(void),
2001-04-06 05:00:10 +00:00
"")
#define FUNC_NAME s_scm_the_vm
{
scm_i_thread *t = SCM_I_CURRENT_THREAD;
if (SCM_UNLIKELY (SCM_FALSEP ((t->vm))))
t->vm = make_vm ();
return t->vm;
2001-04-06 05:00:10 +00:00
}
#undef FUNC_NAME
2000-08-22 15:54:19 +00:00
SCM_DEFINE (scm_vm_p, "vm?", 1, 0, 0,
(SCM obj),
2001-04-01 05:03:41 +00:00
"")
2000-08-22 15:54:19 +00:00
#define FUNC_NAME s_scm_vm_p
{
return SCM_BOOL (SCM_VM_P (obj));
}
#undef FUNC_NAME
SCM_DEFINE (scm_make_vm, "make-vm", 0, 0, 0,
2001-04-01 05:03:41 +00:00
(void),
"")
#define FUNC_NAME s_scm_make_vm,
2000-08-22 15:54:19 +00:00
{
2001-04-01 05:03:41 +00:00
return make_vm ();
2000-08-22 15:54:19 +00:00
}
#undef FUNC_NAME
2001-04-01 05:03:41 +00:00
SCM_DEFINE (scm_vm_ip, "vm:ip", 1, 0, 0,
2000-08-22 15:54:19 +00:00
(SCM vm),
2001-04-01 05:03:41 +00:00
"")
#define FUNC_NAME s_scm_vm_ip
2000-08-22 15:54:19 +00:00
{
SCM_VALIDATE_VM (1, vm);
return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->ip);
2000-08-22 15:54:19 +00:00
}
#undef FUNC_NAME
SCM_DEFINE (scm_vm_sp, "vm:sp", 1, 0, 0,
(SCM vm),
2001-04-01 05:03:41 +00:00
"")
2000-08-22 15:54:19 +00:00
#define FUNC_NAME s_scm_vm_sp
{
SCM_VALIDATE_VM (1, vm);
return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->sp);
2000-08-22 15:54:19 +00:00
}
#undef FUNC_NAME
SCM_DEFINE (scm_vm_fp, "vm:fp", 1, 0, 0,
(SCM vm),
2001-04-01 05:03:41 +00:00
"")
2000-08-22 15:54:19 +00:00
#define FUNC_NAME s_scm_vm_fp
{
SCM_VALIDATE_VM (1, vm);
return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->fp);
2000-08-22 15:54:19 +00:00
}
#undef FUNC_NAME
2001-04-01 05:03:41 +00:00
#define VM_DEFINE_HOOK(n) \
{ \
2001-04-06 00:17:39 +00:00
struct scm_vm *vp; \
2001-04-01 05:03:41 +00:00
SCM_VALIDATE_VM (1, vm); \
2001-04-06 00:17:39 +00:00
vp = SCM_VM_DATA (vm); \
if (SCM_FALSEP (vp->hooks[n])) \
vp->hooks[n] = scm_make_hook (SCM_I_MAKINUM (1)); \
2001-04-06 00:17:39 +00:00
return vp->hooks[n]; \
2001-04-01 05:03:41 +00:00
}
SCM_DEFINE (scm_vm_boot_hook, "vm-boot-hook", 1, 0, 0,
2000-08-22 15:54:19 +00:00
(SCM vm),
2001-04-01 05:03:41 +00:00
"")
#define FUNC_NAME s_scm_vm_boot_hook
2000-08-22 15:54:19 +00:00
{
2001-04-01 05:03:41 +00:00
VM_DEFINE_HOOK (SCM_VM_BOOT_HOOK);
2000-08-22 15:54:19 +00:00
}
#undef FUNC_NAME
2001-04-01 05:03:41 +00:00
SCM_DEFINE (scm_vm_halt_hook, "vm-halt-hook", 1, 0, 0,
(SCM vm),
"")
#define FUNC_NAME s_scm_vm_halt_hook
2000-08-22 15:54:19 +00:00
{
2001-04-01 05:03:41 +00:00
VM_DEFINE_HOOK (SCM_VM_HALT_HOOK);
2000-08-22 15:54:19 +00:00
}
#undef FUNC_NAME
2001-04-01 05:03:41 +00:00
SCM_DEFINE (scm_vm_next_hook, "vm-next-hook", 1, 0, 0,
2000-08-22 15:54:19 +00:00
(SCM vm),
2001-04-01 05:03:41 +00:00
"")
#define FUNC_NAME s_scm_vm_next_hook
2000-08-22 15:54:19 +00:00
{
2001-04-01 05:03:41 +00:00
VM_DEFINE_HOOK (SCM_VM_NEXT_HOOK);
2000-08-22 15:54:19 +00:00
}
#undef FUNC_NAME
2001-05-02 15:05:05 +00:00
SCM_DEFINE (scm_vm_break_hook, "vm-break-hook", 1, 0, 0,
(SCM vm),
"")
#define FUNC_NAME s_scm_vm_break_hook
{
VM_DEFINE_HOOK (SCM_VM_BREAK_HOOK);
}
#undef FUNC_NAME
2001-04-01 05:03:41 +00:00
SCM_DEFINE (scm_vm_enter_hook, "vm-enter-hook", 1, 0, 0,
(SCM vm),
"")
#define FUNC_NAME s_scm_vm_enter_hook
2000-08-22 15:54:19 +00:00
{
2001-04-01 05:03:41 +00:00
VM_DEFINE_HOOK (SCM_VM_ENTER_HOOK);
2000-08-22 15:54:19 +00:00
}
#undef FUNC_NAME
2001-04-01 05:03:41 +00:00
SCM_DEFINE (scm_vm_apply_hook, "vm-apply-hook", 1, 0, 0,
(SCM vm),
"")
#define FUNC_NAME s_scm_vm_apply_hook
2000-08-22 15:54:19 +00:00
{
2001-04-01 05:03:41 +00:00
VM_DEFINE_HOOK (SCM_VM_APPLY_HOOK);
2000-08-22 15:54:19 +00:00
}
#undef FUNC_NAME
2001-04-01 05:03:41 +00:00
SCM_DEFINE (scm_vm_exit_hook, "vm-exit-hook", 1, 0, 0,
2000-08-22 15:54:19 +00:00
(SCM vm),
2001-04-01 05:03:41 +00:00
"")
#define FUNC_NAME s_scm_vm_exit_hook
2000-08-22 15:54:19 +00:00
{
2001-04-01 05:03:41 +00:00
VM_DEFINE_HOOK (SCM_VM_EXIT_HOOK);
2000-08-22 15:54:19 +00:00
}
#undef FUNC_NAME
2001-04-01 05:03:41 +00:00
SCM_DEFINE (scm_vm_return_hook, "vm-return-hook", 1, 0, 0,
2000-08-22 15:54:19 +00:00
(SCM vm),
2001-04-01 05:03:41 +00:00
"")
#define FUNC_NAME s_scm_vm_return_hook
2000-08-22 15:54:19 +00:00
{
2001-04-01 05:03:41 +00:00
VM_DEFINE_HOOK (SCM_VM_RETURN_HOOK);
2000-08-22 15:54:19 +00:00
}
#undef FUNC_NAME
2001-04-01 05:03:41 +00:00
SCM_DEFINE (scm_vm_option, "vm-option", 2, 0, 0,
(SCM vm, SCM key),
"")
#define FUNC_NAME s_scm_vm_option
2000-08-22 15:54:19 +00:00
{
SCM_VALIDATE_VM (1, vm);
2001-04-01 05:03:41 +00:00
return scm_assq_ref (SCM_VM_DATA (vm)->options, key);
2000-08-22 15:54:19 +00:00
}
#undef FUNC_NAME
2001-04-01 05:03:41 +00:00
SCM_DEFINE (scm_set_vm_option_x, "set-vm-option!", 3, 0, 0,
(SCM vm, SCM key, SCM val),
"")
#define FUNC_NAME s_scm_set_vm_option_x
2000-08-22 15:54:19 +00:00
{
SCM_VALIDATE_VM (1, vm);
2001-04-01 05:03:41 +00:00
SCM_VM_DATA (vm)->options
= scm_assq_set_x (SCM_VM_DATA (vm)->options, key, val);
return SCM_UNSPECIFIED;
2000-08-22 15:54:19 +00:00
}
#undef FUNC_NAME
2001-04-01 05:03:41 +00:00
SCM_DEFINE (scm_vm_stats, "vm-stats", 1, 0, 0,
2000-08-22 15:54:19 +00:00
(SCM vm),
2001-04-01 05:03:41 +00:00
"")
#define FUNC_NAME s_scm_vm_stats
2000-08-22 15:54:19 +00:00
{
2001-04-01 05:03:41 +00:00
SCM stats;
2000-08-22 15:54:19 +00:00
SCM_VALIDATE_VM (1, vm);
2001-04-01 05:03:41 +00:00
stats = scm_make_vector (SCM_I_MAKINUM (2), SCM_UNSPECIFIED);
scm_vector_set_x (stats, SCM_I_MAKINUM (0),
scm_from_ulong (SCM_VM_DATA (vm)->time));
scm_vector_set_x (stats, SCM_I_MAKINUM (1),
scm_from_ulong (SCM_VM_DATA (vm)->clock));
2001-04-01 05:03:41 +00:00
return stats;
2000-08-22 15:54:19 +00:00
}
#undef FUNC_NAME
2001-04-01 05:03:41 +00:00
#define VM_CHECK_RUNNING(vm) \
if (!SCM_VM_DATA (vm)->ip) \
SCM_MISC_ERROR ("Not running", SCM_LIST1 (vm))
2001-04-23 04:28:13 +00:00
SCM_DEFINE (scm_vm_this_frame, "vm-this-frame", 1, 0, 0,
2000-08-22 15:54:19 +00:00
(SCM vm),
2001-04-01 05:03:41 +00:00
"")
2001-04-23 04:28:13 +00:00
#define FUNC_NAME s_scm_vm_this_frame
2000-08-22 15:54:19 +00:00
{
SCM_VALIDATE_VM (1, vm);
2001-04-23 04:28:13 +00:00
return SCM_VM_DATA (vm)->this_frame;
2001-04-22 02:13:48 +00:00
}
#undef FUNC_NAME
SCM_DEFINE (scm_vm_last_frame, "vm-last-frame", 1, 0, 0,
(SCM vm),
"")
#define FUNC_NAME s_scm_vm_last_frame
{
SCM_VALIDATE_VM (1, vm);
return SCM_VM_DATA (vm)->last_frame;
2000-08-22 15:54:19 +00:00
}
#undef FUNC_NAME
SCM_DEFINE (scm_vm_last_ip, "vm:last-ip", 1, 0, 0,
(SCM vm),
"")
#define FUNC_NAME s_scm_vm_last_ip
{
SCM_VALIDATE_VM (1, vm);
return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->last_ip);
}
#undef FUNC_NAME
SCM_DEFINE (scm_vm_save_stack, "vm-save-stack", 1, 0, 0,
(SCM vm),
"")
#define FUNC_NAME s_scm_vm_save_stack
{
struct scm_vm *vp;
SCM *dest;
SCM_VALIDATE_VM (1, vm);
vp = SCM_VM_DATA (vm);
if (vp->fp)
{
#ifdef VM_ENABLE_STACK_NULLING
if (vp->sp >= vp->stack_base)
if (!vp->sp[0] || vp->sp[1])
abort ();
#endif
vp->last_frame = vm_heapify_frames_1 (vp, vp->fp, vp->sp, &dest);
vp->last_ip = vp->ip;
}
else
{
vp->last_frame = SCM_BOOL_F;
}
return vp->last_frame;
}
#undef FUNC_NAME
2001-04-01 05:03:41 +00:00
SCM_DEFINE (scm_vm_fetch_code, "vm-fetch-code", 1, 0, 0,
(SCM vm),
"")
#define FUNC_NAME s_scm_vm_fetch_code
{
int i;
SCM list;
scm_byte_t *ip;
struct scm_instruction *p;
2000-08-22 15:54:19 +00:00
2001-04-01 05:03:41 +00:00
SCM_VALIDATE_VM (1, vm);
VM_CHECK_RUNNING (vm);
2000-08-22 15:54:19 +00:00
2001-04-01 05:03:41 +00:00
ip = SCM_VM_DATA (vm)->ip;
p = SCM_INSTRUCTION (*ip);
2000-08-22 15:54:19 +00:00
2001-04-01 05:03:41 +00:00
list = SCM_LIST1 (scm_str2symbol (p->name));
for (i = 1; i <= p->len; i++)
list = scm_cons (SCM_I_MAKINUM (ip[i]), list);
2001-04-01 05:03:41 +00:00
return scm_reverse_x (list, SCM_EOL);
}
#undef FUNC_NAME
SCM_DEFINE (scm_vm_fetch_stack, "vm-fetch-stack", 1, 0, 0,
(SCM vm),
"")
#define FUNC_NAME s_scm_vm_fetch_stack
2000-08-22 15:54:19 +00:00
{
2001-04-07 09:39:38 +00:00
SCM *sp;
SCM ls = SCM_EOL;
struct scm_vm *vp;
2000-08-22 15:54:19 +00:00
SCM_VALIDATE_VM (1, vm);
2001-04-01 05:03:41 +00:00
VM_CHECK_RUNNING (vm);
2000-08-22 15:54:19 +00:00
2001-04-07 09:39:38 +00:00
vp = SCM_VM_DATA (vm);
2001-04-23 04:28:13 +00:00
for (sp = vp->stack_base; sp <= vp->sp; sp++)
2001-04-07 09:39:38 +00:00
ls = scm_cons (*sp, ls);
return ls;
2000-08-22 15:54:19 +00:00
}
#undef FUNC_NAME
/*
2001-04-01 05:03:41 +00:00
* Initialize
2000-08-22 15:54:19 +00:00
*/
big reorg of scheme modules -- e.g. programs.c -> (system vm program) This reorganization kills the ugly module-export-all hacks in bootstrap.scm and core.scm. In fact, it gets rid of core.scm entirely, breaking out its functionality into separate files. * module/system/vm/trace.scm: * module/system/vm/profile.scm: * module/system/vm/disasm.scm: * module/system/vm/debug.scm: * module/system/vm/conv.scm: * module/system/vm/assemble.scm: * module/system/repl/repl.scm: * module/system/repl/common.scm: * module/system/base/compile.scm: * module/system/repl/command.scm: Update for changes, and fix a bug in procedure-documentation. * module/system/vm/bootstrap.scm: Just call scm_bootstrap_vm, which handles setting load-compiled for us. * module/system/vm/core.scm: Removed, functionality folded into other modules. * module/system/vm/frame.scm: Export the C frame procedures here; also move scheme functions from core.scm here. * module/system/vm/instruction.scm: New file, exports procedures from instructions.c. * module/system/vm/objcode.scm: New file, exports procedures from objcodes.c. * module/system/vm/program.scm: New file, exports procedures from programs.c, and some scheme functions originally from core.scm. * module/system/vm/vm.scm: New file, from vm.c and core.scm. * src/Makefile.am (libguile_vm_la_SOURCES): Add bootstrap.h. * src/bootstrap.h: New file, prototypes scm_bootstrap_vm (), which the scm_init_* functions call. * src/frames.h: * src/frames.c (scm_init_frames): * src/frames.c (scm_bootstrap_frames): * src/vm.h: * src/instructions.h: * src/instructions.c (scm_init_instructions): * src/instructions.c (scm_bootstrap_instructions): * src/objcodes.h: * src/objcodes.c (scm_bootstrap_objcodes): * src/objcodes.c (scm_init_objcodes): * src/programs.h: * src/programs.c (scm_bootstrap_programs): * src/programs.c (scm_init_programs): * src/vm.c (scm_bootstrap_vm): * src/vm.c (scm_init_vm): Call scm_bootstrap_vm() before doing anything in an init function. Bootstrap_vm will call bootstrap_instructions(), etc to initialize types, then set load-compiled to point to load-compiled/vm. * src/vm.c (scm_load_compiled_with_vm): Code to load .go files, if they're present.
2008-08-07 13:11:27 +02:00
SCM scm_load_compiled_with_vm (SCM file)
{
SCM program = scm_objcode_to_program (scm_load_objcode (file));
return vm_run (scm_the_vm (), program, SCM_EOL);
big reorg of scheme modules -- e.g. programs.c -> (system vm program) This reorganization kills the ugly module-export-all hacks in bootstrap.scm and core.scm. In fact, it gets rid of core.scm entirely, breaking out its functionality into separate files. * module/system/vm/trace.scm: * module/system/vm/profile.scm: * module/system/vm/disasm.scm: * module/system/vm/debug.scm: * module/system/vm/conv.scm: * module/system/vm/assemble.scm: * module/system/repl/repl.scm: * module/system/repl/common.scm: * module/system/base/compile.scm: * module/system/repl/command.scm: Update for changes, and fix a bug in procedure-documentation. * module/system/vm/bootstrap.scm: Just call scm_bootstrap_vm, which handles setting load-compiled for us. * module/system/vm/core.scm: Removed, functionality folded into other modules. * module/system/vm/frame.scm: Export the C frame procedures here; also move scheme functions from core.scm here. * module/system/vm/instruction.scm: New file, exports procedures from instructions.c. * module/system/vm/objcode.scm: New file, exports procedures from objcodes.c. * module/system/vm/program.scm: New file, exports procedures from programs.c, and some scheme functions originally from core.scm. * module/system/vm/vm.scm: New file, from vm.c and core.scm. * src/Makefile.am (libguile_vm_la_SOURCES): Add bootstrap.h. * src/bootstrap.h: New file, prototypes scm_bootstrap_vm (), which the scm_init_* functions call. * src/frames.h: * src/frames.c (scm_init_frames): * src/frames.c (scm_bootstrap_frames): * src/vm.h: * src/instructions.h: * src/instructions.c (scm_init_instructions): * src/instructions.c (scm_bootstrap_instructions): * src/objcodes.h: * src/objcodes.c (scm_bootstrap_objcodes): * src/objcodes.c (scm_init_objcodes): * src/programs.h: * src/programs.c (scm_bootstrap_programs): * src/programs.c (scm_init_programs): * src/vm.c (scm_bootstrap_vm): * src/vm.c (scm_init_vm): Call scm_bootstrap_vm() before doing anything in an init function. Bootstrap_vm will call bootstrap_instructions(), etc to initialize types, then set load-compiled to point to load-compiled/vm. * src/vm.c (scm_load_compiled_with_vm): Code to load .go files, if they're present.
2008-08-07 13:11:27 +02:00
}
2001-04-01 05:03:41 +00:00
void
big reorg of scheme modules -- e.g. programs.c -> (system vm program) This reorganization kills the ugly module-export-all hacks in bootstrap.scm and core.scm. In fact, it gets rid of core.scm entirely, breaking out its functionality into separate files. * module/system/vm/trace.scm: * module/system/vm/profile.scm: * module/system/vm/disasm.scm: * module/system/vm/debug.scm: * module/system/vm/conv.scm: * module/system/vm/assemble.scm: * module/system/repl/repl.scm: * module/system/repl/common.scm: * module/system/base/compile.scm: * module/system/repl/command.scm: Update for changes, and fix a bug in procedure-documentation. * module/system/vm/bootstrap.scm: Just call scm_bootstrap_vm, which handles setting load-compiled for us. * module/system/vm/core.scm: Removed, functionality folded into other modules. * module/system/vm/frame.scm: Export the C frame procedures here; also move scheme functions from core.scm here. * module/system/vm/instruction.scm: New file, exports procedures from instructions.c. * module/system/vm/objcode.scm: New file, exports procedures from objcodes.c. * module/system/vm/program.scm: New file, exports procedures from programs.c, and some scheme functions originally from core.scm. * module/system/vm/vm.scm: New file, from vm.c and core.scm. * src/Makefile.am (libguile_vm_la_SOURCES): Add bootstrap.h. * src/bootstrap.h: New file, prototypes scm_bootstrap_vm (), which the scm_init_* functions call. * src/frames.h: * src/frames.c (scm_init_frames): * src/frames.c (scm_bootstrap_frames): * src/vm.h: * src/instructions.h: * src/instructions.c (scm_init_instructions): * src/instructions.c (scm_bootstrap_instructions): * src/objcodes.h: * src/objcodes.c (scm_bootstrap_objcodes): * src/objcodes.c (scm_init_objcodes): * src/programs.h: * src/programs.c (scm_bootstrap_programs): * src/programs.c (scm_init_programs): * src/vm.c (scm_bootstrap_vm): * src/vm.c (scm_init_vm): Call scm_bootstrap_vm() before doing anything in an init function. Bootstrap_vm will call bootstrap_instructions(), etc to initialize types, then set load-compiled to point to load-compiled/vm. * src/vm.c (scm_load_compiled_with_vm): Code to load .go files, if they're present.
2008-08-07 13:11:27 +02:00
scm_bootstrap_vm (void)
2001-04-01 05:03:41 +00:00
{
big reorg of scheme modules -- e.g. programs.c -> (system vm program) This reorganization kills the ugly module-export-all hacks in bootstrap.scm and core.scm. In fact, it gets rid of core.scm entirely, breaking out its functionality into separate files. * module/system/vm/trace.scm: * module/system/vm/profile.scm: * module/system/vm/disasm.scm: * module/system/vm/debug.scm: * module/system/vm/conv.scm: * module/system/vm/assemble.scm: * module/system/repl/repl.scm: * module/system/repl/common.scm: * module/system/base/compile.scm: * module/system/repl/command.scm: Update for changes, and fix a bug in procedure-documentation. * module/system/vm/bootstrap.scm: Just call scm_bootstrap_vm, which handles setting load-compiled for us. * module/system/vm/core.scm: Removed, functionality folded into other modules. * module/system/vm/frame.scm: Export the C frame procedures here; also move scheme functions from core.scm here. * module/system/vm/instruction.scm: New file, exports procedures from instructions.c. * module/system/vm/objcode.scm: New file, exports procedures from objcodes.c. * module/system/vm/program.scm: New file, exports procedures from programs.c, and some scheme functions originally from core.scm. * module/system/vm/vm.scm: New file, from vm.c and core.scm. * src/Makefile.am (libguile_vm_la_SOURCES): Add bootstrap.h. * src/bootstrap.h: New file, prototypes scm_bootstrap_vm (), which the scm_init_* functions call. * src/frames.h: * src/frames.c (scm_init_frames): * src/frames.c (scm_bootstrap_frames): * src/vm.h: * src/instructions.h: * src/instructions.c (scm_init_instructions): * src/instructions.c (scm_bootstrap_instructions): * src/objcodes.h: * src/objcodes.c (scm_bootstrap_objcodes): * src/objcodes.c (scm_init_objcodes): * src/programs.h: * src/programs.c (scm_bootstrap_programs): * src/programs.c (scm_init_programs): * src/vm.c (scm_bootstrap_vm): * src/vm.c (scm_init_vm): Call scm_bootstrap_vm() before doing anything in an init function. Bootstrap_vm will call bootstrap_instructions(), etc to initialize types, then set load-compiled to point to load-compiled/vm. * src/vm.c (scm_load_compiled_with_vm): Code to load .go files, if they're present.
2008-08-07 13:11:27 +02:00
static int strappage = 0;
if (strappage)
return;
scm_bootstrap_frames ();
scm_bootstrap_instructions ();
scm_bootstrap_objcodes ();
scm_bootstrap_programs ();
2000-08-22 15:54:19 +00:00
2001-04-01 05:03:41 +00:00
scm_tc16_vm_cont = scm_make_smob_type ("vm-cont", 0);
scm_set_smob_mark (scm_tc16_vm_cont, vm_cont_mark);
scm_set_smob_free (scm_tc16_vm_cont, vm_cont_free);
2000-08-22 15:54:19 +00:00
2001-04-01 05:03:41 +00:00
scm_tc16_vm = scm_make_smob_type ("vm", 0);
scm_set_smob_mark (scm_tc16_vm, vm_mark);
scm_set_smob_free (scm_tc16_vm, vm_free);
scm_set_smob_apply (scm_tc16_vm, scm_vm_apply, 1, 0, 1);
2000-08-22 15:54:19 +00:00
merge guile-vm into libguile itself * ice-9/boot-9.scm: Only define load-compiled as #f if it's not already defined, which won't normally be the case. * libguile/guile-vm.c: Removed, there's no more guile-vm binary. * libguile/frames.c: (with change frame? -> heap-frame?) * libguile/frames.h: * libguile/instructions.c: * libguile/instructions.h: * libguile/objcodes.c: * libguile/objcodes.h: * libguile/programs.c: * libguile/programs.h: * libguile/vm-bootstrap.h: (was bootstrap.h) * libguile/vm-engine.c: (was vm_engine.c) * libguile/vm-engine.h: (was vm_engine.h) * libguile/vm-expand.h: (was vm_expand.h) * libguile/vm-i-loader.c: (was vm_loader.c) * libguile/vm-i-scheme.c: (was vm_scheme.c) * libguile/vm-i-system.c: (was vm_system.c) * libguile/vm.c: * libguile/vm.h: These files moved here from src/, as guile-vm is now a part of libguile. * libguile/init.c: Bootstrap the VM. Yay! * libguile/Makefile.am: The necessary chicanery here. * module/system/vm/Makefile.am: * module/system/vm/bootstrap.scm: * module/system/vm/frame.scm: * module/system/vm/instruction.scm: * module/system/vm/objcode.scm: * module/system/vm/program.scm: * module/system/vm/vm.scm: * pre-inst-guile-env.in: Add builddirs to the load path; add module/ to the path in the empty-$GUILE_LOAD_PATH case as well. * src/Makefile.am: Moved out everything except guilec and guile-disasm, which probably should be moved to the scripts directory? * testsuite/Makefile.am: Update to find guile-vm in the right place. * module/system/vm/Makefile.am: * module/system/vm/bootstrap.scm: Removed bootstrap.scm, scm_init_guile handles the bootstrapping for us. * module/system/vm/frame.scm: * module/system/vm/instruction.scm: * module/system/vm/objcode.scm: * module/system/vm/program.scm: * module/system/vm/vm.scm: Call the init functions in libguile; should fix at some point to avoid the dlopen?
2008-08-21 18:39:30 -07:00
scm_c_define ("load-compiled",
scm_c_make_gsubr ("load-compiled/vm", 1, 0, 0,
scm_load_compiled_with_vm));
big reorg of scheme modules -- e.g. programs.c -> (system vm program) This reorganization kills the ugly module-export-all hacks in bootstrap.scm and core.scm. In fact, it gets rid of core.scm entirely, breaking out its functionality into separate files. * module/system/vm/trace.scm: * module/system/vm/profile.scm: * module/system/vm/disasm.scm: * module/system/vm/debug.scm: * module/system/vm/conv.scm: * module/system/vm/assemble.scm: * module/system/repl/repl.scm: * module/system/repl/common.scm: * module/system/base/compile.scm: * module/system/repl/command.scm: Update for changes, and fix a bug in procedure-documentation. * module/system/vm/bootstrap.scm: Just call scm_bootstrap_vm, which handles setting load-compiled for us. * module/system/vm/core.scm: Removed, functionality folded into other modules. * module/system/vm/frame.scm: Export the C frame procedures here; also move scheme functions from core.scm here. * module/system/vm/instruction.scm: New file, exports procedures from instructions.c. * module/system/vm/objcode.scm: New file, exports procedures from objcodes.c. * module/system/vm/program.scm: New file, exports procedures from programs.c, and some scheme functions originally from core.scm. * module/system/vm/vm.scm: New file, from vm.c and core.scm. * src/Makefile.am (libguile_vm_la_SOURCES): Add bootstrap.h. * src/bootstrap.h: New file, prototypes scm_bootstrap_vm (), which the scm_init_* functions call. * src/frames.h: * src/frames.c (scm_init_frames): * src/frames.c (scm_bootstrap_frames): * src/vm.h: * src/instructions.h: * src/instructions.c (scm_init_instructions): * src/instructions.c (scm_bootstrap_instructions): * src/objcodes.h: * src/objcodes.c (scm_bootstrap_objcodes): * src/objcodes.c (scm_init_objcodes): * src/programs.h: * src/programs.c (scm_bootstrap_programs): * src/programs.c (scm_init_programs): * src/vm.c (scm_bootstrap_vm): * src/vm.c (scm_init_vm): Call scm_bootstrap_vm() before doing anything in an init function. Bootstrap_vm will call bootstrap_instructions(), etc to initialize types, then set load-compiled to point to load-compiled/vm. * src/vm.c (scm_load_compiled_with_vm): Code to load .go files, if they're present.
2008-08-07 13:11:27 +02:00
sym_vm_run = scm_permanent_object (scm_from_locale_symbol ("vm-run"));
sym_vm_error = scm_permanent_object (scm_from_locale_symbol ("vm-error"));
sym_debug = scm_permanent_object (scm_from_locale_symbol ("debug"));
big reorg of scheme modules -- e.g. programs.c -> (system vm program) This reorganization kills the ugly module-export-all hacks in bootstrap.scm and core.scm. In fact, it gets rid of core.scm entirely, breaking out its functionality into separate files. * module/system/vm/trace.scm: * module/system/vm/profile.scm: * module/system/vm/disasm.scm: * module/system/vm/debug.scm: * module/system/vm/conv.scm: * module/system/vm/assemble.scm: * module/system/repl/repl.scm: * module/system/repl/common.scm: * module/system/base/compile.scm: * module/system/repl/command.scm: Update for changes, and fix a bug in procedure-documentation. * module/system/vm/bootstrap.scm: Just call scm_bootstrap_vm, which handles setting load-compiled for us. * module/system/vm/core.scm: Removed, functionality folded into other modules. * module/system/vm/frame.scm: Export the C frame procedures here; also move scheme functions from core.scm here. * module/system/vm/instruction.scm: New file, exports procedures from instructions.c. * module/system/vm/objcode.scm: New file, exports procedures from objcodes.c. * module/system/vm/program.scm: New file, exports procedures from programs.c, and some scheme functions originally from core.scm. * module/system/vm/vm.scm: New file, from vm.c and core.scm. * src/Makefile.am (libguile_vm_la_SOURCES): Add bootstrap.h. * src/bootstrap.h: New file, prototypes scm_bootstrap_vm (), which the scm_init_* functions call. * src/frames.h: * src/frames.c (scm_init_frames): * src/frames.c (scm_bootstrap_frames): * src/vm.h: * src/instructions.h: * src/instructions.c (scm_init_instructions): * src/instructions.c (scm_bootstrap_instructions): * src/objcodes.h: * src/objcodes.c (scm_bootstrap_objcodes): * src/objcodes.c (scm_init_objcodes): * src/programs.h: * src/programs.c (scm_bootstrap_programs): * src/programs.c (scm_init_programs): * src/vm.c (scm_bootstrap_vm): * src/vm.c (scm_init_vm): Call scm_bootstrap_vm() before doing anything in an init function. Bootstrap_vm will call bootstrap_instructions(), etc to initialize types, then set load-compiled to point to load-compiled/vm. * src/vm.c (scm_load_compiled_with_vm): Code to load .go files, if they're present.
2008-08-07 13:11:27 +02:00
strappage = 1;
}
void
scm_init_vm (void)
{
scm_bootstrap_vm ();
2001-04-01 05:03:41 +00:00
#ifndef SCM_MAGIC_SNARFER
2000-08-22 15:54:19 +00:00
#include "vm.x"
2001-04-01 05:03:41 +00:00
#endif
2000-08-22 15:54:19 +00:00
}
2001-04-01 05:03:41 +00:00
/*
Local Variables:
c-file-style: "gnu"
End:
*/