rewinding prompts works
[bpt/guile.git] / libguile / vm.c
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
75 void
76 scm_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 */
94 SCM
95 scm_i_vm_capture_stack (SCM *stack_base, SCM *fp, SCM *sp, scm_t_uint8 *ra,
96 scm_t_uint8 *mvra, scm_t_uint32 flags)
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 p->flags = flags;
120 return scm_cell (scm_tc7_vm_cont, (scm_t_bits)p);
121 }
122
123 static void
124 vm_return_to_continuation (SCM vm, SCM cont, size_t n, SCM *argv)
125 {
126 struct scm_vm *vp;
127 struct scm_vm_cont *cp;
128 SCM *argv_copy;
129
130 argv_copy = alloca (n * sizeof(SCM));
131 memcpy (argv_copy, argv, n * sizeof(SCM));
132
133 vp = SCM_VM_DATA (vm);
134 cp = SCM_VM_CONT_DATA (cont);
135
136 if (n == 0 && !cp->mvra)
137 scm_misc_error (NULL, "Too few values returned to continuation",
138 SCM_EOL);
139
140 if (vp->stack_size < cp->stack_size + n + 1)
141 scm_misc_error ("vm-engine", "not enough space to reinstate continuation",
142 scm_list_2 (vm, cont));
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
177 SCM
178 scm_i_vm_capture_continuation (SCM vm)
179 {
180 struct scm_vm *vp = SCM_VM_DATA (vm);
181 return scm_i_vm_capture_stack (vp->stack_base, vp->fp, vp->sp, vp->ip, NULL, 0);
182 }
183
184 static void
185 vm_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
204 static void vm_abort (SCM vm, size_t n, scm_t_int64 cookie) SCM_NORETURN;
205 static void
206 vm_abort (SCM vm, size_t n, scm_t_int64 vm_cookie)
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 scm_misc_error ("vm-engine", "tail values to abort should be a list",
218 scm_list_1 (tail));
219
220 tag = SCM_VM_DATA (vm)->sp[-n];
221 argv = alloca ((n + tail_len) * sizeof (SCM));
222 for (i = 0; i < n; i++)
223 argv[i] = SCM_VM_DATA (vm)->sp[-(n-1-i)];
224 for (; i < n + tail_len; i++, tail = scm_cdr (tail))
225 argv[i] = scm_car (tail);
226 /* NULLSTACK (n + 1) */
227 SCM_VM_DATA (vm)->sp -= n + 1;
228
229 scm_c_abort (vm, tag, n + tail_len, argv, vm_cookie);
230 }
231
232 static void
233 vm_reinstate_partial_continuation (SCM vm, SCM cont, SCM intwinds,
234 size_t n, SCM *argv, scm_t_int64 vm_cookie)
235 {
236 struct scm_vm *vp;
237 struct scm_vm_cont *cp;
238 SCM *argv_copy, *base;
239 size_t i;
240
241 argv_copy = alloca (n * sizeof(SCM));
242 memcpy (argv_copy, argv, n * sizeof(SCM));
243
244 vp = SCM_VM_DATA (vm);
245 cp = SCM_VM_CONT_DATA (cont);
246 base = SCM_FRAME_UPPER_ADDRESS (vp->fp) + 1;
247
248 #define RELOC(scm_p) (scm_p + cp->reloc + (base - cp->stack_base))
249
250 if ((base - vp->stack_base) + cp->stack_size + n + 1 > vp->stack_size)
251 scm_misc_error ("vm-engine",
252 "not enough space to instate partial continuation",
253 scm_list_2 (vm, cont));
254
255 memcpy (base, cp->stack_base, cp->stack_size * sizeof (SCM));
256
257 /* now relocate frame pointers */
258 {
259 SCM *fp;
260 for (fp = RELOC (cp->fp);
261 SCM_FRAME_LOWER_ADDRESS (fp) > base;
262 fp = SCM_FRAME_DYNAMIC_LINK (fp))
263 SCM_FRAME_SET_DYNAMIC_LINK (fp, RELOC (SCM_FRAME_DYNAMIC_LINK (fp)));
264 }
265
266 vp->sp = base - 1 + cp->stack_size;
267 vp->fp = RELOC (cp->fp);
268 vp->ip = cp->mvra;
269
270 /* now push args. ip is in a MV context. */
271 for (i = 0; i < n; i++)
272 {
273 vp->sp++;
274 *vp->sp = argv_copy[i];
275 }
276 vp->sp++;
277 *vp->sp = scm_from_size_t (n);
278
279 /* Finally, rewind the dynamic state.
280
281 We have to treat prompts specially, because we could be rewinding the
282 dynamic state from a different thread, or just a different position on the
283 C and/or VM stack -- so we need to reset the jump buffers so that an abort
284 comes back here, with appropriately adjusted sp and fp registers. */
285 {
286 long delta = 0;
287 SCM newwinds = scm_i_dynwinds ();
288 for (; scm_is_pair (intwinds); intwinds = scm_cdr (intwinds), delta--)
289 {
290 SCM x = scm_car (intwinds);
291 if (SCM_PROMPT_P (x))
292 /* the jmpbuf will be reset by our caller */
293 x = scm_c_make_prompt (SCM_PROMPT_TAG (x),
294 RELOC (SCM_PROMPT_REGISTERS (x)->fp),
295 RELOC (SCM_PROMPT_REGISTERS (x)->sp),
296 SCM_PROMPT_REGISTERS (x)->ip,
297 SCM_PROMPT_ESCAPE_P (x),
298 vm_cookie,
299 newwinds);
300 newwinds = scm_cons (x, newwinds);
301 }
302 scm_dowinds (newwinds, delta);
303 }
304 #undef RELOC
305 }
306
307 \f
308 /*
309 * VM Internal functions
310 */
311
312 /* Unfortunately we can't snarf these: snarfed things are only loaded up from
313 (system vm vm), which might not be loaded before an error happens. */
314 static SCM sym_vm_run, sym_vm_error, sym_keyword_argument_error, sym_debug;
315
316 void
317 scm_i_vm_print (SCM x, SCM port, scm_print_state *pstate)
318 {
319 scm_puts ("#<vm ", port);
320 scm_uintprint (SCM_UNPACK (x), 16, port);
321 scm_puts (">", port);
322 }
323
324 static SCM
325 really_make_boot_program (long nargs)
326 {
327 SCM u8vec;
328 scm_t_uint8 text[] = { scm_op_mv_call, 0, 0, 0, 1,
329 scm_op_make_int8_1, scm_op_halt };
330 struct scm_objcode *bp;
331 SCM ret;
332
333 if (SCM_UNLIKELY (nargs > 255 || nargs < 0))
334 scm_misc_error ("vm-engine", "too many args when making boot procedure",
335 scm_list_1 (scm_from_long (nargs)));
336
337 text[1] = (scm_t_uint8)nargs;
338
339 bp = scm_malloc (sizeof (struct scm_objcode) + sizeof (text));
340 memcpy (SCM_C_OBJCODE_BASE (bp), text, sizeof (text));
341 bp->len = sizeof(text);
342 bp->metalen = 0;
343
344 u8vec = scm_c_take_bytevector ((scm_t_int8*)bp,
345 sizeof (struct scm_objcode) + sizeof (text));
346 ret = scm_make_program (scm_bytecode_to_objcode (u8vec),
347 SCM_BOOL_F, SCM_BOOL_F);
348 SCM_SET_CELL_WORD_0 (ret, SCM_CELL_WORD_0 (ret) | SCM_F_PROGRAM_IS_BOOT);
349
350 return ret;
351 }
352 #define NUM_BOOT_PROGS 8
353 static SCM
354 vm_make_boot_program (long nargs)
355 {
356 static SCM programs[NUM_BOOT_PROGS] = { 0, };
357
358 if (SCM_UNLIKELY (!programs[0]))
359 {
360 int i;
361 for (i = 0; i < NUM_BOOT_PROGS; i++)
362 programs[i] = really_make_boot_program (i);
363 }
364
365 if (SCM_LIKELY (nargs < NUM_BOOT_PROGS))
366 return programs[nargs];
367 else
368 return really_make_boot_program (nargs);
369 }
370
371 \f
372 /*
373 * VM
374 */
375
376 static SCM
377 resolve_variable (SCM what, SCM program_module)
378 {
379 if (SCM_LIKELY (scm_is_symbol (what)))
380 {
381 if (SCM_LIKELY (scm_module_system_booted_p
382 && scm_is_true (program_module)))
383 /* might longjmp */
384 return scm_module_lookup (program_module, what);
385 else
386 {
387 SCM v = scm_sym2var (what, SCM_BOOL_F, SCM_BOOL_F);
388 if (scm_is_false (v))
389 scm_misc_error (NULL, "unbound variable: ~S", scm_list_1 (what));
390 else
391 return v;
392 }
393 }
394 else
395 {
396 SCM mod;
397 /* compilation of @ or @@
398 `what' is a three-element list: (MODNAME SYM INTERFACE?)
399 INTERFACE? is #t if we compiled @ or #f if we compiled @@
400 */
401 mod = scm_resolve_module (SCM_CAR (what));
402 if (scm_is_true (SCM_CADDR (what)))
403 mod = scm_module_public_interface (mod);
404 if (scm_is_false (mod))
405 scm_misc_error (NULL, "no such module: ~S",
406 scm_list_1 (SCM_CAR (what)));
407 /* might longjmp */
408 return scm_module_lookup (mod, SCM_CADR (what));
409 }
410 }
411
412 #define VM_DEFAULT_STACK_SIZE (64 * 1024)
413
414 #define VM_NAME vm_regular_engine
415 #define FUNC_NAME "vm-regular-engine"
416 #define VM_ENGINE SCM_VM_REGULAR_ENGINE
417 #include "vm-engine.c"
418 #undef VM_NAME
419 #undef FUNC_NAME
420 #undef VM_ENGINE
421
422 #define VM_NAME vm_debug_engine
423 #define FUNC_NAME "vm-debug-engine"
424 #define VM_ENGINE SCM_VM_DEBUG_ENGINE
425 #include "vm-engine.c"
426 #undef VM_NAME
427 #undef FUNC_NAME
428 #undef VM_ENGINE
429
430 static const scm_t_vm_engine vm_engines[] =
431 { vm_regular_engine, vm_debug_engine };
432
433 #ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
434
435 /* The GC "kind" for the VM stack. */
436 static int vm_stack_gc_kind;
437
438 #endif
439
440 static SCM
441 make_vm (void)
442 #define FUNC_NAME "make_vm"
443 {
444 int i;
445 struct scm_vm *vp;
446
447 vp = scm_gc_malloc (sizeof (struct scm_vm), "vm");
448
449 vp->stack_size = VM_DEFAULT_STACK_SIZE;
450
451 #ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
452 vp->stack_base = (SCM *)
453 GC_generic_malloc (vp->stack_size * sizeof (SCM), vm_stack_gc_kind);
454
455 /* Keep a pointer to VP so that `vm_stack_mark ()' can know what the stack
456 top is. */
457 *vp->stack_base = PTR2SCM (vp);
458 vp->stack_base++;
459 vp->stack_size--;
460 #else
461 vp->stack_base = scm_gc_malloc (vp->stack_size * sizeof (SCM),
462 "stack-base");
463 #endif
464
465 #ifdef VM_ENABLE_STACK_NULLING
466 memset (vp->stack_base, 0, vp->stack_size * sizeof (SCM));
467 #endif
468 vp->stack_limit = vp->stack_base + vp->stack_size;
469 vp->ip = NULL;
470 vp->sp = vp->stack_base - 1;
471 vp->fp = NULL;
472 vp->engine = SCM_VM_DEBUG_ENGINE;
473 vp->options = SCM_EOL;
474 vp->trace_level = 0;
475 for (i = 0; i < SCM_VM_NUM_HOOKS; i++)
476 vp->hooks[i] = SCM_BOOL_F;
477 vp->cookie = 0;
478 return scm_cell (scm_tc7_vm, (scm_t_bits)vp);
479 }
480 #undef FUNC_NAME
481
482 #ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
483
484 /* Mark the VM stack region between its base and its current top. */
485 static struct GC_ms_entry *
486 vm_stack_mark (GC_word *addr, struct GC_ms_entry *mark_stack_ptr,
487 struct GC_ms_entry *mark_stack_limit, GC_word env)
488 {
489 GC_word *word;
490 const struct scm_vm *vm;
491
492 /* The first word of the VM stack should contain a pointer to the
493 corresponding VM. */
494 vm = * ((struct scm_vm **) addr);
495
496 if (vm == NULL
497 || (SCM *) addr != vm->stack_base - 1
498 || vm->stack_limit - vm->stack_base != vm->stack_size)
499 /* ADDR must be a pointer to a free-list element, which we must ignore
500 (see warning in <gc/gc_mark.h>). */
501 return mark_stack_ptr;
502
503 for (word = (GC_word *) vm->stack_base; word <= (GC_word *) vm->sp; word++)
504 mark_stack_ptr = GC_MARK_AND_PUSH ((* (GC_word **) word),
505 mark_stack_ptr, mark_stack_limit,
506 NULL);
507
508 return mark_stack_ptr;
509 }
510
511 #endif /* VM_ENABLE_PRECISE_STACK_GC_SCAN */
512
513
514 SCM
515 scm_c_vm_run (SCM vm, SCM program, SCM *argv, int nargs)
516 {
517 struct scm_vm *vp = SCM_VM_DATA (vm);
518 return vm_engines[vp->engine](vm, program, argv, nargs);
519 }
520
521 SCM_DEFINE (scm_vm_apply, "vm-apply", 3, 0, 0,
522 (SCM vm, SCM program, SCM args),
523 "")
524 #define FUNC_NAME s_scm_vm_apply
525 {
526 SCM *argv;
527 int i, nargs;
528
529 SCM_VALIDATE_VM (1, vm);
530 SCM_VALIDATE_PROC (2, program);
531
532 nargs = scm_ilength (args);
533 if (SCM_UNLIKELY (nargs < 0))
534 scm_wrong_type_arg_msg (FUNC_NAME, 3, args, "list");
535
536 argv = alloca(nargs * sizeof(SCM));
537 for (i = 0; i < nargs; i++)
538 {
539 argv[i] = SCM_CAR (args);
540 args = SCM_CDR (args);
541 }
542
543 return scm_c_vm_run (vm, program, argv, nargs);
544 }
545 #undef FUNC_NAME
546
547 SCM
548 scm_vm_call_with_new_stack (SCM vm, SCM thunk, SCM id)
549 {
550 return scm_c_vm_run (vm, thunk, NULL, 0);
551 }
552
553 /* Scheme interface */
554
555 SCM_DEFINE (scm_vm_version, "vm-version", 0, 0, 0,
556 (void),
557 "")
558 #define FUNC_NAME s_scm_vm_version
559 {
560 return scm_from_locale_string (PACKAGE_VERSION);
561 }
562 #undef FUNC_NAME
563
564 SCM_DEFINE (scm_the_vm, "the-vm", 0, 0, 0,
565 (void),
566 "")
567 #define FUNC_NAME s_scm_the_vm
568 {
569 scm_i_thread *t = SCM_I_CURRENT_THREAD;
570
571 if (SCM_UNLIKELY (scm_is_false ((t->vm))))
572 t->vm = make_vm ();
573
574 return t->vm;
575 }
576 #undef FUNC_NAME
577
578
579 SCM_DEFINE (scm_vm_p, "vm?", 1, 0, 0,
580 (SCM obj),
581 "")
582 #define FUNC_NAME s_scm_vm_p
583 {
584 return scm_from_bool (SCM_VM_P (obj));
585 }
586 #undef FUNC_NAME
587
588 SCM_DEFINE (scm_make_vm, "make-vm", 0, 0, 0,
589 (void),
590 "")
591 #define FUNC_NAME s_scm_make_vm,
592 {
593 return make_vm ();
594 }
595 #undef FUNC_NAME
596
597 SCM_DEFINE (scm_vm_ip, "vm:ip", 1, 0, 0,
598 (SCM vm),
599 "")
600 #define FUNC_NAME s_scm_vm_ip
601 {
602 SCM_VALIDATE_VM (1, vm);
603 return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->ip);
604 }
605 #undef FUNC_NAME
606
607 SCM_DEFINE (scm_vm_sp, "vm:sp", 1, 0, 0,
608 (SCM vm),
609 "")
610 #define FUNC_NAME s_scm_vm_sp
611 {
612 SCM_VALIDATE_VM (1, vm);
613 return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->sp);
614 }
615 #undef FUNC_NAME
616
617 SCM_DEFINE (scm_vm_fp, "vm:fp", 1, 0, 0,
618 (SCM vm),
619 "")
620 #define FUNC_NAME s_scm_vm_fp
621 {
622 SCM_VALIDATE_VM (1, vm);
623 return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->fp);
624 }
625 #undef FUNC_NAME
626
627 #define VM_DEFINE_HOOK(n) \
628 { \
629 struct scm_vm *vp; \
630 SCM_VALIDATE_VM (1, vm); \
631 vp = SCM_VM_DATA (vm); \
632 if (scm_is_false (vp->hooks[n])) \
633 vp->hooks[n] = scm_make_hook (SCM_I_MAKINUM (1)); \
634 return vp->hooks[n]; \
635 }
636
637 SCM_DEFINE (scm_vm_boot_hook, "vm-boot-hook", 1, 0, 0,
638 (SCM vm),
639 "")
640 #define FUNC_NAME s_scm_vm_boot_hook
641 {
642 VM_DEFINE_HOOK (SCM_VM_BOOT_HOOK);
643 }
644 #undef FUNC_NAME
645
646 SCM_DEFINE (scm_vm_halt_hook, "vm-halt-hook", 1, 0, 0,
647 (SCM vm),
648 "")
649 #define FUNC_NAME s_scm_vm_halt_hook
650 {
651 VM_DEFINE_HOOK (SCM_VM_HALT_HOOK);
652 }
653 #undef FUNC_NAME
654
655 SCM_DEFINE (scm_vm_next_hook, "vm-next-hook", 1, 0, 0,
656 (SCM vm),
657 "")
658 #define FUNC_NAME s_scm_vm_next_hook
659 {
660 VM_DEFINE_HOOK (SCM_VM_NEXT_HOOK);
661 }
662 #undef FUNC_NAME
663
664 SCM_DEFINE (scm_vm_break_hook, "vm-break-hook", 1, 0, 0,
665 (SCM vm),
666 "")
667 #define FUNC_NAME s_scm_vm_break_hook
668 {
669 VM_DEFINE_HOOK (SCM_VM_BREAK_HOOK);
670 }
671 #undef FUNC_NAME
672
673 SCM_DEFINE (scm_vm_enter_hook, "vm-enter-hook", 1, 0, 0,
674 (SCM vm),
675 "")
676 #define FUNC_NAME s_scm_vm_enter_hook
677 {
678 VM_DEFINE_HOOK (SCM_VM_ENTER_HOOK);
679 }
680 #undef FUNC_NAME
681
682 SCM_DEFINE (scm_vm_apply_hook, "vm-apply-hook", 1, 0, 0,
683 (SCM vm),
684 "")
685 #define FUNC_NAME s_scm_vm_apply_hook
686 {
687 VM_DEFINE_HOOK (SCM_VM_APPLY_HOOK);
688 }
689 #undef FUNC_NAME
690
691 SCM_DEFINE (scm_vm_exit_hook, "vm-exit-hook", 1, 0, 0,
692 (SCM vm),
693 "")
694 #define FUNC_NAME s_scm_vm_exit_hook
695 {
696 VM_DEFINE_HOOK (SCM_VM_EXIT_HOOK);
697 }
698 #undef FUNC_NAME
699
700 SCM_DEFINE (scm_vm_return_hook, "vm-return-hook", 1, 0, 0,
701 (SCM vm),
702 "")
703 #define FUNC_NAME s_scm_vm_return_hook
704 {
705 VM_DEFINE_HOOK (SCM_VM_RETURN_HOOK);
706 }
707 #undef FUNC_NAME
708
709 SCM_DEFINE (scm_vm_option, "vm-option", 2, 0, 0,
710 (SCM vm, SCM key),
711 "")
712 #define FUNC_NAME s_scm_vm_option
713 {
714 SCM_VALIDATE_VM (1, vm);
715 return scm_assq_ref (SCM_VM_DATA (vm)->options, key);
716 }
717 #undef FUNC_NAME
718
719 SCM_DEFINE (scm_set_vm_option_x, "set-vm-option!", 3, 0, 0,
720 (SCM vm, SCM key, SCM val),
721 "")
722 #define FUNC_NAME s_scm_set_vm_option_x
723 {
724 SCM_VALIDATE_VM (1, vm);
725 SCM_VM_DATA (vm)->options
726 = scm_assq_set_x (SCM_VM_DATA (vm)->options, key, val);
727 return SCM_UNSPECIFIED;
728 }
729 #undef FUNC_NAME
730
731 SCM_DEFINE (scm_vm_trace_level, "vm-trace-level", 1, 0, 0,
732 (SCM vm),
733 "")
734 #define FUNC_NAME s_scm_vm_trace_level
735 {
736 SCM_VALIDATE_VM (1, vm);
737 return scm_from_int (SCM_VM_DATA (vm)->trace_level);
738 }
739 #undef FUNC_NAME
740
741 SCM_DEFINE (scm_set_vm_trace_level_x, "set-vm-trace-level!", 2, 0, 0,
742 (SCM vm, SCM level),
743 "")
744 #define FUNC_NAME s_scm_set_vm_trace_level_x
745 {
746 SCM_VALIDATE_VM (1, vm);
747 SCM_VM_DATA (vm)->trace_level = scm_to_int (level);
748 return SCM_UNSPECIFIED;
749 }
750 #undef FUNC_NAME
751
752 \f
753 /*
754 * Initialize
755 */
756
757 SCM scm_load_compiled_with_vm (SCM file)
758 {
759 SCM program = scm_make_program (scm_load_objcode (file),
760 SCM_BOOL_F, SCM_BOOL_F);
761
762 return scm_c_vm_run (scm_the_vm (), program, NULL, 0);
763 }
764
765 void
766 scm_bootstrap_vm (void)
767 {
768 scm_c_register_extension ("libguile", "scm_init_vm",
769 (scm_t_extension_init_func)scm_init_vm, NULL);
770
771 sym_vm_run = scm_from_locale_symbol ("vm-run");
772 sym_vm_error = scm_from_locale_symbol ("vm-error");
773 sym_keyword_argument_error = scm_from_locale_symbol ("keyword-argument-error");
774 sym_debug = scm_from_locale_symbol ("debug");
775
776 #ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
777 vm_stack_gc_kind =
778 GC_new_kind (GC_new_free_list (),
779 GC_MAKE_PROC (GC_new_proc (vm_stack_mark), 0),
780 0, 1);
781
782 #endif
783 }
784
785 void
786 scm_init_vm (void)
787 {
788 #ifndef SCM_MAGIC_SNARFER
789 #include "libguile/vm.x"
790 #endif
791 }
792
793 /*
794 Local Variables:
795 c-file-style: "gnu"
796 End:
797 */