guile/libguile/vm-engine.c

498 lines
15 KiB
C
Raw Normal View History

/* Copyright (C) 2001, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
2000-08-22 15:54:19 +00:00
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 3 of
* the License, or (at your option) any later version.
2000-08-22 15:54:19 +00:00
*
* This library 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
* Lesser General Public License for more details.
2000-08-22 15:54:19 +00:00
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
2000-08-22 15:54:19 +00:00
/* This file is included in vm.c multiple times */
#if (VM_ENGINE == SCM_VM_REGULAR_ENGINE)
# define VM_USE_HOOKS 0 /* Various hooks */
#elif (VM_ENGINE == SCM_VM_DEBUG_ENGINE)
# define VM_USE_HOOKS 1
#else
# error unknown debug engine VM_ENGINE
#endif
2000-08-22 15:54:19 +00:00
/* Register optimization. [ stolen from librep/src/lispmach.h,v 1.3 ]
Some compilers underestimate the use of the local variables representing
the abstract machine registers, and don't put them in hardware registers,
which slows down the interpreter considerably.
For GCC, I have hand-assigned hardware registers for several architectures.
*/
#ifdef __GNUC__
#ifdef __mips__
#define IP_REG asm("$16")
#define SP_REG asm("$17")
#define FP_REG asm("$18")
#endif
#ifdef __sparc__
#define IP_REG asm("%l0")
#define SP_REG asm("%l1")
#define FP_REG asm("%l2")
#endif
#ifdef __alpha__
#ifdef __CRAY__
#define IP_REG asm("r9")
#define SP_REG asm("r10")
#define FP_REG asm("r11")
#else
#define IP_REG asm("$9")
#define SP_REG asm("$10")
#define FP_REG asm("$11")
#endif
#endif
#ifdef __i386__
/* too few registers! because of register allocation errors with various gcs,
just punt on explicit assignments on i386, hoping that the "register"
declaration will be sufficient. */
#elif defined __x86_64__
/* GCC 4.6 chooses %rbp for IP_REG and %rbx for SP_REG, which works
well. Tell it to keep the jump table in a r12, which is
callee-saved. */
#define JT_REG asm ("r12")
#endif
#if defined(PPC) || defined(_POWER) || defined(_IBMR2)
#define IP_REG asm("26")
#define SP_REG asm("27")
#define FP_REG asm("28")
#endif
#ifdef __hppa__
#define IP_REG asm("%r18")
#define SP_REG asm("%r17")
#define FP_REG asm("%r16")
#endif
#ifdef __mc68000__
#define IP_REG asm("a5")
#define SP_REG asm("a4")
#define FP_REG
#endif
#ifdef __arm__
#define IP_REG asm("r9")
#define SP_REG asm("r8")
#define FP_REG asm("r7")
#endif
#endif
#ifndef IP_REG
#define IP_REG
#endif
#ifndef SP_REG
#define SP_REG
#endif
#ifndef FP_REG
#define FP_REG
#endif
#ifndef JT_REG
#define JT_REG
#endif
#define VM_ASSERT(condition, handler) \
do { \
if (SCM_UNLIKELY (!(condition))) \
{ \
SYNC_ALL(); \
handler; \
} \
} while (0)
#ifdef VM_ENABLE_ASSERTIONS
# define ASSERT(condition) VM_ASSERT (condition, abort())
#else
# define ASSERT(condition)
#endif
/* 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)
/*
* Hooks
*/
#if VM_USE_HOOKS
#define RUN_HOOK(h) \
{ \
if (SCM_UNLIKELY (vp->trace_level > 0)) \
{ \
SYNC_REGISTER (); \
vm_dispatch_hook (vm, h); \
} \
}
#define RUN_HOOK1(h, x) \
{ \
if (SCM_UNLIKELY (vp->trace_level > 0)) \
{ \
PUSH (x); \
SYNC_REGISTER (); \
vm_dispatch_hook (vm, h); \
DROP(); \
} \
}
#else
#define RUN_HOOK(h)
#define RUN_HOOK1(h, x)
#endif
#define APPLY_HOOK() \
RUN_HOOK (SCM_VM_APPLY_HOOK)
#define PUSH_CONTINUATION_HOOK() \
RUN_HOOK (SCM_VM_PUSH_CONTINUATION_HOOK)
#define POP_CONTINUATION_HOOK(n) \
RUN_HOOK1 (SCM_VM_POP_CONTINUATION_HOOK, SCM_I_MAKINUM (n))
#define NEXT_HOOK() \
RUN_HOOK (SCM_VM_NEXT_HOOK)
#define ABORT_CONTINUATION_HOOK() \
RUN_HOOK (SCM_VM_ABORT_CONTINUATION_HOOK)
#define RESTORE_CONTINUATION_HOOK() \
RUN_HOOK (SCM_VM_RESTORE_CONTINUATION_HOOK)
#define VM_HANDLE_INTERRUPTS \
SCM_ASYNC_TICK_WITH_CODE (current_thread, SYNC_REGISTER ())
/*
* 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 (); \
}
2000-08-22 15:54:19 +00:00
static SCM
VM_NAME (SCM vm, SCM program, SCM *argv, int nargs)
2000-08-22 15:54:19 +00:00
{
2001-04-01 05:03:41 +00:00
/* VM registers */
register scm_t_uint8 *ip IP_REG; /* instruction pointer */
2001-04-01 05:03:41 +00:00
register SCM *sp SP_REG; /* stack pointer */
register SCM *fp FP_REG; /* frame pointer */
struct scm_vm *vp = SCM_VM_DATA (vm);
2000-08-22 15:54:19 +00:00
2000-08-22 19:02:22 +00:00
/* Cache variables */
static opcodes; refactor program/objcode division; use new assembly pipeline * gdbinit: Untested attempts to get the stack fondling macros to deal with the new program representation. * libguile/frames.c (scm_vm_frame_arguments, scm_vm_frame_source) (scm_vm_frame_local_ref, scm_vm_frame_local_set_x): SCM_PROGRAM_DATA is a struct scm_objcode*. * libguile/instructions.h: * libguile/instructions.c: Hide the instruction table and the struct scm_instruction structure; all access to instructions now goes through procedures. This is because instructions are no longer in a packed array indexed by opcode. Also, declare a mask that all instructions should fit in. * libguile/objcodes.h: * libguile/objcodes.c: Rewrite so that object code directly maps its arity and length from its bytecode. This makes it unnecessary to keep this information in programs, allowing programs to be simple conses between the code (objcodes) and data (the object table and the closure variables). * libguile/programs.c (scm_make_program): Rework so that make-program takes objcode, an object table, and externals as arguments. It's much clearer this way, and we avoid malloc(). * libguile/stacks.c (is_vm_bootstrap_frame): Update for program/objcode changes. * libguile/vm-engine.c (vm_run): Initialize the jump table on the first run, with the opcodes declared in the instruction sources, and with bad instructions raising an error instead of wandering off into the Unknown. * libguile/vm-engine.h (FETCH_LENGTH): Always represent lengths as 3 bytes. The old code was too error-prone. (NEXT_JUMP): Mask the instruction with SCM_VM_INSTRUCTION_MASK. (NEW_FRAME): Update for program/objcode changes. * libguile/vm-expand.h (VM_DEFINE_FUNCTION, VM_DEFINE_INSTRUCTION) (VM_DEFINE_LOADER): Update so that we explicitly specify opcodes, so that we have a stable bytecode API. * libguile/vm-i-loader.c: Update license to LGPLv2+. Explicitly declare opcodes. (load-integer): Use an int instead of a long as the accumulator; still need to revisit this code at some point, I think. (load-program): Simplify, thankfully!! Just creates the objcode slice and rolls with it. * libguile/vm-i-scheme.c: Number the opcodes explicitly. * libguile/vm-i-system.c: Update license to LGPLv2+. Explicitly declare opcodes. (make-closure): Update for new program API. * libguile/vm.c (vm_make_boot_program): Update for new program/objcode API. Still a bit ugly. (scm_load_compiled_with_vm): Update for new program/objcode API. * module/language/assembly.scm (byte-length): Fix byte-length calculation for loaders, and load-program. (code-pack, code-unpack): Start to move things from (system vm conv) here. (object->code, code->object): More things from conv.scm. * module/language/glil.scm (<glil-program>): Add a new field, closure-level. (make-glil-program, compute-closure-level): Calculate the "closure level" when making a glil program. This is the maximum depth of external binding refs in this closure. (unparse-glil): Fix label serialization. * module/language/glil/compile-assembly.scm (make-meta): Prepend #f for the meta's object table, though maybe in the future we can avoid creating assembly in the first place. (assoc-ref-or-acons, object-index-and-alist): GRRR! Caught again by the different sets of arguments to assoc and assoc-ref! (glil->assembly): Attempt to make the <glil-program> case more readable, and fix the bugs. Sorry I don't know how to comment this change any more than this. (glil->assembly): For <glil-module> serialize the whole key, not just the name. (dump-object): subprogram-code is already a list. Serialize integers as strings, not u8vectors. Fix the order of lists and vectors. * module/language/glil/spec.scm (glil): Switch orders, so we prefer glil -> assembly -> objcode. Actually glil->objcode doesn't work any more, needs to be removed I think. * module/language/objcode/spec.scm (objcode->value): s/objcode->program/make-program/. * module/language/scheme/inline.scm: Add acons inline. * module/system/vm/conv.scm (make-byte-decoder): Skip the first 8 bytes, they are header. Handle subprograms properly. Still needs help though. (decode-length): Lengths are always 3 bytes now. * module/system/vm/disasm.scm: Superficial changes to keep things working. I'd like to fix this better in the future. * module/system/vm/frame.scm (bootstrap-frame?): Fixes for program-bytecode. * module/system/vm/program.scm: Export make-program. It's program-objcode now, no more program-bytecode. * module/system/vm/vm.scm (vm-load): Use make-program. * test-suite/tests/asm-to-bytecode.test: New test, very minimal. * module/system/vm/objcode.scm: Export word-size, byte-order, and write-objcode.
2009-01-29 21:09:04 +01:00
struct scm_objcode *bp = NULL; /* program base pointer */
2001-04-01 05:03:41 +00:00
SCM *objects = NULL; /* constant objects */
2001-04-06 00:17:39 +00:00
SCM *stack_limit = vp->stack_limit; /* stack limit address */
abort always dispatches to VM bytecode, to detect same-invocation aborts * libguile/control.h: * libguile/control.c (scm_c_make_prompt): Take an extra arg, a cookie. Continuations will be rewindable only if the abort has the same cookie as the prompt. (scm_at_abort): Redefine from scm_abort, and instead of taking rest args, take the abort values as a list directly. Also, don't allow rewinding, because we won't support rewinding the C stack with delimited continuations. * libguile/eval.c (eval): Adapt to scm_c_make_prompt change. * libguile/vm-engine.c (vm_engine): Use vp->cookie to get a unique value corresponding to this VM invocation. * libguile/vm-i-system.c (prompt): Pass the cookie to scm_c_make_prompt. (abort): Take an additional tail arg. * libguile/vm.c (vm_abort): Parse out the abort tail arg. This is for the @abort case, or the (apply abort ...) case. (make_vm): Initialize the cookie to 0. * libguile/vm.h (struct scm_vm): Add cookie. * module/ice-9/boot-9.scm (abort): Define here as a trampoline to @abort. Needed to make sure that a call to abort dispatches to a VM opcode, so the cookie will be the same. * module/language/tree-il.scm (<tree-il>): Add a "tail" field to <abort>, for the (apply abort ...) case, or (@abort tag args). Should be #<const ()> in the normal case. Add support throughout. * module/language/tree-il/analyze.scm (analyze-lexicals): Add abort-tail support here too. * module/language/tree-il/compile-glil.scm (flatten): Compile the tail argument appropriately. * module/language/tree-il/primitives.scm (*primitive-expand-table*): Fix @abort and abort cases to pass the tail arg to make-abort.
2010-02-22 21:53:24 +01:00
scm_i_thread *current_thread = SCM_I_CURRENT_THREAD;
2000-08-22 15:54:19 +00:00
2000-08-22 19:02:22 +00:00
/* Internal variables */
int nvalues = 0;
scm_i_jmp_buf registers; /* used for prompts */
static opcodes; refactor program/objcode division; use new assembly pipeline * gdbinit: Untested attempts to get the stack fondling macros to deal with the new program representation. * libguile/frames.c (scm_vm_frame_arguments, scm_vm_frame_source) (scm_vm_frame_local_ref, scm_vm_frame_local_set_x): SCM_PROGRAM_DATA is a struct scm_objcode*. * libguile/instructions.h: * libguile/instructions.c: Hide the instruction table and the struct scm_instruction structure; all access to instructions now goes through procedures. This is because instructions are no longer in a packed array indexed by opcode. Also, declare a mask that all instructions should fit in. * libguile/objcodes.h: * libguile/objcodes.c: Rewrite so that object code directly maps its arity and length from its bytecode. This makes it unnecessary to keep this information in programs, allowing programs to be simple conses between the code (objcodes) and data (the object table and the closure variables). * libguile/programs.c (scm_make_program): Rework so that make-program takes objcode, an object table, and externals as arguments. It's much clearer this way, and we avoid malloc(). * libguile/stacks.c (is_vm_bootstrap_frame): Update for program/objcode changes. * libguile/vm-engine.c (vm_run): Initialize the jump table on the first run, with the opcodes declared in the instruction sources, and with bad instructions raising an error instead of wandering off into the Unknown. * libguile/vm-engine.h (FETCH_LENGTH): Always represent lengths as 3 bytes. The old code was too error-prone. (NEXT_JUMP): Mask the instruction with SCM_VM_INSTRUCTION_MASK. (NEW_FRAME): Update for program/objcode changes. * libguile/vm-expand.h (VM_DEFINE_FUNCTION, VM_DEFINE_INSTRUCTION) (VM_DEFINE_LOADER): Update so that we explicitly specify opcodes, so that we have a stable bytecode API. * libguile/vm-i-loader.c: Update license to LGPLv2+. Explicitly declare opcodes. (load-integer): Use an int instead of a long as the accumulator; still need to revisit this code at some point, I think. (load-program): Simplify, thankfully!! Just creates the objcode slice and rolls with it. * libguile/vm-i-scheme.c: Number the opcodes explicitly. * libguile/vm-i-system.c: Update license to LGPLv2+. Explicitly declare opcodes. (make-closure): Update for new program API. * libguile/vm.c (vm_make_boot_program): Update for new program/objcode API. Still a bit ugly. (scm_load_compiled_with_vm): Update for new program/objcode API. * module/language/assembly.scm (byte-length): Fix byte-length calculation for loaders, and load-program. (code-pack, code-unpack): Start to move things from (system vm conv) here. (object->code, code->object): More things from conv.scm. * module/language/glil.scm (<glil-program>): Add a new field, closure-level. (make-glil-program, compute-closure-level): Calculate the "closure level" when making a glil program. This is the maximum depth of external binding refs in this closure. (unparse-glil): Fix label serialization. * module/language/glil/compile-assembly.scm (make-meta): Prepend #f for the meta's object table, though maybe in the future we can avoid creating assembly in the first place. (assoc-ref-or-acons, object-index-and-alist): GRRR! Caught again by the different sets of arguments to assoc and assoc-ref! (glil->assembly): Attempt to make the <glil-program> case more readable, and fix the bugs. Sorry I don't know how to comment this change any more than this. (glil->assembly): For <glil-module> serialize the whole key, not just the name. (dump-object): subprogram-code is already a list. Serialize integers as strings, not u8vectors. Fix the order of lists and vectors. * module/language/glil/spec.scm (glil): Switch orders, so we prefer glil -> assembly -> objcode. Actually glil->objcode doesn't work any more, needs to be removed I think. * module/language/objcode/spec.scm (objcode->value): s/objcode->program/make-program/. * module/language/scheme/inline.scm: Add acons inline. * module/system/vm/conv.scm (make-byte-decoder): Skip the first 8 bytes, they are header. Handle subprograms properly. Still needs help though. (decode-length): Lengths are always 3 bytes now. * module/system/vm/disasm.scm: Superficial changes to keep things working. I'd like to fix this better in the future. * module/system/vm/frame.scm (bootstrap-frame?): Fixes for program-bytecode. * module/system/vm/program.scm: Export make-program. It's program-objcode now, no more program-bytecode. * module/system/vm/vm.scm (vm-load): Use make-program. * test-suite/tests/asm-to-bytecode.test: New test, very minimal. * module/system/vm/objcode.scm: Export word-size, byte-order, and write-objcode.
2009-01-29 21:09:04 +01:00
#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))
static opcodes; refactor program/objcode division; use new assembly pipeline * gdbinit: Untested attempts to get the stack fondling macros to deal with the new program representation. * libguile/frames.c (scm_vm_frame_arguments, scm_vm_frame_source) (scm_vm_frame_local_ref, scm_vm_frame_local_set_x): SCM_PROGRAM_DATA is a struct scm_objcode*. * libguile/instructions.h: * libguile/instructions.c: Hide the instruction table and the struct scm_instruction structure; all access to instructions now goes through procedures. This is because instructions are no longer in a packed array indexed by opcode. Also, declare a mask that all instructions should fit in. * libguile/objcodes.h: * libguile/objcodes.c: Rewrite so that object code directly maps its arity and length from its bytecode. This makes it unnecessary to keep this information in programs, allowing programs to be simple conses between the code (objcodes) and data (the object table and the closure variables). * libguile/programs.c (scm_make_program): Rework so that make-program takes objcode, an object table, and externals as arguments. It's much clearer this way, and we avoid malloc(). * libguile/stacks.c (is_vm_bootstrap_frame): Update for program/objcode changes. * libguile/vm-engine.c (vm_run): Initialize the jump table on the first run, with the opcodes declared in the instruction sources, and with bad instructions raising an error instead of wandering off into the Unknown. * libguile/vm-engine.h (FETCH_LENGTH): Always represent lengths as 3 bytes. The old code was too error-prone. (NEXT_JUMP): Mask the instruction with SCM_VM_INSTRUCTION_MASK. (NEW_FRAME): Update for program/objcode changes. * libguile/vm-expand.h (VM_DEFINE_FUNCTION, VM_DEFINE_INSTRUCTION) (VM_DEFINE_LOADER): Update so that we explicitly specify opcodes, so that we have a stable bytecode API. * libguile/vm-i-loader.c: Update license to LGPLv2+. Explicitly declare opcodes. (load-integer): Use an int instead of a long as the accumulator; still need to revisit this code at some point, I think. (load-program): Simplify, thankfully!! Just creates the objcode slice and rolls with it. * libguile/vm-i-scheme.c: Number the opcodes explicitly. * libguile/vm-i-system.c: Update license to LGPLv2+. Explicitly declare opcodes. (make-closure): Update for new program API. * libguile/vm.c (vm_make_boot_program): Update for new program/objcode API. Still a bit ugly. (scm_load_compiled_with_vm): Update for new program/objcode API. * module/language/assembly.scm (byte-length): Fix byte-length calculation for loaders, and load-program. (code-pack, code-unpack): Start to move things from (system vm conv) here. (object->code, code->object): More things from conv.scm. * module/language/glil.scm (<glil-program>): Add a new field, closure-level. (make-glil-program, compute-closure-level): Calculate the "closure level" when making a glil program. This is the maximum depth of external binding refs in this closure. (unparse-glil): Fix label serialization. * module/language/glil/compile-assembly.scm (make-meta): Prepend #f for the meta's object table, though maybe in the future we can avoid creating assembly in the first place. (assoc-ref-or-acons, object-index-and-alist): GRRR! Caught again by the different sets of arguments to assoc and assoc-ref! (glil->assembly): Attempt to make the <glil-program> case more readable, and fix the bugs. Sorry I don't know how to comment this change any more than this. (glil->assembly): For <glil-module> serialize the whole key, not just the name. (dump-object): subprogram-code is already a list. Serialize integers as strings, not u8vectors. Fix the order of lists and vectors. * module/language/glil/spec.scm (glil): Switch orders, so we prefer glil -> assembly -> objcode. Actually glil->objcode doesn't work any more, needs to be removed I think. * module/language/objcode/spec.scm (objcode->value): s/objcode->program/make-program/. * module/language/scheme/inline.scm: Add acons inline. * module/system/vm/conv.scm (make-byte-decoder): Skip the first 8 bytes, they are header. Handle subprograms properly. Still needs help though. (decode-length): Lengths are always 3 bytes now. * module/system/vm/disasm.scm: Superficial changes to keep things working. I'd like to fix this better in the future. * module/system/vm/frame.scm (bootstrap-frame?): Fixes for program-bytecode. * module/system/vm/program.scm: Export make-program. It's program-objcode now, no more program-bytecode. * module/system/vm/vm.scm (vm-load): Use make-program. * test-suite/tests/asm-to-bytecode.test: New test, very minimal. * module/system/vm/objcode.scm: Export word-size, byte-order, and write-objcode.
2009-01-29 21:09:04 +01:00
{
int i;
jump_table_pointer = malloc (SCM_VM_NUM_INSTRUCTIONS * sizeof (void*));
static opcodes; refactor program/objcode division; use new assembly pipeline * gdbinit: Untested attempts to get the stack fondling macros to deal with the new program representation. * libguile/frames.c (scm_vm_frame_arguments, scm_vm_frame_source) (scm_vm_frame_local_ref, scm_vm_frame_local_set_x): SCM_PROGRAM_DATA is a struct scm_objcode*. * libguile/instructions.h: * libguile/instructions.c: Hide the instruction table and the struct scm_instruction structure; all access to instructions now goes through procedures. This is because instructions are no longer in a packed array indexed by opcode. Also, declare a mask that all instructions should fit in. * libguile/objcodes.h: * libguile/objcodes.c: Rewrite so that object code directly maps its arity and length from its bytecode. This makes it unnecessary to keep this information in programs, allowing programs to be simple conses between the code (objcodes) and data (the object table and the closure variables). * libguile/programs.c (scm_make_program): Rework so that make-program takes objcode, an object table, and externals as arguments. It's much clearer this way, and we avoid malloc(). * libguile/stacks.c (is_vm_bootstrap_frame): Update for program/objcode changes. * libguile/vm-engine.c (vm_run): Initialize the jump table on the first run, with the opcodes declared in the instruction sources, and with bad instructions raising an error instead of wandering off into the Unknown. * libguile/vm-engine.h (FETCH_LENGTH): Always represent lengths as 3 bytes. The old code was too error-prone. (NEXT_JUMP): Mask the instruction with SCM_VM_INSTRUCTION_MASK. (NEW_FRAME): Update for program/objcode changes. * libguile/vm-expand.h (VM_DEFINE_FUNCTION, VM_DEFINE_INSTRUCTION) (VM_DEFINE_LOADER): Update so that we explicitly specify opcodes, so that we have a stable bytecode API. * libguile/vm-i-loader.c: Update license to LGPLv2+. Explicitly declare opcodes. (load-integer): Use an int instead of a long as the accumulator; still need to revisit this code at some point, I think. (load-program): Simplify, thankfully!! Just creates the objcode slice and rolls with it. * libguile/vm-i-scheme.c: Number the opcodes explicitly. * libguile/vm-i-system.c: Update license to LGPLv2+. Explicitly declare opcodes. (make-closure): Update for new program API. * libguile/vm.c (vm_make_boot_program): Update for new program/objcode API. Still a bit ugly. (scm_load_compiled_with_vm): Update for new program/objcode API. * module/language/assembly.scm (byte-length): Fix byte-length calculation for loaders, and load-program. (code-pack, code-unpack): Start to move things from (system vm conv) here. (object->code, code->object): More things from conv.scm. * module/language/glil.scm (<glil-program>): Add a new field, closure-level. (make-glil-program, compute-closure-level): Calculate the "closure level" when making a glil program. This is the maximum depth of external binding refs in this closure. (unparse-glil): Fix label serialization. * module/language/glil/compile-assembly.scm (make-meta): Prepend #f for the meta's object table, though maybe in the future we can avoid creating assembly in the first place. (assoc-ref-or-acons, object-index-and-alist): GRRR! Caught again by the different sets of arguments to assoc and assoc-ref! (glil->assembly): Attempt to make the <glil-program> case more readable, and fix the bugs. Sorry I don't know how to comment this change any more than this. (glil->assembly): For <glil-module> serialize the whole key, not just the name. (dump-object): subprogram-code is already a list. Serialize integers as strings, not u8vectors. Fix the order of lists and vectors. * module/language/glil/spec.scm (glil): Switch orders, so we prefer glil -> assembly -> objcode. Actually glil->objcode doesn't work any more, needs to be removed I think. * module/language/objcode/spec.scm (objcode->value): s/objcode->program/make-program/. * module/language/scheme/inline.scm: Add acons inline. * module/system/vm/conv.scm (make-byte-decoder): Skip the first 8 bytes, they are header. Handle subprograms properly. Still needs help though. (decode-length): Lengths are always 3 bytes now. * module/system/vm/disasm.scm: Superficial changes to keep things working. I'd like to fix this better in the future. * module/system/vm/frame.scm (bootstrap-frame?): Fixes for program-bytecode. * module/system/vm/program.scm: Export make-program. It's program-objcode now, no more program-bytecode. * module/system/vm/vm.scm (vm-load): Use make-program. * test-suite/tests/asm-to-bytecode.test: New test, very minimal. * module/system/vm/objcode.scm: Export word-size, byte-order, and write-objcode.
2009-01-29 21:09:04 +01:00
for (i = 0; i < SCM_VM_NUM_INSTRUCTIONS; i++)
jump_table_pointer[i] = &&vm_error_bad_instruction;
static opcodes; refactor program/objcode division; use new assembly pipeline * gdbinit: Untested attempts to get the stack fondling macros to deal with the new program representation. * libguile/frames.c (scm_vm_frame_arguments, scm_vm_frame_source) (scm_vm_frame_local_ref, scm_vm_frame_local_set_x): SCM_PROGRAM_DATA is a struct scm_objcode*. * libguile/instructions.h: * libguile/instructions.c: Hide the instruction table and the struct scm_instruction structure; all access to instructions now goes through procedures. This is because instructions are no longer in a packed array indexed by opcode. Also, declare a mask that all instructions should fit in. * libguile/objcodes.h: * libguile/objcodes.c: Rewrite so that object code directly maps its arity and length from its bytecode. This makes it unnecessary to keep this information in programs, allowing programs to be simple conses between the code (objcodes) and data (the object table and the closure variables). * libguile/programs.c (scm_make_program): Rework so that make-program takes objcode, an object table, and externals as arguments. It's much clearer this way, and we avoid malloc(). * libguile/stacks.c (is_vm_bootstrap_frame): Update for program/objcode changes. * libguile/vm-engine.c (vm_run): Initialize the jump table on the first run, with the opcodes declared in the instruction sources, and with bad instructions raising an error instead of wandering off into the Unknown. * libguile/vm-engine.h (FETCH_LENGTH): Always represent lengths as 3 bytes. The old code was too error-prone. (NEXT_JUMP): Mask the instruction with SCM_VM_INSTRUCTION_MASK. (NEW_FRAME): Update for program/objcode changes. * libguile/vm-expand.h (VM_DEFINE_FUNCTION, VM_DEFINE_INSTRUCTION) (VM_DEFINE_LOADER): Update so that we explicitly specify opcodes, so that we have a stable bytecode API. * libguile/vm-i-loader.c: Update license to LGPLv2+. Explicitly declare opcodes. (load-integer): Use an int instead of a long as the accumulator; still need to revisit this code at some point, I think. (load-program): Simplify, thankfully!! Just creates the objcode slice and rolls with it. * libguile/vm-i-scheme.c: Number the opcodes explicitly. * libguile/vm-i-system.c: Update license to LGPLv2+. Explicitly declare opcodes. (make-closure): Update for new program API. * libguile/vm.c (vm_make_boot_program): Update for new program/objcode API. Still a bit ugly. (scm_load_compiled_with_vm): Update for new program/objcode API. * module/language/assembly.scm (byte-length): Fix byte-length calculation for loaders, and load-program. (code-pack, code-unpack): Start to move things from (system vm conv) here. (object->code, code->object): More things from conv.scm. * module/language/glil.scm (<glil-program>): Add a new field, closure-level. (make-glil-program, compute-closure-level): Calculate the "closure level" when making a glil program. This is the maximum depth of external binding refs in this closure. (unparse-glil): Fix label serialization. * module/language/glil/compile-assembly.scm (make-meta): Prepend #f for the meta's object table, though maybe in the future we can avoid creating assembly in the first place. (assoc-ref-or-acons, object-index-and-alist): GRRR! Caught again by the different sets of arguments to assoc and assoc-ref! (glil->assembly): Attempt to make the <glil-program> case more readable, and fix the bugs. Sorry I don't know how to comment this change any more than this. (glil->assembly): For <glil-module> serialize the whole key, not just the name. (dump-object): subprogram-code is already a list. Serialize integers as strings, not u8vectors. Fix the order of lists and vectors. * module/language/glil/spec.scm (glil): Switch orders, so we prefer glil -> assembly -> objcode. Actually glil->objcode doesn't work any more, needs to be removed I think. * module/language/objcode/spec.scm (objcode->value): s/objcode->program/make-program/. * module/language/scheme/inline.scm: Add acons inline. * module/system/vm/conv.scm (make-byte-decoder): Skip the first 8 bytes, they are header. Handle subprograms properly. Still needs help though. (decode-length): Lengths are always 3 bytes now. * module/system/vm/disasm.scm: Superficial changes to keep things working. I'd like to fix this better in the future. * module/system/vm/frame.scm (bootstrap-frame?): Fixes for program-bytecode. * module/system/vm/program.scm: Export make-program. It's program-objcode now, no more program-bytecode. * module/system/vm/vm.scm (vm-load): Use make-program. * test-suite/tests/asm-to-bytecode.test: New test, very minimal. * module/system/vm/objcode.scm: Export word-size, byte-order, and write-objcode.
2009-01-29 21:09:04 +01:00
#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
static opcodes; refactor program/objcode division; use new assembly pipeline * gdbinit: Untested attempts to get the stack fondling macros to deal with the new program representation. * libguile/frames.c (scm_vm_frame_arguments, scm_vm_frame_source) (scm_vm_frame_local_ref, scm_vm_frame_local_set_x): SCM_PROGRAM_DATA is a struct scm_objcode*. * libguile/instructions.h: * libguile/instructions.c: Hide the instruction table and the struct scm_instruction structure; all access to instructions now goes through procedures. This is because instructions are no longer in a packed array indexed by opcode. Also, declare a mask that all instructions should fit in. * libguile/objcodes.h: * libguile/objcodes.c: Rewrite so that object code directly maps its arity and length from its bytecode. This makes it unnecessary to keep this information in programs, allowing programs to be simple conses between the code (objcodes) and data (the object table and the closure variables). * libguile/programs.c (scm_make_program): Rework so that make-program takes objcode, an object table, and externals as arguments. It's much clearer this way, and we avoid malloc(). * libguile/stacks.c (is_vm_bootstrap_frame): Update for program/objcode changes. * libguile/vm-engine.c (vm_run): Initialize the jump table on the first run, with the opcodes declared in the instruction sources, and with bad instructions raising an error instead of wandering off into the Unknown. * libguile/vm-engine.h (FETCH_LENGTH): Always represent lengths as 3 bytes. The old code was too error-prone. (NEXT_JUMP): Mask the instruction with SCM_VM_INSTRUCTION_MASK. (NEW_FRAME): Update for program/objcode changes. * libguile/vm-expand.h (VM_DEFINE_FUNCTION, VM_DEFINE_INSTRUCTION) (VM_DEFINE_LOADER): Update so that we explicitly specify opcodes, so that we have a stable bytecode API. * libguile/vm-i-loader.c: Update license to LGPLv2+. Explicitly declare opcodes. (load-integer): Use an int instead of a long as the accumulator; still need to revisit this code at some point, I think. (load-program): Simplify, thankfully!! Just creates the objcode slice and rolls with it. * libguile/vm-i-scheme.c: Number the opcodes explicitly. * libguile/vm-i-system.c: Update license to LGPLv2+. Explicitly declare opcodes. (make-closure): Update for new program API. * libguile/vm.c (vm_make_boot_program): Update for new program/objcode API. Still a bit ugly. (scm_load_compiled_with_vm): Update for new program/objcode API. * module/language/assembly.scm (byte-length): Fix byte-length calculation for loaders, and load-program. (code-pack, code-unpack): Start to move things from (system vm conv) here. (object->code, code->object): More things from conv.scm. * module/language/glil.scm (<glil-program>): Add a new field, closure-level. (make-glil-program, compute-closure-level): Calculate the "closure level" when making a glil program. This is the maximum depth of external binding refs in this closure. (unparse-glil): Fix label serialization. * module/language/glil/compile-assembly.scm (make-meta): Prepend #f for the meta's object table, though maybe in the future we can avoid creating assembly in the first place. (assoc-ref-or-acons, object-index-and-alist): GRRR! Caught again by the different sets of arguments to assoc and assoc-ref! (glil->assembly): Attempt to make the <glil-program> case more readable, and fix the bugs. Sorry I don't know how to comment this change any more than this. (glil->assembly): For <glil-module> serialize the whole key, not just the name. (dump-object): subprogram-code is already a list. Serialize integers as strings, not u8vectors. Fix the order of lists and vectors. * module/language/glil/spec.scm (glil): Switch orders, so we prefer glil -> assembly -> objcode. Actually glil->objcode doesn't work any more, needs to be removed I think. * module/language/objcode/spec.scm (objcode->value): s/objcode->program/make-program/. * module/language/scheme/inline.scm: Add acons inline. * module/system/vm/conv.scm (make-byte-decoder): Skip the first 8 bytes, they are header. Handle subprograms properly. Still needs help though. (decode-length): Lengths are always 3 bytes now. * module/system/vm/disasm.scm: Superficial changes to keep things working. I'd like to fix this better in the future. * module/system/vm/frame.scm (bootstrap-frame?): Fixes for program-bytecode. * module/system/vm/program.scm: Export make-program. It's program-objcode now, no more program-bytecode. * module/system/vm/vm.scm (vm-load): Use make-program. * test-suite/tests/asm-to-bytecode.test: New test, very minimal. * module/system/vm/objcode.scm: Export word-size, byte-order, and write-objcode.
2009-01-29 21:09:04 +01:00
#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;
static opcodes; refactor program/objcode division; use new assembly pipeline * gdbinit: Untested attempts to get the stack fondling macros to deal with the new program representation. * libguile/frames.c (scm_vm_frame_arguments, scm_vm_frame_source) (scm_vm_frame_local_ref, scm_vm_frame_local_set_x): SCM_PROGRAM_DATA is a struct scm_objcode*. * libguile/instructions.h: * libguile/instructions.c: Hide the instruction table and the struct scm_instruction structure; all access to instructions now goes through procedures. This is because instructions are no longer in a packed array indexed by opcode. Also, declare a mask that all instructions should fit in. * libguile/objcodes.h: * libguile/objcodes.c: Rewrite so that object code directly maps its arity and length from its bytecode. This makes it unnecessary to keep this information in programs, allowing programs to be simple conses between the code (objcodes) and data (the object table and the closure variables). * libguile/programs.c (scm_make_program): Rework so that make-program takes objcode, an object table, and externals as arguments. It's much clearer this way, and we avoid malloc(). * libguile/stacks.c (is_vm_bootstrap_frame): Update for program/objcode changes. * libguile/vm-engine.c (vm_run): Initialize the jump table on the first run, with the opcodes declared in the instruction sources, and with bad instructions raising an error instead of wandering off into the Unknown. * libguile/vm-engine.h (FETCH_LENGTH): Always represent lengths as 3 bytes. The old code was too error-prone. (NEXT_JUMP): Mask the instruction with SCM_VM_INSTRUCTION_MASK. (NEW_FRAME): Update for program/objcode changes. * libguile/vm-expand.h (VM_DEFINE_FUNCTION, VM_DEFINE_INSTRUCTION) (VM_DEFINE_LOADER): Update so that we explicitly specify opcodes, so that we have a stable bytecode API. * libguile/vm-i-loader.c: Update license to LGPLv2+. Explicitly declare opcodes. (load-integer): Use an int instead of a long as the accumulator; still need to revisit this code at some point, I think. (load-program): Simplify, thankfully!! Just creates the objcode slice and rolls with it. * libguile/vm-i-scheme.c: Number the opcodes explicitly. * libguile/vm-i-system.c: Update license to LGPLv2+. Explicitly declare opcodes. (make-closure): Update for new program API. * libguile/vm.c (vm_make_boot_program): Update for new program/objcode API. Still a bit ugly. (scm_load_compiled_with_vm): Update for new program/objcode API. * module/language/assembly.scm (byte-length): Fix byte-length calculation for loaders, and load-program. (code-pack, code-unpack): Start to move things from (system vm conv) here. (object->code, code->object): More things from conv.scm. * module/language/glil.scm (<glil-program>): Add a new field, closure-level. (make-glil-program, compute-closure-level): Calculate the "closure level" when making a glil program. This is the maximum depth of external binding refs in this closure. (unparse-glil): Fix label serialization. * module/language/glil/compile-assembly.scm (make-meta): Prepend #f for the meta's object table, though maybe in the future we can avoid creating assembly in the first place. (assoc-ref-or-acons, object-index-and-alist): GRRR! Caught again by the different sets of arguments to assoc and assoc-ref! (glil->assembly): Attempt to make the <glil-program> case more readable, and fix the bugs. Sorry I don't know how to comment this change any more than this. (glil->assembly): For <glil-module> serialize the whole key, not just the name. (dump-object): subprogram-code is already a list. Serialize integers as strings, not u8vectors. Fix the order of lists and vectors. * module/language/glil/spec.scm (glil): Switch orders, so we prefer glil -> assembly -> objcode. Actually glil->objcode doesn't work any more, needs to be removed I think. * module/language/objcode/spec.scm (objcode->value): s/objcode->program/make-program/. * module/language/scheme/inline.scm: Add acons inline. * module/system/vm/conv.scm (make-byte-decoder): Skip the first 8 bytes, they are header. Handle subprograms properly. Still needs help though. (decode-length): Lengths are always 3 bytes now. * module/system/vm/disasm.scm: Superficial changes to keep things working. I'd like to fix this better in the future. * module/system/vm/frame.scm (bootstrap-frame?): Fixes for program-bytecode. * module/system/vm/program.scm: Export make-program. It's program-objcode now, no more program-bytecode. * module/system/vm/vm.scm (vm-load): Use make-program. * test-suite/tests/asm-to-bytecode.test: New test, very minimal. * module/system/vm/objcode.scm: Export word-size, byte-order, and write-objcode.
2009-01-29 21:09:04 +01:00
#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 ();
NEXT;
}
static opcodes; refactor program/objcode division; use new assembly pipeline * gdbinit: Untested attempts to get the stack fondling macros to deal with the new program representation. * libguile/frames.c (scm_vm_frame_arguments, scm_vm_frame_source) (scm_vm_frame_local_ref, scm_vm_frame_local_set_x): SCM_PROGRAM_DATA is a struct scm_objcode*. * libguile/instructions.h: * libguile/instructions.c: Hide the instruction table and the struct scm_instruction structure; all access to instructions now goes through procedures. This is because instructions are no longer in a packed array indexed by opcode. Also, declare a mask that all instructions should fit in. * libguile/objcodes.h: * libguile/objcodes.c: Rewrite so that object code directly maps its arity and length from its bytecode. This makes it unnecessary to keep this information in programs, allowing programs to be simple conses between the code (objcodes) and data (the object table and the closure variables). * libguile/programs.c (scm_make_program): Rework so that make-program takes objcode, an object table, and externals as arguments. It's much clearer this way, and we avoid malloc(). * libguile/stacks.c (is_vm_bootstrap_frame): Update for program/objcode changes. * libguile/vm-engine.c (vm_run): Initialize the jump table on the first run, with the opcodes declared in the instruction sources, and with bad instructions raising an error instead of wandering off into the Unknown. * libguile/vm-engine.h (FETCH_LENGTH): Always represent lengths as 3 bytes. The old code was too error-prone. (NEXT_JUMP): Mask the instruction with SCM_VM_INSTRUCTION_MASK. (NEW_FRAME): Update for program/objcode changes. * libguile/vm-expand.h (VM_DEFINE_FUNCTION, VM_DEFINE_INSTRUCTION) (VM_DEFINE_LOADER): Update so that we explicitly specify opcodes, so that we have a stable bytecode API. * libguile/vm-i-loader.c: Update license to LGPLv2+. Explicitly declare opcodes. (load-integer): Use an int instead of a long as the accumulator; still need to revisit this code at some point, I think. (load-program): Simplify, thankfully!! Just creates the objcode slice and rolls with it. * libguile/vm-i-scheme.c: Number the opcodes explicitly. * libguile/vm-i-system.c: Update license to LGPLv2+. Explicitly declare opcodes. (make-closure): Update for new program API. * libguile/vm.c (vm_make_boot_program): Update for new program/objcode API. Still a bit ugly. (scm_load_compiled_with_vm): Update for new program/objcode API. * module/language/assembly.scm (byte-length): Fix byte-length calculation for loaders, and load-program. (code-pack, code-unpack): Start to move things from (system vm conv) here. (object->code, code->object): More things from conv.scm. * module/language/glil.scm (<glil-program>): Add a new field, closure-level. (make-glil-program, compute-closure-level): Calculate the "closure level" when making a glil program. This is the maximum depth of external binding refs in this closure. (unparse-glil): Fix label serialization. * module/language/glil/compile-assembly.scm (make-meta): Prepend #f for the meta's object table, though maybe in the future we can avoid creating assembly in the first place. (assoc-ref-or-acons, object-index-and-alist): GRRR! Caught again by the different sets of arguments to assoc and assoc-ref! (glil->assembly): Attempt to make the <glil-program> case more readable, and fix the bugs. Sorry I don't know how to comment this change any more than this. (glil->assembly): For <glil-module> serialize the whole key, not just the name. (dump-object): subprogram-code is already a list. Serialize integers as strings, not u8vectors. Fix the order of lists and vectors. * module/language/glil/spec.scm (glil): Switch orders, so we prefer glil -> assembly -> objcode. Actually glil->objcode doesn't work any more, needs to be removed I think. * module/language/objcode/spec.scm (objcode->value): s/objcode->program/make-program/. * module/language/scheme/inline.scm: Add acons inline. * module/system/vm/conv.scm (make-byte-decoder): Skip the first 8 bytes, they are header. Handle subprograms properly. Still needs help though. (decode-length): Lengths are always 3 bytes now. * module/system/vm/disasm.scm: Superficial changes to keep things working. I'd like to fix this better in the future. * module/system/vm/frame.scm (bootstrap-frame?): Fixes for program-bytecode. * module/system/vm/program.scm: Export make-program. It's program-objcode now, no more program-bytecode. * module/system/vm/vm.scm (vm-load): Use make-program. * test-suite/tests/asm-to-bytecode.test: New test, very minimal. * module/system/vm/objcode.scm: Export word-size, byte-order, and write-objcode.
2009-01-29 21:09:04 +01:00
/* Initial frame */
CACHE_REGISTER ();
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;
VM_ASSERT (sp + nargs < stack_limit, vm_error_too_many_args (nargs));
while (nargs--)
PUSH (*argv++);
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_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 ();
2000-08-22 15:54:19 +00:00
/* Let's go! */
static opcodes; refactor program/objcode division; use new assembly pipeline * gdbinit: Untested attempts to get the stack fondling macros to deal with the new program representation. * libguile/frames.c (scm_vm_frame_arguments, scm_vm_frame_source) (scm_vm_frame_local_ref, scm_vm_frame_local_set_x): SCM_PROGRAM_DATA is a struct scm_objcode*. * libguile/instructions.h: * libguile/instructions.c: Hide the instruction table and the struct scm_instruction structure; all access to instructions now goes through procedures. This is because instructions are no longer in a packed array indexed by opcode. Also, declare a mask that all instructions should fit in. * libguile/objcodes.h: * libguile/objcodes.c: Rewrite so that object code directly maps its arity and length from its bytecode. This makes it unnecessary to keep this information in programs, allowing programs to be simple conses between the code (objcodes) and data (the object table and the closure variables). * libguile/programs.c (scm_make_program): Rework so that make-program takes objcode, an object table, and externals as arguments. It's much clearer this way, and we avoid malloc(). * libguile/stacks.c (is_vm_bootstrap_frame): Update for program/objcode changes. * libguile/vm-engine.c (vm_run): Initialize the jump table on the first run, with the opcodes declared in the instruction sources, and with bad instructions raising an error instead of wandering off into the Unknown. * libguile/vm-engine.h (FETCH_LENGTH): Always represent lengths as 3 bytes. The old code was too error-prone. (NEXT_JUMP): Mask the instruction with SCM_VM_INSTRUCTION_MASK. (NEW_FRAME): Update for program/objcode changes. * libguile/vm-expand.h (VM_DEFINE_FUNCTION, VM_DEFINE_INSTRUCTION) (VM_DEFINE_LOADER): Update so that we explicitly specify opcodes, so that we have a stable bytecode API. * libguile/vm-i-loader.c: Update license to LGPLv2+. Explicitly declare opcodes. (load-integer): Use an int instead of a long as the accumulator; still need to revisit this code at some point, I think. (load-program): Simplify, thankfully!! Just creates the objcode slice and rolls with it. * libguile/vm-i-scheme.c: Number the opcodes explicitly. * libguile/vm-i-system.c: Update license to LGPLv2+. Explicitly declare opcodes. (make-closure): Update for new program API. * libguile/vm.c (vm_make_boot_program): Update for new program/objcode API. Still a bit ugly. (scm_load_compiled_with_vm): Update for new program/objcode API. * module/language/assembly.scm (byte-length): Fix byte-length calculation for loaders, and load-program. (code-pack, code-unpack): Start to move things from (system vm conv) here. (object->code, code->object): More things from conv.scm. * module/language/glil.scm (<glil-program>): Add a new field, closure-level. (make-glil-program, compute-closure-level): Calculate the "closure level" when making a glil program. This is the maximum depth of external binding refs in this closure. (unparse-glil): Fix label serialization. * module/language/glil/compile-assembly.scm (make-meta): Prepend #f for the meta's object table, though maybe in the future we can avoid creating assembly in the first place. (assoc-ref-or-acons, object-index-and-alist): GRRR! Caught again by the different sets of arguments to assoc and assoc-ref! (glil->assembly): Attempt to make the <glil-program> case more readable, and fix the bugs. Sorry I don't know how to comment this change any more than this. (glil->assembly): For <glil-module> serialize the whole key, not just the name. (dump-object): subprogram-code is already a list. Serialize integers as strings, not u8vectors. Fix the order of lists and vectors. * module/language/glil/spec.scm (glil): Switch orders, so we prefer glil -> assembly -> objcode. Actually glil->objcode doesn't work any more, needs to be removed I think. * module/language/objcode/spec.scm (objcode->value): s/objcode->program/make-program/. * module/language/scheme/inline.scm: Add acons inline. * module/system/vm/conv.scm (make-byte-decoder): Skip the first 8 bytes, they are header. Handle subprograms properly. Still needs help though. (decode-length): Lengths are always 3 bytes now. * module/system/vm/disasm.scm: Superficial changes to keep things working. I'd like to fix this better in the future. * module/system/vm/frame.scm (bootstrap-frame?): Fixes for program-bytecode. * module/system/vm/program.scm: Export make-program. It's program-objcode now, no more program-bytecode. * module/system/vm/vm.scm (vm-load): Use make-program. * test-suite/tests/asm-to-bytecode.test: New test, very minimal. * module/system/vm/objcode.scm: Export word-size, byte-order, and write-objcode.
2009-01-29 21:09:04 +01:00
NEXT;
2000-08-22 15:54:19 +00:00
#ifndef HAVE_LABELS_AS_VALUES
2001-04-01 05:03:41 +00:00
vm_start:
static opcodes; refactor program/objcode division; use new assembly pipeline * gdbinit: Untested attempts to get the stack fondling macros to deal with the new program representation. * libguile/frames.c (scm_vm_frame_arguments, scm_vm_frame_source) (scm_vm_frame_local_ref, scm_vm_frame_local_set_x): SCM_PROGRAM_DATA is a struct scm_objcode*. * libguile/instructions.h: * libguile/instructions.c: Hide the instruction table and the struct scm_instruction structure; all access to instructions now goes through procedures. This is because instructions are no longer in a packed array indexed by opcode. Also, declare a mask that all instructions should fit in. * libguile/objcodes.h: * libguile/objcodes.c: Rewrite so that object code directly maps its arity and length from its bytecode. This makes it unnecessary to keep this information in programs, allowing programs to be simple conses between the code (objcodes) and data (the object table and the closure variables). * libguile/programs.c (scm_make_program): Rework so that make-program takes objcode, an object table, and externals as arguments. It's much clearer this way, and we avoid malloc(). * libguile/stacks.c (is_vm_bootstrap_frame): Update for program/objcode changes. * libguile/vm-engine.c (vm_run): Initialize the jump table on the first run, with the opcodes declared in the instruction sources, and with bad instructions raising an error instead of wandering off into the Unknown. * libguile/vm-engine.h (FETCH_LENGTH): Always represent lengths as 3 bytes. The old code was too error-prone. (NEXT_JUMP): Mask the instruction with SCM_VM_INSTRUCTION_MASK. (NEW_FRAME): Update for program/objcode changes. * libguile/vm-expand.h (VM_DEFINE_FUNCTION, VM_DEFINE_INSTRUCTION) (VM_DEFINE_LOADER): Update so that we explicitly specify opcodes, so that we have a stable bytecode API. * libguile/vm-i-loader.c: Update license to LGPLv2+. Explicitly declare opcodes. (load-integer): Use an int instead of a long as the accumulator; still need to revisit this code at some point, I think. (load-program): Simplify, thankfully!! Just creates the objcode slice and rolls with it. * libguile/vm-i-scheme.c: Number the opcodes explicitly. * libguile/vm-i-system.c: Update license to LGPLv2+. Explicitly declare opcodes. (make-closure): Update for new program API. * libguile/vm.c (vm_make_boot_program): Update for new program/objcode API. Still a bit ugly. (scm_load_compiled_with_vm): Update for new program/objcode API. * module/language/assembly.scm (byte-length): Fix byte-length calculation for loaders, and load-program. (code-pack, code-unpack): Start to move things from (system vm conv) here. (object->code, code->object): More things from conv.scm. * module/language/glil.scm (<glil-program>): Add a new field, closure-level. (make-glil-program, compute-closure-level): Calculate the "closure level" when making a glil program. This is the maximum depth of external binding refs in this closure. (unparse-glil): Fix label serialization. * module/language/glil/compile-assembly.scm (make-meta): Prepend #f for the meta's object table, though maybe in the future we can avoid creating assembly in the first place. (assoc-ref-or-acons, object-index-and-alist): GRRR! Caught again by the different sets of arguments to assoc and assoc-ref! (glil->assembly): Attempt to make the <glil-program> case more readable, and fix the bugs. Sorry I don't know how to comment this change any more than this. (glil->assembly): For <glil-module> serialize the whole key, not just the name. (dump-object): subprogram-code is already a list. Serialize integers as strings, not u8vectors. Fix the order of lists and vectors. * module/language/glil/spec.scm (glil): Switch orders, so we prefer glil -> assembly -> objcode. Actually glil->objcode doesn't work any more, needs to be removed I think. * module/language/objcode/spec.scm (objcode->value): s/objcode->program/make-program/. * module/language/scheme/inline.scm: Add acons inline. * module/system/vm/conv.scm (make-byte-decoder): Skip the first 8 bytes, they are header. Handle subprograms properly. Still needs help though. (decode-length): Lengths are always 3 bytes now. * module/system/vm/disasm.scm: Superficial changes to keep things working. I'd like to fix this better in the future. * module/system/vm/frame.scm (bootstrap-frame?): Fixes for program-bytecode. * module/system/vm/program.scm: Export make-program. It's program-objcode now, no more program-bytecode. * module/system/vm/vm.scm (vm-load): Use make-program. * test-suite/tests/asm-to-bytecode.test: New test, very minimal. * module/system/vm/objcode.scm: Export word-size, byte-order, and write-objcode.
2009-01-29 21:09:04 +01:00
switch ((*ip++) & SCM_VM_INSTRUCTION_MASK) {
2000-08-22 15:54:19 +00:00
#endif
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-expand.h"
#include "vm-i-system.c"
#include "vm-i-scheme.c"
#include "vm-i-loader.c"
2000-08-22 15:54:19 +00:00
#ifndef HAVE_LABELS_AS_VALUES
static opcodes; refactor program/objcode division; use new assembly pipeline * gdbinit: Untested attempts to get the stack fondling macros to deal with the new program representation. * libguile/frames.c (scm_vm_frame_arguments, scm_vm_frame_source) (scm_vm_frame_local_ref, scm_vm_frame_local_set_x): SCM_PROGRAM_DATA is a struct scm_objcode*. * libguile/instructions.h: * libguile/instructions.c: Hide the instruction table and the struct scm_instruction structure; all access to instructions now goes through procedures. This is because instructions are no longer in a packed array indexed by opcode. Also, declare a mask that all instructions should fit in. * libguile/objcodes.h: * libguile/objcodes.c: Rewrite so that object code directly maps its arity and length from its bytecode. This makes it unnecessary to keep this information in programs, allowing programs to be simple conses between the code (objcodes) and data (the object table and the closure variables). * libguile/programs.c (scm_make_program): Rework so that make-program takes objcode, an object table, and externals as arguments. It's much clearer this way, and we avoid malloc(). * libguile/stacks.c (is_vm_bootstrap_frame): Update for program/objcode changes. * libguile/vm-engine.c (vm_run): Initialize the jump table on the first run, with the opcodes declared in the instruction sources, and with bad instructions raising an error instead of wandering off into the Unknown. * libguile/vm-engine.h (FETCH_LENGTH): Always represent lengths as 3 bytes. The old code was too error-prone. (NEXT_JUMP): Mask the instruction with SCM_VM_INSTRUCTION_MASK. (NEW_FRAME): Update for program/objcode changes. * libguile/vm-expand.h (VM_DEFINE_FUNCTION, VM_DEFINE_INSTRUCTION) (VM_DEFINE_LOADER): Update so that we explicitly specify opcodes, so that we have a stable bytecode API. * libguile/vm-i-loader.c: Update license to LGPLv2+. Explicitly declare opcodes. (load-integer): Use an int instead of a long as the accumulator; still need to revisit this code at some point, I think. (load-program): Simplify, thankfully!! Just creates the objcode slice and rolls with it. * libguile/vm-i-scheme.c: Number the opcodes explicitly. * libguile/vm-i-system.c: Update license to LGPLv2+. Explicitly declare opcodes. (make-closure): Update for new program API. * libguile/vm.c (vm_make_boot_program): Update for new program/objcode API. Still a bit ugly. (scm_load_compiled_with_vm): Update for new program/objcode API. * module/language/assembly.scm (byte-length): Fix byte-length calculation for loaders, and load-program. (code-pack, code-unpack): Start to move things from (system vm conv) here. (object->code, code->object): More things from conv.scm. * module/language/glil.scm (<glil-program>): Add a new field, closure-level. (make-glil-program, compute-closure-level): Calculate the "closure level" when making a glil program. This is the maximum depth of external binding refs in this closure. (unparse-glil): Fix label serialization. * module/language/glil/compile-assembly.scm (make-meta): Prepend #f for the meta's object table, though maybe in the future we can avoid creating assembly in the first place. (assoc-ref-or-acons, object-index-and-alist): GRRR! Caught again by the different sets of arguments to assoc and assoc-ref! (glil->assembly): Attempt to make the <glil-program> case more readable, and fix the bugs. Sorry I don't know how to comment this change any more than this. (glil->assembly): For <glil-module> serialize the whole key, not just the name. (dump-object): subprogram-code is already a list. Serialize integers as strings, not u8vectors. Fix the order of lists and vectors. * module/language/glil/spec.scm (glil): Switch orders, so we prefer glil -> assembly -> objcode. Actually glil->objcode doesn't work any more, needs to be removed I think. * module/language/objcode/spec.scm (objcode->value): s/objcode->program/make-program/. * module/language/scheme/inline.scm: Add acons inline. * module/system/vm/conv.scm (make-byte-decoder): Skip the first 8 bytes, they are header. Handle subprograms properly. Still needs help though. (decode-length): Lengths are always 3 bytes now. * module/system/vm/disasm.scm: Superficial changes to keep things working. I'd like to fix this better in the future. * module/system/vm/frame.scm (bootstrap-frame?): Fixes for program-bytecode. * module/system/vm/program.scm: Export make-program. It's program-objcode now, no more program-bytecode. * module/system/vm/vm.scm (vm-load): Use make-program. * test-suite/tests/asm-to-bytecode.test: New test, very minimal. * module/system/vm/objcode.scm: Export word-size, byte-order, and write-objcode.
2009-01-29 21:09:04 +01:00
default:
goto vm_error_bad_instruction;
2000-08-22 15:54:19 +00:00
}
#endif
abort (); /* never reached */
vm_error_bad_instruction:
vm_error_bad_instruction (ip[-1]);
abort (); /* never reached */
2001-04-01 05:03:41 +00:00
handle_overflow:
SYNC_ALL ();
vm_error_stack_overflow (vp);
2000-08-22 15:54:19 +00:00
abort (); /* never reached */
}
#undef RUN_HOOK
#undef RUN_HOOK1
#undef VM_USE_HOOKS
2001-04-01 05:03:41 +00:00
/*
Local Variables:
c-file-style: "gnu"
End:
*/