abort always dispatches to VM bytecode, to detect same-invocation aborts
[bpt/guile.git] / libguile / vm.c
... / ...
CommitLineData
1/* Copyright (C) 2001, 2009, 2010 Free Software Foundation, Inc.
2 *
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public License
5 * as published by the Free Software Foundation; either version 3 of
6 * the License, or (at your option) any later version.
7 *
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 * 02110-1301 USA
17 */
18
19#if HAVE_CONFIG_H
20# include <config.h>
21#endif
22
23#include <stdlib.h>
24#include <alloca.h>
25#include <string.h>
26
27#include "libguile/bdw-gc.h"
28#include <gc/gc_mark.h>
29
30#include "_scm.h"
31#include "control.h"
32#include "frames.h"
33#include "instructions.h"
34#include "objcodes.h"
35#include "programs.h"
36#include "lang.h" /* NULL_OR_NIL_P */
37#include "vm.h"
38
39/* I sometimes use this for debugging. */
40#define vm_puts(OBJ) \
41{ \
42 scm_display (OBJ, scm_current_error_port ()); \
43 scm_newline (scm_current_error_port ()); \
44}
45
46/* The VM has a number of internal assertions that shouldn't normally be
47 necessary, but might be if you think you found a bug in the VM. */
48#define VM_ENABLE_ASSERTIONS
49
50/* We can add a mode that ensures that all stack items above the stack pointer
51 are NULL. This is useful for checking the internal consistency of the VM's
52 assumptions and its operators, but isn't necessary for normal operation. It
53 will ensure that assertions are enabled. Slows down the VM by about 30%. */
54/* NB! If you enable this, search for NULLING in throw.c */
55/* #define VM_ENABLE_STACK_NULLING */
56
57/* #define VM_ENABLE_PARANOID_ASSERTIONS */
58
59#if defined (VM_ENABLE_STACK_NULLING) && !defined (VM_ENABLE_ASSERTIONS)
60#define VM_ENABLE_ASSERTIONS
61#endif
62
63/* When defined, arrange so that the GC doesn't scan the VM stack beyond its
64 current SP. This should help avoid excess data retention. See
65 http://thread.gmane.org/gmane.comp.programming.garbage-collection.boehmgc/3001
66 for a discussion. */
67#define VM_ENABLE_PRECISE_STACK_GC_SCAN
68
69
70\f
71/*
72 * VM Continuation
73 */
74
75void
76scm_i_vm_cont_print (SCM x, SCM port, scm_print_state *pstate)
77{
78 scm_puts ("#<vm-continuation ", port);
79 scm_uintprint (SCM_UNPACK (x), 16, port);
80 scm_puts (">", port);
81}
82
83/* In theory, a number of vm instances can be active in the call trace, and we
84 only want to reify the continuations of those in the current continuation
85 root. I don't see a nice way to do this -- ideally it would involve dynwinds,
86 and previous values of the *the-vm* fluid within the current continuation
87 root. But we don't have access to continuation roots in the dynwind stack.
88 So, just punt for now, we just capture the continuation for the current VM.
89
90 While I'm on the topic, ideally we could avoid copying the C stack if the
91 continuation root is inside VM code, and call/cc was invoked within that same
92 call to vm_run; but that's currently not implemented.
93 */
94static SCM
95vm_capture_continuation (SCM *stack_base,
96 SCM *fp, SCM *sp, scm_t_uint8 *ra, scm_t_uint8 *mvra)
97{
98 struct scm_vm_cont *p;
99
100 p = scm_gc_malloc (sizeof (*p), "capture_vm_cont");
101 p->stack_size = sp - stack_base + 1;
102 p->stack_base = scm_gc_malloc (p->stack_size * sizeof (SCM),
103 "capture_vm_cont");
104#if defined(VM_ENABLE_STACK_NULLING) && 0
105 /* Tail continuations leave their frame on the stack for subsequent
106 application, but don't capture the frame -- so there are some elements on
107 the stack then, and this check doesn't work, so disable it for now. */
108 if (sp >= vp->stack_base)
109 if (!vp->sp[0] || vp->sp[1])
110 abort ();
111 memset (p->stack_base, 0, p->stack_size * sizeof (SCM));
112#endif
113 p->ra = ra;
114 p->mvra = mvra;
115 p->sp = sp;
116 p->fp = fp;
117 memcpy (p->stack_base, stack_base, (sp + 1 - stack_base) * sizeof (SCM));
118 p->reloc = p->stack_base - stack_base;
119 return scm_cell (scm_tc7_vm_cont, (scm_t_bits)p);
120}
121
122static void
123vm_return_to_continuation (SCM vm, SCM cont, size_t n, SCM *argv)
124{
125 struct scm_vm *vp;
126 struct scm_vm_cont *cp;
127 SCM *argv_copy;
128
129 argv_copy = alloca (n * sizeof(SCM));
130 memcpy (argv_copy, argv, n * sizeof(SCM));
131
132 vp = SCM_VM_DATA (vm);
133 cp = SCM_VM_CONT_DATA (cont);
134
135 if (n == 0 && !cp->mvra)
136 scm_misc_error (NULL, "Too few values returned to continuation",
137 SCM_EOL);
138
139 if (vp->stack_size < cp->stack_size + n + 1)
140 {
141 /* puts ("FIXME: Need to expand"); */
142 abort ();
143 }
144#ifdef VM_ENABLE_STACK_NULLING
145 {
146 scm_t_ptrdiff nzero = (vp->sp - cp->sp);
147 if (nzero > 0)
148 memset (vp->stack_base + cp->stack_size, 0, nzero * sizeof (SCM));
149 /* actually nzero should always be negative, because vm_reset_stack will
150 unwind the stack to some point *below* this continuation */
151 }
152#endif
153 vp->sp = cp->sp;
154 vp->fp = cp->fp;
155 memcpy (vp->stack_base, cp->stack_base, cp->stack_size * sizeof (SCM));
156
157 if (n == 1 || !cp->mvra)
158 {
159 vp->ip = cp->ra;
160 vp->sp++;
161 *vp->sp = argv_copy[0];
162 }
163 else
164 {
165 size_t i;
166 for (i = 0; i < n; i++)
167 {
168 vp->sp++;
169 *vp->sp = argv_copy[i];
170 }
171 vp->sp++;
172 *vp->sp = scm_from_size_t (n);
173 vp->ip = cp->mvra;
174 }
175}
176
177SCM
178scm_i_vm_capture_continuation (SCM vm)
179{
180 struct scm_vm *vp = SCM_VM_DATA (vm);
181 return vm_capture_continuation (vp->stack_base, vp->fp, vp->sp, vp->ip, NULL);
182}
183
184static void
185vm_dispatch_hook (SCM vm, int hook_num)
186{
187 struct scm_vm *vp;
188 SCM hook;
189 SCM frame;
190
191 vp = SCM_VM_DATA (vm);
192 hook = vp->hooks[hook_num];
193
194 if (SCM_LIKELY (scm_is_false (hook))
195 || scm_is_null (SCM_HOOK_PROCEDURES (hook)))
196 return;
197
198 vp->trace_level--;
199 frame = scm_c_make_frame (vm, vp->fp, vp->sp, vp->ip, 0);
200 scm_c_run_hookn (hook, &frame, 1);
201 vp->trace_level++;
202}
203
204static void vm_abort (SCM vm, size_t n) SCM_NORETURN;
205static void
206vm_abort (SCM vm, size_t n)
207{
208 size_t i;
209 ssize_t tail_len;
210 SCM tag, tail, *argv;
211
212 /* FIXME: VM_ENABLE_STACK_NULLING */
213 tail = *(SCM_VM_DATA (vm)->sp--);
214 /* NULLSTACK (1) */
215 tail_len = scm_ilength (tail);
216 if (tail_len < 0)
217 abort ();
218 tag = SCM_VM_DATA (vm)->sp[-n];
219 argv = alloca ((n + tail_len) * sizeof (SCM));
220 for (i = 0; i < n; i++)
221 argv[i] = SCM_VM_DATA (vm)->sp[-(n-1-i)];
222 for (; i < n + tail_len; i++, tail = scm_cdr (tail))
223 argv[i] = scm_car (tail);
224 /* NULLSTACK (n + 1) */
225 SCM_VM_DATA (vm)->sp -= n + 1;
226
227 scm_c_abort (vm, tag, n + tail_len, argv);
228}
229
230\f
231/*
232 * VM Internal functions
233 */
234
235SCM_SYMBOL (sym_vm_run, "vm-run");
236SCM_SYMBOL (sym_vm_error, "vm-error");
237SCM_SYMBOL (sym_keyword_argument_error, "keyword-argument-error");
238SCM_SYMBOL (sym_debug, "debug");
239
240void
241scm_i_vm_print (SCM x, SCM port, scm_print_state *pstate)
242{
243 scm_puts ("#<vm ", port);
244 scm_uintprint (SCM_UNPACK (x), 16, port);
245 scm_puts (">", port);
246}
247
248static SCM
249really_make_boot_program (long nargs)
250{
251 SCM u8vec;
252 scm_t_uint8 text[] = { scm_op_mv_call, 0, 0, 0, 1,
253 scm_op_make_int8_1, scm_op_halt };
254 struct scm_objcode *bp;
255 SCM ret;
256
257 if (SCM_UNLIKELY (nargs > 255 || nargs < 0))
258 abort ();
259 text[1] = (scm_t_uint8)nargs;
260
261 bp = scm_malloc (sizeof (struct scm_objcode) + sizeof (text));
262 memcpy (SCM_C_OBJCODE_BASE (bp), text, sizeof (text));
263 bp->len = sizeof(text);
264 bp->metalen = 0;
265
266 u8vec = scm_c_take_bytevector ((scm_t_int8*)bp,
267 sizeof (struct scm_objcode) + sizeof (text));
268 ret = scm_make_program (scm_bytecode_to_objcode (u8vec),
269 SCM_BOOL_F, SCM_BOOL_F);
270 SCM_SET_CELL_WORD_0 (ret, SCM_CELL_WORD_0 (ret) | SCM_F_PROGRAM_IS_BOOT);
271
272 return ret;
273}
274#define NUM_BOOT_PROGS 8
275static SCM
276vm_make_boot_program (long nargs)
277{
278 static SCM programs[NUM_BOOT_PROGS] = { 0, };
279
280 if (SCM_UNLIKELY (!programs[0]))
281 {
282 int i;
283 for (i = 0; i < NUM_BOOT_PROGS; i++)
284 programs[i] = really_make_boot_program (i);
285 }
286
287 if (SCM_LIKELY (nargs < NUM_BOOT_PROGS))
288 return programs[nargs];
289 else
290 return really_make_boot_program (nargs);
291}
292
293\f
294/*
295 * VM
296 */
297
298static SCM
299resolve_variable (SCM what, SCM program_module)
300{
301 if (SCM_LIKELY (scm_is_symbol (what)))
302 {
303 if (SCM_LIKELY (scm_module_system_booted_p
304 && scm_is_true (program_module)))
305 /* might longjmp */
306 return scm_module_lookup (program_module, what);
307 else
308 {
309 SCM v = scm_sym2var (what, SCM_BOOL_F, SCM_BOOL_F);
310 if (scm_is_false (v))
311 scm_misc_error (NULL, "unbound variable: ~S", scm_list_1 (what));
312 else
313 return v;
314 }
315 }
316 else
317 {
318 SCM mod;
319 /* compilation of @ or @@
320 `what' is a three-element list: (MODNAME SYM INTERFACE?)
321 INTERFACE? is #t if we compiled @ or #f if we compiled @@
322 */
323 mod = scm_resolve_module (SCM_CAR (what));
324 if (scm_is_true (SCM_CADDR (what)))
325 mod = scm_module_public_interface (mod);
326 if (scm_is_false (mod))
327 scm_misc_error (NULL, "no such module: ~S",
328 scm_list_1 (SCM_CAR (what)));
329 /* might longjmp */
330 return scm_module_lookup (mod, SCM_CADR (what));
331 }
332}
333
334#define VM_DEFAULT_STACK_SIZE (64 * 1024)
335
336#define VM_NAME vm_regular_engine
337#define FUNC_NAME "vm-regular-engine"
338#define VM_ENGINE SCM_VM_REGULAR_ENGINE
339#include "vm-engine.c"
340#undef VM_NAME
341#undef FUNC_NAME
342#undef VM_ENGINE
343
344#define VM_NAME vm_debug_engine
345#define FUNC_NAME "vm-debug-engine"
346#define VM_ENGINE SCM_VM_DEBUG_ENGINE
347#include "vm-engine.c"
348#undef VM_NAME
349#undef FUNC_NAME
350#undef VM_ENGINE
351
352static const scm_t_vm_engine vm_engines[] =
353 { vm_regular_engine, vm_debug_engine };
354
355#ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
356
357/* The GC "kind" for the VM stack. */
358static int vm_stack_gc_kind;
359
360#endif
361
362static SCM
363make_vm (void)
364#define FUNC_NAME "make_vm"
365{
366 int i;
367 struct scm_vm *vp;
368
369 vp = scm_gc_malloc (sizeof (struct scm_vm), "vm");
370
371 vp->stack_size = VM_DEFAULT_STACK_SIZE;
372
373#ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
374 vp->stack_base = (SCM *)
375 GC_generic_malloc (vp->stack_size * sizeof (SCM), vm_stack_gc_kind);
376
377 /* Keep a pointer to VP so that `vm_stack_mark ()' can know what the stack
378 top is. */
379 *vp->stack_base = PTR2SCM (vp);
380 vp->stack_base++;
381 vp->stack_size--;
382#else
383 vp->stack_base = scm_gc_malloc (vp->stack_size * sizeof (SCM),
384 "stack-base");
385#endif
386
387#ifdef VM_ENABLE_STACK_NULLING
388 memset (vp->stack_base, 0, vp->stack_size * sizeof (SCM));
389#endif
390 vp->stack_limit = vp->stack_base + vp->stack_size;
391 vp->ip = NULL;
392 vp->sp = vp->stack_base - 1;
393 vp->fp = NULL;
394 vp->engine = SCM_VM_DEBUG_ENGINE;
395 vp->options = SCM_EOL;
396 vp->trace_level = 0;
397 for (i = 0; i < SCM_VM_NUM_HOOKS; i++)
398 vp->hooks[i] = SCM_BOOL_F;
399 vp->cookie = 0;
400 return scm_cell (scm_tc7_vm, (scm_t_bits)vp);
401}
402#undef FUNC_NAME
403
404#ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
405
406/* Mark the VM stack region between its base and its current top. */
407static struct GC_ms_entry *
408vm_stack_mark (GC_word *addr, struct GC_ms_entry *mark_stack_ptr,
409 struct GC_ms_entry *mark_stack_limit, GC_word env)
410{
411 GC_word *word;
412 const struct scm_vm *vm;
413
414 /* The first word of the VM stack should contain a pointer to the
415 corresponding VM. */
416 vm = * ((struct scm_vm **) addr);
417
418 if (vm == NULL
419 || (SCM *) addr != vm->stack_base - 1
420 || vm->stack_limit - vm->stack_base != vm->stack_size)
421 /* ADDR must be a pointer to a free-list element, which we must ignore
422 (see warning in <gc/gc_mark.h>). */
423 return mark_stack_ptr;
424
425 for (word = (GC_word *) vm->stack_base; word <= (GC_word *) vm->sp; word++)
426 mark_stack_ptr = GC_MARK_AND_PUSH ((* (GC_word **) word),
427 mark_stack_ptr, mark_stack_limit,
428 NULL);
429
430 return mark_stack_ptr;
431}
432
433#endif /* VM_ENABLE_PRECISE_STACK_GC_SCAN */
434
435
436SCM
437scm_c_vm_run (SCM vm, SCM program, SCM *argv, int nargs)
438{
439 struct scm_vm *vp = SCM_VM_DATA (vm);
440 return vm_engines[vp->engine](vm, program, argv, nargs);
441}
442
443SCM_DEFINE (scm_vm_apply, "vm-apply", 3, 0, 0,
444 (SCM vm, SCM program, SCM args),
445 "")
446#define FUNC_NAME s_scm_vm_apply
447{
448 SCM *argv;
449 int i, nargs;
450
451 SCM_VALIDATE_VM (1, vm);
452 SCM_VALIDATE_PROC (2, program);
453
454 nargs = scm_ilength (args);
455 if (SCM_UNLIKELY (nargs < 0))
456 scm_wrong_type_arg_msg (FUNC_NAME, 3, args, "list");
457
458 argv = alloca(nargs * sizeof(SCM));
459 for (i = 0; i < nargs; i++)
460 {
461 argv[i] = SCM_CAR (args);
462 args = SCM_CDR (args);
463 }
464
465 return scm_c_vm_run (vm, program, argv, nargs);
466}
467#undef FUNC_NAME
468
469SCM
470scm_vm_call_with_new_stack (SCM vm, SCM thunk, SCM id)
471{
472 return scm_c_vm_run (vm, thunk, NULL, 0);
473}
474
475/* Scheme interface */
476
477SCM_DEFINE (scm_vm_version, "vm-version", 0, 0, 0,
478 (void),
479 "")
480#define FUNC_NAME s_scm_vm_version
481{
482 return scm_from_locale_string (PACKAGE_VERSION);
483}
484#undef FUNC_NAME
485
486SCM_DEFINE (scm_the_vm, "the-vm", 0, 0, 0,
487 (void),
488 "")
489#define FUNC_NAME s_scm_the_vm
490{
491 scm_i_thread *t = SCM_I_CURRENT_THREAD;
492
493 if (SCM_UNLIKELY (scm_is_false ((t->vm))))
494 t->vm = make_vm ();
495
496 return t->vm;
497}
498#undef FUNC_NAME
499
500
501SCM_DEFINE (scm_vm_p, "vm?", 1, 0, 0,
502 (SCM obj),
503 "")
504#define FUNC_NAME s_scm_vm_p
505{
506 return scm_from_bool (SCM_VM_P (obj));
507}
508#undef FUNC_NAME
509
510SCM_DEFINE (scm_make_vm, "make-vm", 0, 0, 0,
511 (void),
512 "")
513#define FUNC_NAME s_scm_make_vm,
514{
515 return make_vm ();
516}
517#undef FUNC_NAME
518
519SCM_DEFINE (scm_vm_ip, "vm:ip", 1, 0, 0,
520 (SCM vm),
521 "")
522#define FUNC_NAME s_scm_vm_ip
523{
524 SCM_VALIDATE_VM (1, vm);
525 return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->ip);
526}
527#undef FUNC_NAME
528
529SCM_DEFINE (scm_vm_sp, "vm:sp", 1, 0, 0,
530 (SCM vm),
531 "")
532#define FUNC_NAME s_scm_vm_sp
533{
534 SCM_VALIDATE_VM (1, vm);
535 return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->sp);
536}
537#undef FUNC_NAME
538
539SCM_DEFINE (scm_vm_fp, "vm:fp", 1, 0, 0,
540 (SCM vm),
541 "")
542#define FUNC_NAME s_scm_vm_fp
543{
544 SCM_VALIDATE_VM (1, vm);
545 return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->fp);
546}
547#undef FUNC_NAME
548
549#define VM_DEFINE_HOOK(n) \
550{ \
551 struct scm_vm *vp; \
552 SCM_VALIDATE_VM (1, vm); \
553 vp = SCM_VM_DATA (vm); \
554 if (scm_is_false (vp->hooks[n])) \
555 vp->hooks[n] = scm_make_hook (SCM_I_MAKINUM (1)); \
556 return vp->hooks[n]; \
557}
558
559SCM_DEFINE (scm_vm_boot_hook, "vm-boot-hook", 1, 0, 0,
560 (SCM vm),
561 "")
562#define FUNC_NAME s_scm_vm_boot_hook
563{
564 VM_DEFINE_HOOK (SCM_VM_BOOT_HOOK);
565}
566#undef FUNC_NAME
567
568SCM_DEFINE (scm_vm_halt_hook, "vm-halt-hook", 1, 0, 0,
569 (SCM vm),
570 "")
571#define FUNC_NAME s_scm_vm_halt_hook
572{
573 VM_DEFINE_HOOK (SCM_VM_HALT_HOOK);
574}
575#undef FUNC_NAME
576
577SCM_DEFINE (scm_vm_next_hook, "vm-next-hook", 1, 0, 0,
578 (SCM vm),
579 "")
580#define FUNC_NAME s_scm_vm_next_hook
581{
582 VM_DEFINE_HOOK (SCM_VM_NEXT_HOOK);
583}
584#undef FUNC_NAME
585
586SCM_DEFINE (scm_vm_break_hook, "vm-break-hook", 1, 0, 0,
587 (SCM vm),
588 "")
589#define FUNC_NAME s_scm_vm_break_hook
590{
591 VM_DEFINE_HOOK (SCM_VM_BREAK_HOOK);
592}
593#undef FUNC_NAME
594
595SCM_DEFINE (scm_vm_enter_hook, "vm-enter-hook", 1, 0, 0,
596 (SCM vm),
597 "")
598#define FUNC_NAME s_scm_vm_enter_hook
599{
600 VM_DEFINE_HOOK (SCM_VM_ENTER_HOOK);
601}
602#undef FUNC_NAME
603
604SCM_DEFINE (scm_vm_apply_hook, "vm-apply-hook", 1, 0, 0,
605 (SCM vm),
606 "")
607#define FUNC_NAME s_scm_vm_apply_hook
608{
609 VM_DEFINE_HOOK (SCM_VM_APPLY_HOOK);
610}
611#undef FUNC_NAME
612
613SCM_DEFINE (scm_vm_exit_hook, "vm-exit-hook", 1, 0, 0,
614 (SCM vm),
615 "")
616#define FUNC_NAME s_scm_vm_exit_hook
617{
618 VM_DEFINE_HOOK (SCM_VM_EXIT_HOOK);
619}
620#undef FUNC_NAME
621
622SCM_DEFINE (scm_vm_return_hook, "vm-return-hook", 1, 0, 0,
623 (SCM vm),
624 "")
625#define FUNC_NAME s_scm_vm_return_hook
626{
627 VM_DEFINE_HOOK (SCM_VM_RETURN_HOOK);
628}
629#undef FUNC_NAME
630
631SCM_DEFINE (scm_vm_option, "vm-option", 2, 0, 0,
632 (SCM vm, SCM key),
633 "")
634#define FUNC_NAME s_scm_vm_option
635{
636 SCM_VALIDATE_VM (1, vm);
637 return scm_assq_ref (SCM_VM_DATA (vm)->options, key);
638}
639#undef FUNC_NAME
640
641SCM_DEFINE (scm_set_vm_option_x, "set-vm-option!", 3, 0, 0,
642 (SCM vm, SCM key, SCM val),
643 "")
644#define FUNC_NAME s_scm_set_vm_option_x
645{
646 SCM_VALIDATE_VM (1, vm);
647 SCM_VM_DATA (vm)->options
648 = scm_assq_set_x (SCM_VM_DATA (vm)->options, key, val);
649 return SCM_UNSPECIFIED;
650}
651#undef FUNC_NAME
652
653SCM_DEFINE (scm_vm_trace_level, "vm-trace-level", 1, 0, 0,
654 (SCM vm),
655 "")
656#define FUNC_NAME s_scm_vm_trace_level
657{
658 SCM_VALIDATE_VM (1, vm);
659 return scm_from_int (SCM_VM_DATA (vm)->trace_level);
660}
661#undef FUNC_NAME
662
663SCM_DEFINE (scm_set_vm_trace_level_x, "set-vm-trace-level!", 2, 0, 0,
664 (SCM vm, SCM level),
665 "")
666#define FUNC_NAME s_scm_set_vm_trace_level_x
667{
668 SCM_VALIDATE_VM (1, vm);
669 SCM_VM_DATA (vm)->trace_level = scm_to_int (level);
670 return SCM_UNSPECIFIED;
671}
672#undef FUNC_NAME
673
674\f
675/*
676 * Initialize
677 */
678
679SCM scm_load_compiled_with_vm (SCM file)
680{
681 SCM program = scm_make_program (scm_load_objcode (file),
682 SCM_BOOL_F, SCM_BOOL_F);
683
684 return scm_c_vm_run (scm_the_vm (), program, NULL, 0);
685}
686
687void
688scm_bootstrap_vm (void)
689{
690 scm_c_register_extension ("libguile", "scm_init_vm",
691 (scm_t_extension_init_func)scm_init_vm, NULL);
692
693#ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
694 vm_stack_gc_kind =
695 GC_new_kind (GC_new_free_list (),
696 GC_MAKE_PROC (GC_new_proc (vm_stack_mark), 0),
697 0, 1);
698
699#endif
700}
701
702void
703scm_init_vm (void)
704{
705#ifndef SCM_MAGIC_SNARFER
706#include "libguile/vm.x"
707#endif
708}
709
710/*
711 Local Variables:
712 c-file-style: "gnu"
713 End:
714*/