mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-14 15:40:19 +02:00
Remove stack programs, objcode, and the old VM.
* libguile/Makefile.am: * libguile/vm-i-loader.c: * libguile/vm-i-scheme.c: * libguile/vm-i-system.c: Remove the old VM files, and the rules to build the .i files. * libguile/vm-engine.c: * libguile/vm.c: Remove the old VM. Woot! * libguile/_scm.h (SCM_OBJCODE_COOKIE, SCM_OBJCODE_ENDIANNESS_OFFSET) (SCM_OBJCODE_WORD_SIZE_OFFSET): Remove. * libguile/evalext.c (scm_self_evaluating_p): Remove objcode and program cases. * libguile/frames.c (scm_frame_num_locals, scm_frame_previous): Remove program cases. * libguile/gc.c (scm_i_tag_name): Remove objcode case. * libguile/goops.c (scm_class_of, create_standard_classes): Remove objcode and program cases. * libguile/instructions.h: * libguile/instructions.c (scm_instruction_list, scm_instruction_p) (scm_instruction_length, scm_instruction_pops, scm_instruction_pushes) (scm_instruction_to_opcode, scm_opcode_to_instruction): Remove old VM code. * libguile/objcodes.h: * libguile/objcodes.c: Remove the objcode data type, and handling for objcode files. * libguile/print.c: Remove objcode and program printers. * libguile/procprop.c: Remove program cases. * libguile/procs.c: * libguile/programs.h: * libguile/programs.c: Remove old program code. * libguile/smob.c: Remove objcodes include. * libguile/snarf.h: Remove static program defines. * libguile/stacks.c: Remove program case. * libguile/tags.h: Remove program and objcode tc7s. * module/ice-9/session.scm (procedure-arguments) * module/language/tree-il/analyze.scm (validate-arity) * module/statprof.scm (get-call-data, procedure=?) * module/system/vm/frame.scm (frame-bindings) (frame-call-representation): Remove old program cases. * module/system/repl/debug.scm (frame->module): Add a FIXME. * module/system/vm/instruction.scm: Remove old exports. * module/system/vm/program.scm: Remove old program code.
This commit is contained in:
parent
84680d2382
commit
1c33be992e
31 changed files with 51 additions and 4308 deletions
|
@ -19,32 +19,6 @@
|
|||
/* This file is included in vm.c multiple times. */
|
||||
|
||||
|
||||
/* Virtual Machine
|
||||
|
||||
This file contains two virtual machines. First, the old one -- the
|
||||
one that is currently used, and corresponds to Guile 2.0. It's a
|
||||
stack machine, meaning that most instructions pop their operands from
|
||||
the top of the stack, and push results there too.
|
||||
|
||||
Following it is the new virtual machine. It's a register machine,
|
||||
meaning that intructions address their operands by index, and store
|
||||
results in indexed slots as well. Those slots are on the stack.
|
||||
It's somewhat confusing to call it a register machine, given that the
|
||||
values are on the stack. Perhaps it needs a new name.
|
||||
|
||||
Anyway, things are in a transitional state. We're going to try to
|
||||
avoid munging the old VM very much while we flesh out the new one.
|
||||
We're also going to try to make them interoperable, as much as
|
||||
possible -- to have the old VM be able to call procedures for the new
|
||||
VM, and vice versa. This should ease the bootstrapping process. */
|
||||
|
||||
|
||||
/* The old VM. */
|
||||
static SCM VM_NAME (SCM, SCM, SCM*, int);
|
||||
/* The new VM. */
|
||||
static SCM RTL_VM_NAME (SCM, SCM, SCM*, size_t);
|
||||
|
||||
|
||||
#if (VM_ENGINE == SCM_VM_REGULAR_ENGINE)
|
||||
# define VM_USE_HOOKS 0 /* Various hooks */
|
||||
#elif (VM_ENGINE == SCM_VM_DEBUG_ENGINE)
|
||||
|
@ -70,9 +44,6 @@ static SCM RTL_VM_NAME (SCM, SCM, SCM*, size_t);
|
|||
#ifndef IP_REG
|
||||
# define IP_REG
|
||||
#endif
|
||||
#ifndef SP_REG
|
||||
# define SP_REG
|
||||
#endif
|
||||
#ifndef FP_REG
|
||||
# define FP_REG
|
||||
#endif
|
||||
|
@ -126,393 +97,6 @@ static SCM RTL_VM_NAME (SCM, SCM, SCM*, size_t);
|
|||
SCM_ASYNC_TICK_WITH_CODE (current_thread, SYNC_REGISTER ())
|
||||
|
||||
|
||||
|
||||
|
||||
/* Cache the VM's instruction, stack, and frame pointer in local variables. */
|
||||
#define CACHE_REGISTER() \
|
||||
{ \
|
||||
ip = vp->ip; \
|
||||
sp = vp->sp; \
|
||||
fp = vp->fp; \
|
||||
}
|
||||
|
||||
/* Update the registers in VP, a pointer to the current VM. This must be done
|
||||
at least before any GC invocation so that `vp->sp' is up-to-date and the
|
||||
whole stack gets marked. */
|
||||
#define SYNC_REGISTER() \
|
||||
{ \
|
||||
vp->ip = ip; \
|
||||
vp->sp = sp; \
|
||||
vp->fp = fp; \
|
||||
}
|
||||
|
||||
/* FIXME */
|
||||
#define ASSERT_VARIABLE(x) \
|
||||
VM_ASSERT (SCM_VARIABLEP (x), abort())
|
||||
#define ASSERT_BOUND_VARIABLE(x) \
|
||||
VM_ASSERT (SCM_VARIABLEP (x) \
|
||||
&& !scm_is_eq (SCM_VARIABLE_REF (x), SCM_UNDEFINED), \
|
||||
abort())
|
||||
|
||||
#ifdef VM_ENABLE_PARANOID_ASSERTIONS
|
||||
#define CHECK_IP() \
|
||||
do { if (ip < bp->base || ip - bp->base > bp->len) abort (); } while (0)
|
||||
#define ASSERT_ALIGNED_PROCEDURE() \
|
||||
do { if ((scm_t_bits)bp % 8) abort (); } while (0)
|
||||
#define ASSERT_BOUND(x) \
|
||||
VM_ASSERT (!scm_is_eq ((x), SCM_UNDEFINED), abort())
|
||||
#else
|
||||
#define CHECK_IP()
|
||||
#define ASSERT_ALIGNED_PROCEDURE()
|
||||
#define ASSERT_BOUND(x)
|
||||
#endif
|
||||
|
||||
/* Cache the object table and free variables. */
|
||||
#define CACHE_PROGRAM() \
|
||||
{ \
|
||||
if (bp != SCM_PROGRAM_DATA (program)) { \
|
||||
bp = SCM_PROGRAM_DATA (program); \
|
||||
ASSERT_ALIGNED_PROCEDURE (); \
|
||||
if (SCM_I_IS_VECTOR (SCM_PROGRAM_OBJTABLE (program))) { \
|
||||
objects = SCM_I_VECTOR_WELTS (SCM_PROGRAM_OBJTABLE (program)); \
|
||||
} else { \
|
||||
objects = NULL; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define SYNC_BEFORE_GC() \
|
||||
{ \
|
||||
SYNC_REGISTER (); \
|
||||
}
|
||||
|
||||
#define SYNC_ALL() \
|
||||
{ \
|
||||
SYNC_REGISTER (); \
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Error check
|
||||
*/
|
||||
|
||||
/* Accesses to a program's object table. */
|
||||
#define CHECK_OBJECT(_num)
|
||||
#define CHECK_FREE_VARIABLE(_num)
|
||||
|
||||
|
||||
/*
|
||||
* Stack operation
|
||||
*/
|
||||
|
||||
#ifdef VM_ENABLE_STACK_NULLING
|
||||
# define CHECK_STACK_LEAKN(_n) ASSERT (!sp[_n]);
|
||||
# define CHECK_STACK_LEAK() CHECK_STACK_LEAKN(1)
|
||||
# define NULLSTACK(_n) { int __x = _n; CHECK_STACK_LEAKN (_n+1); while (__x > 0) sp[__x--] = NULL; }
|
||||
/* If you have a nonlocal exit in a pre-wind proc while invoking a continuation
|
||||
inside a dynwind (phew!), the stack is fully rewound but vm_reset_stack for
|
||||
that continuation doesn't have a chance to run. It's not important on a
|
||||
semantic level, but it does mess up our stack nulling -- so this macro is to
|
||||
fix that. */
|
||||
# define NULLSTACK_FOR_NONLOCAL_EXIT() if (vp->sp > sp) NULLSTACK (vp->sp - sp);
|
||||
#else
|
||||
# define CHECK_STACK_LEAKN(_n)
|
||||
# define CHECK_STACK_LEAK()
|
||||
# define NULLSTACK(_n)
|
||||
# define NULLSTACK_FOR_NONLOCAL_EXIT()
|
||||
#endif
|
||||
|
||||
/* For this check, we don't use VM_ASSERT, because that leads to a
|
||||
per-site SYNC_ALL, which is too much code growth. The real problem
|
||||
of course is having to check for overflow all the time... */
|
||||
#define CHECK_OVERFLOW() \
|
||||
do { if (SCM_UNLIKELY (sp >= stack_limit)) goto handle_overflow; } while (0)
|
||||
|
||||
#ifdef VM_CHECK_UNDERFLOW
|
||||
#define PRE_CHECK_UNDERFLOW(N) \
|
||||
VM_ASSERT (sp - (N) > SCM_FRAME_UPPER_ADDRESS (fp), vm_error_stack_underflow ())
|
||||
#define CHECK_UNDERFLOW() PRE_CHECK_UNDERFLOW (0)
|
||||
#else
|
||||
#define PRE_CHECK_UNDERFLOW(N) /* nop */
|
||||
#define CHECK_UNDERFLOW() /* nop */
|
||||
#endif
|
||||
|
||||
|
||||
#define PUSH(x) do { sp++; CHECK_OVERFLOW (); *sp = x; } while (0)
|
||||
#define DROP() do { sp--; CHECK_UNDERFLOW (); NULLSTACK (1); } while (0)
|
||||
#define DROPN(_n) do { sp -= (_n); CHECK_UNDERFLOW (); NULLSTACK (_n); } while (0)
|
||||
#define POP(x) do { PRE_CHECK_UNDERFLOW (1); x = *sp--; NULLSTACK (1); } while (0)
|
||||
#define POP2(x,y) do { PRE_CHECK_UNDERFLOW (2); x = *sp--; y = *sp--; NULLSTACK (2); } while (0)
|
||||
#define POP3(x,y,z) do { PRE_CHECK_UNDERFLOW (3); x = *sp--; y = *sp--; z = *sp--; NULLSTACK (3); } while (0)
|
||||
|
||||
/* Pop the N objects on top of the stack and push a list that contains
|
||||
them. */
|
||||
#define POP_LIST(n) \
|
||||
do \
|
||||
{ \
|
||||
int i; \
|
||||
SCM l = SCM_EOL, x; \
|
||||
SYNC_BEFORE_GC (); \
|
||||
for (i = n; i; i--) \
|
||||
{ \
|
||||
POP (x); \
|
||||
l = scm_cons (x, l); \
|
||||
} \
|
||||
PUSH (l); \
|
||||
} while (0)
|
||||
|
||||
/* The opposite: push all of the elements in L onto the list. */
|
||||
#define PUSH_LIST(l, NILP) \
|
||||
do \
|
||||
{ \
|
||||
for (; scm_is_pair (l); l = SCM_CDR (l)) \
|
||||
PUSH (SCM_CAR (l)); \
|
||||
VM_ASSERT (NILP (l), vm_error_improper_list (l)); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/*
|
||||
* Instruction operation
|
||||
*/
|
||||
|
||||
#define FETCH() (*ip++)
|
||||
#define FETCH_LENGTH(len) do { len=*ip++; len<<=8; len+=*ip++; len<<=8; len+=*ip++; } while (0)
|
||||
|
||||
#undef NEXT_JUMP
|
||||
#ifdef HAVE_LABELS_AS_VALUES
|
||||
# define NEXT_JUMP() goto *jump_table[FETCH () & SCM_VM_INSTRUCTION_MASK]
|
||||
#else
|
||||
# define NEXT_JUMP() goto vm_start
|
||||
#endif
|
||||
|
||||
#define NEXT \
|
||||
{ \
|
||||
NEXT_HOOK (); \
|
||||
CHECK_STACK_LEAK (); \
|
||||
NEXT_JUMP (); \
|
||||
}
|
||||
|
||||
|
||||
/* See frames.h for the layout of stack frames */
|
||||
/* When this is called, bp points to the new program data,
|
||||
and the arguments are already on the stack */
|
||||
#define DROP_FRAME() \
|
||||
{ \
|
||||
sp -= 3; \
|
||||
NULLSTACK (3); \
|
||||
CHECK_UNDERFLOW (); \
|
||||
}
|
||||
|
||||
|
||||
static SCM
|
||||
VM_NAME (SCM vm, SCM program, SCM *argv, int nargs)
|
||||
{
|
||||
/* VM registers */
|
||||
register scm_t_uint8 *ip IP_REG; /* instruction pointer */
|
||||
register SCM *sp SP_REG; /* stack pointer */
|
||||
register SCM *fp FP_REG; /* frame pointer */
|
||||
struct scm_vm *vp = SCM_VM_DATA (vm);
|
||||
|
||||
/* Cache variables */
|
||||
struct scm_objcode *bp = NULL; /* program base pointer */
|
||||
SCM *objects = NULL; /* constant objects */
|
||||
SCM *stack_limit = vp->stack_limit; /* stack limit address */
|
||||
|
||||
scm_i_thread *current_thread = SCM_I_CURRENT_THREAD;
|
||||
|
||||
/* Internal variables */
|
||||
int nvalues = 0;
|
||||
scm_i_jmp_buf registers; /* used for prompts */
|
||||
|
||||
#ifdef HAVE_LABELS_AS_VALUES
|
||||
static const void **jump_table_pointer = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LABELS_AS_VALUES
|
||||
register const void **jump_table JT_REG;
|
||||
|
||||
if (SCM_UNLIKELY (!jump_table_pointer))
|
||||
{
|
||||
int i;
|
||||
jump_table_pointer = malloc (SCM_VM_NUM_INSTRUCTIONS * sizeof (void*));
|
||||
for (i = 0; i < SCM_VM_NUM_INSTRUCTIONS; i++)
|
||||
jump_table_pointer[i] = &&vm_error_bad_instruction;
|
||||
#define VM_INSTRUCTION_TO_LABEL 1
|
||||
#define jump_table jump_table_pointer
|
||||
#include <libguile/vm-expand.h>
|
||||
#include <libguile/vm-i-system.i>
|
||||
#include <libguile/vm-i-scheme.i>
|
||||
#include <libguile/vm-i-loader.i>
|
||||
#undef jump_table
|
||||
#undef VM_INSTRUCTION_TO_LABEL
|
||||
}
|
||||
|
||||
/* Attempt to keep JUMP_TABLE_POINTER in a register. This saves one
|
||||
load instruction at each instruction dispatch. */
|
||||
jump_table = jump_table_pointer;
|
||||
#endif
|
||||
|
||||
if (SCM_I_SETJMP (registers))
|
||||
{
|
||||
/* Non-local return. Cache the VM registers back from the vp, and
|
||||
go to the handler.
|
||||
|
||||
Note, at this point, we must assume that any variable local to
|
||||
vm_engine that can be assigned *has* been assigned. So we need to pull
|
||||
all our state back from the ip/fp/sp.
|
||||
*/
|
||||
CACHE_REGISTER ();
|
||||
program = SCM_FRAME_PROGRAM (fp);
|
||||
CACHE_PROGRAM ();
|
||||
/* The stack contains the values returned to this continuation,
|
||||
along with a number-of-values marker -- like an MV return. */
|
||||
ABORT_CONTINUATION_HOOK (sp - SCM_I_INUM (*sp), SCM_I_INUM (*sp));
|
||||
NEXT;
|
||||
}
|
||||
|
||||
CACHE_REGISTER ();
|
||||
|
||||
/* Since it's possible to receive the arguments on the stack itself,
|
||||
and indeed the RTL VM invokes us that way, shuffle up the
|
||||
arguments first. */
|
||||
VM_ASSERT (sp + 8 + nargs < stack_limit, vm_error_too_many_args (nargs));
|
||||
{
|
||||
int i;
|
||||
for (i = nargs - 1; i >= 0; i--)
|
||||
sp[9 + i] = argv[i];
|
||||
}
|
||||
|
||||
/* Initial frame */
|
||||
PUSH (SCM_PACK (fp)); /* dynamic link */
|
||||
PUSH (SCM_PACK (0)); /* mvra */
|
||||
PUSH (SCM_PACK (ip)); /* ra */
|
||||
PUSH (boot_continuation);
|
||||
fp = sp + 1;
|
||||
ip = SCM_C_OBJCODE_BASE (SCM_PROGRAM_DATA (boot_continuation));
|
||||
|
||||
/* MV-call frame, function & arguments */
|
||||
PUSH (SCM_PACK (fp)); /* dynamic link */
|
||||
PUSH (SCM_PACK (ip + 1)); /* mvra */
|
||||
PUSH (SCM_PACK (ip)); /* ra */
|
||||
PUSH (program);
|
||||
fp = sp + 1;
|
||||
sp += nargs;
|
||||
|
||||
PUSH_CONTINUATION_HOOK ();
|
||||
|
||||
apply:
|
||||
program = fp[-1];
|
||||
if (!SCM_PROGRAM_P (program))
|
||||
{
|
||||
if (SCM_STRUCTP (program) && SCM_STRUCT_APPLICABLE_P (program))
|
||||
fp[-1] = SCM_STRUCT_PROCEDURE (program);
|
||||
else if (SCM_HAS_TYP7 (program, scm_tc7_rtl_program))
|
||||
{
|
||||
SCM ret;
|
||||
SYNC_ALL ();
|
||||
|
||||
ret = RTL_VM_NAME (vm, program, fp, sp - fp + 1);
|
||||
|
||||
NULLSTACK_FOR_NONLOCAL_EXIT ();
|
||||
|
||||
if (SCM_UNLIKELY (SCM_VALUESP (ret)))
|
||||
{
|
||||
/* multiple values returned to continuation */
|
||||
ret = scm_struct_ref (ret, SCM_INUM0);
|
||||
nvalues = scm_ilength (ret);
|
||||
PUSH_LIST (ret, scm_is_null);
|
||||
goto vm_return_values;
|
||||
}
|
||||
else
|
||||
{
|
||||
PUSH (ret);
|
||||
goto vm_return;
|
||||
}
|
||||
}
|
||||
else if (SCM_HAS_TYP7 (program, scm_tc7_smob)
|
||||
&& SCM_SMOB_APPLICABLE_P (program))
|
||||
{
|
||||
/* (smob arg0 ... argN) => (apply-smob smob arg0 ... argN) */
|
||||
int i;
|
||||
PUSH (SCM_BOOL_F);
|
||||
for (i = sp - fp; i >= 0; i--)
|
||||
fp[i] = fp[i - 1];
|
||||
fp[-1] = SCM_SMOB_DESCRIPTOR (program).apply_trampoline;
|
||||
}
|
||||
else
|
||||
{
|
||||
SYNC_ALL();
|
||||
vm_error_wrong_type_apply (program);
|
||||
}
|
||||
goto apply;
|
||||
}
|
||||
|
||||
CACHE_PROGRAM ();
|
||||
ip = SCM_C_OBJCODE_BASE (bp);
|
||||
|
||||
APPLY_HOOK ();
|
||||
|
||||
/* Let's go! */
|
||||
NEXT;
|
||||
|
||||
#ifndef HAVE_LABELS_AS_VALUES
|
||||
vm_start:
|
||||
switch ((*ip++) & SCM_VM_INSTRUCTION_MASK) {
|
||||
#endif
|
||||
|
||||
#include "vm-expand.h"
|
||||
#include "vm-i-system.c"
|
||||
#include "vm-i-scheme.c"
|
||||
#include "vm-i-loader.c"
|
||||
|
||||
#ifndef HAVE_LABELS_AS_VALUES
|
||||
default:
|
||||
goto vm_error_bad_instruction;
|
||||
}
|
||||
#endif
|
||||
|
||||
abort (); /* never reached */
|
||||
|
||||
vm_error_bad_instruction:
|
||||
vm_error_bad_instruction (ip[-1]);
|
||||
abort (); /* never reached */
|
||||
|
||||
handle_overflow:
|
||||
SYNC_ALL ();
|
||||
vm_error_stack_overflow (vp);
|
||||
abort (); /* never reached */
|
||||
}
|
||||
|
||||
#undef ALIGNED_P
|
||||
#undef CACHE_REGISTER
|
||||
#undef CHECK_OVERFLOW
|
||||
#undef FUNC2
|
||||
#undef INIT
|
||||
#undef INUM_MAX
|
||||
#undef INUM_MIN
|
||||
#undef INUM_STEP
|
||||
#undef jump_table
|
||||
#undef LOCAL_REF
|
||||
#undef LOCAL_SET
|
||||
#undef NEXT
|
||||
#undef NEXT_JUMP
|
||||
#undef REL
|
||||
#undef RETURN
|
||||
#undef RETURN_ONE_VALUE
|
||||
#undef RETURN_VALUE_LIST
|
||||
#undef SYNC_ALL
|
||||
#undef SYNC_BEFORE_GC
|
||||
#undef SYNC_IP
|
||||
#undef SYNC_REGISTER
|
||||
#undef VARIABLE_BOUNDP
|
||||
#undef VARIABLE_REF
|
||||
#undef VARIABLE_SET
|
||||
#undef VM_DEFINE_OP
|
||||
#undef VM_INSTRUCTION_TO_LABEL
|
||||
|
||||
|
||||
|
||||
|
||||
/* Virtual Machine
|
||||
|
||||
This is Guile's new virtual machine. When I say "new", I mean
|
||||
|
@ -918,22 +502,8 @@ RTL_VM_NAME (SCM vm, SCM program, SCM *argv, size_t nargs_)
|
|||
continue;
|
||||
}
|
||||
|
||||
#if 0
|
||||
SYNC_IP();
|
||||
vm_error_wrong_type_apply (proc);
|
||||
#else
|
||||
{
|
||||
SCM ret;
|
||||
SYNC_ALL ();
|
||||
|
||||
ret = VM_NAME (vm, fp[-1], fp, FRAME_LOCALS_COUNT () - 1);
|
||||
|
||||
if (SCM_UNLIKELY (SCM_VALUESP (ret)))
|
||||
RETURN_VALUE_LIST (scm_struct_ref (ret, SCM_INUM0));
|
||||
else
|
||||
RETURN_ONE_VALUE (ret);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Let's go! */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue