record IP in partial continuations
[bpt/guile.git] / libguile / vm.c
CommitLineData
a6029b97 1/* Copyright (C) 2001, 2009, 2010 Free Software Foundation, Inc.
a98cef7e 2 *
560b9c25 3 * This library is free software; you can redistribute it and/or
53befeb7
NJ
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.
a98cef7e 7 *
53befeb7
NJ
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
560b9c25
AW
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
a98cef7e 12 *
560b9c25
AW
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
53befeb7
NJ
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 * 02110-1301 USA
560b9c25 17 */
a98cef7e 18
13c47753
AW
19#if HAVE_CONFIG_H
20# include <config.h>
21#endif
22
da8b4747 23#include <stdlib.h>
6d14383e 24#include <alloca.h>
17e90c5e 25#include <string.h>
e3eb628d 26
1c44468d 27#include "libguile/bdw-gc.h"
e3eb628d
LC
28#include <gc/gc_mark.h>
29
560b9c25 30#include "_scm.h"
adaf86ec 31#include "control.h"
ac99cb0c 32#include "frames.h"
17e90c5e 33#include "instructions.h"
8f5cfc81 34#include "objcodes.h"
ac99cb0c 35#include "programs.h"
fb10a008 36#include "lang.h" /* NULL_OR_NIL_P */
a98cef7e
KN
37#include "vm.h"
38
a98cef7e
KN
39/* I sometimes use this for debugging. */
40#define vm_puts(OBJ) \
41{ \
22bcbe8c
AW
42 scm_display (OBJ, scm_current_error_port ()); \
43 scm_newline (scm_current_error_port ()); \
a98cef7e
KN
44}
45
11ea1aba
AW
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
616167fc 53 will ensure that assertions are enabled. Slows down the VM by about 30%. */
747a1635 54/* NB! If you enable this, search for NULLING in throw.c */
616167fc 55/* #define VM_ENABLE_STACK_NULLING */
11ea1aba 56
53e28ed9
AW
57/* #define VM_ENABLE_PARANOID_ASSERTIONS */
58
11ea1aba
AW
59#if defined (VM_ENABLE_STACK_NULLING) && !defined (VM_ENABLE_ASSERTIONS)
60#define VM_ENABLE_ASSERTIONS
61#endif
62
e3eb628d
LC
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
a98cef7e 70\f
a98cef7e
KN
71/*
72 * VM Continuation
73 */
74
6f3b0cc2
AW
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}
17e90c5e 82
d8873dfe
AW
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 */
cee1d22c
AW
94SCM
95scm_i_vm_capture_stack (SCM *stack_base, SCM *fp, SCM *sp, scm_t_uint8 *ra,
96 scm_t_uint8 *mvra, scm_t_uint32 flags)
a98cef7e 97{
d8873dfe
AW
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;
d8eeb67c
LC
102 p->stack_base = scm_gc_malloc (p->stack_size * sizeof (SCM),
103 "capture_vm_cont");
d8873dfe
AW
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)
66db076a
AW
109 if (!vp->sp[0] || vp->sp[1])
110 abort ();
11ea1aba
AW
111 memset (p->stack_base, 0, p->stack_size * sizeof (SCM));
112#endif
d8873dfe
AW
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;
cee1d22c 119 p->flags = flags;
6f3b0cc2 120 return scm_cell (scm_tc7_vm_cont, (scm_t_bits)p);
a98cef7e
KN
121}
122
123static void
d8873dfe 124vm_return_to_continuation (SCM vm, SCM cont, size_t n, SCM *argv)
a98cef7e 125{
d8873dfe
AW
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)
a98cef7e 141 {
17e90c5e 142 /* puts ("FIXME: Need to expand"); */
a98cef7e
KN
143 abort ();
144 }
11ea1aba
AW
145#ifdef VM_ENABLE_STACK_NULLING
146 {
d8873dfe 147 scm_t_ptrdiff nzero = (vp->sp - cp->sp);
11ea1aba 148 if (nzero > 0)
d8873dfe 149 memset (vp->stack_base + cp->stack_size, 0, nzero * sizeof (SCM));
66db076a
AW
150 /* actually nzero should always be negative, because vm_reset_stack will
151 unwind the stack to some point *below* this continuation */
11ea1aba
AW
152 }
153#endif
d8873dfe
AW
154 vp->sp = cp->sp;
155 vp->fp = cp->fp;
156 memcpy (vp->stack_base, cp->stack_base, cp->stack_size * sizeof (SCM));
bfffd258 157
d8873dfe
AW
158 if (n == 1 || !cp->mvra)
159 {
160 vp->ip = cp->ra;
161 vp->sp++;
162 *vp->sp = argv_copy[0];
163 }
164 else
165 {
166 size_t i;
167 for (i = 0; i < n; i++)
168 {
169 vp->sp++;
170 *vp->sp = argv_copy[i];
171 }
172 vp->sp++;
173 *vp->sp = scm_from_size_t (n);
174 vp->ip = cp->mvra;
175 }
176}
bfffd258 177
bfffd258 178SCM
269479e3 179scm_i_vm_capture_continuation (SCM vm)
bfffd258 180{
d8873dfe 181 struct scm_vm *vp = SCM_VM_DATA (vm);
cee1d22c 182 return scm_i_vm_capture_stack (vp->stack_base, vp->fp, vp->sp, vp->ip, NULL, 0);
a98cef7e
KN
183}
184
b1b942b7 185static void
7656f194 186vm_dispatch_hook (SCM vm, int hook_num)
b1b942b7 187{
7656f194
AW
188 struct scm_vm *vp;
189 SCM hook;
190 SCM frame;
b1b942b7 191
7656f194
AW
192 vp = SCM_VM_DATA (vm);
193 hook = vp->hooks[hook_num];
b1b942b7 194
7656f194
AW
195 if (SCM_LIKELY (scm_is_false (hook))
196 || scm_is_null (SCM_HOOK_PROCEDURES (hook)))
197 return;
198
199 vp->trace_level--;
200 frame = scm_c_make_frame (vm, vp->fp, vp->sp, vp->ip, 0);
201 scm_c_run_hookn (hook, &frame, 1);
202 vp->trace_level++;
b1b942b7
AW
203}
204
cee1d22c 205static void vm_abort (SCM vm, size_t n, scm_t_int64 cookie) SCM_NORETURN;
4f66bcde 206static void
cee1d22c 207vm_abort (SCM vm, size_t n, scm_t_int64 vm_cookie)
4f66bcde 208{
eaefabee 209 size_t i;
2d026f04
AW
210 ssize_t tail_len;
211 SCM tag, tail, *argv;
eaefabee 212
2d026f04
AW
213 /* FIXME: VM_ENABLE_STACK_NULLING */
214 tail = *(SCM_VM_DATA (vm)->sp--);
215 /* NULLSTACK (1) */
216 tail_len = scm_ilength (tail);
217 if (tail_len < 0)
218 abort ();
eaefabee 219 tag = SCM_VM_DATA (vm)->sp[-n];
2d026f04 220 argv = alloca ((n + tail_len) * sizeof (SCM));
eaefabee
AW
221 for (i = 0; i < n; i++)
222 argv[i] = SCM_VM_DATA (vm)->sp[-(n-1-i)];
2d026f04
AW
223 for (; i < n + tail_len; i++, tail = scm_cdr (tail))
224 argv[i] = scm_car (tail);
225 /* NULLSTACK (n + 1) */
eaefabee
AW
226 SCM_VM_DATA (vm)->sp -= n + 1;
227
cee1d22c
AW
228 scm_c_abort (vm, tag, n + tail_len, argv, vm_cookie);
229}
230
231static void
232vm_reinstate_partial_continuation (SCM vm, SCM vm_cont, SCM intwinds,
233 SCM extwinds)
234{
235 abort ();
4f66bcde
AW
236}
237
238\f
17e90c5e
KN
239/*
240 * VM Internal functions
241 */
242
f6a8e791
AW
243SCM_SYMBOL (sym_vm_run, "vm-run");
244SCM_SYMBOL (sym_vm_error, "vm-error");
245SCM_SYMBOL (sym_keyword_argument_error, "keyword-argument-error");
246SCM_SYMBOL (sym_debug, "debug");
17e90c5e 247
6f3b0cc2
AW
248void
249scm_i_vm_print (SCM x, SCM port, scm_print_state *pstate)
250{
251 scm_puts ("#<vm ", port);
252 scm_uintprint (SCM_UNPACK (x), 16, port);
253 scm_puts (">", port);
254}
255
2fda0242 256static SCM
d2d7acd5 257really_make_boot_program (long nargs)
2fda0242 258{
5bd047ce 259 SCM u8vec;
97fcf583
AW
260 scm_t_uint8 text[] = { scm_op_mv_call, 0, 0, 0, 1,
261 scm_op_make_int8_1, scm_op_halt };
28b119ee 262 struct scm_objcode *bp;
3b9e095b 263 SCM ret;
5bd047ce 264
53e28ed9 265 if (SCM_UNLIKELY (nargs > 255 || nargs < 0))
2fda0242 266 abort ();
28b119ee
AW
267 text[1] = (scm_t_uint8)nargs;
268
d7e7a02a 269 bp = scm_malloc (sizeof (struct scm_objcode) + sizeof (text));
3dbbe28d 270 memcpy (SCM_C_OBJCODE_BASE (bp), text, sizeof (text));
28b119ee
AW
271 bp->len = sizeof(text);
272 bp->metalen = 0;
28b119ee 273
7055591c
AW
274 u8vec = scm_c_take_bytevector ((scm_t_int8*)bp,
275 sizeof (struct scm_objcode) + sizeof (text));
5bd047ce 276 ret = scm_make_program (scm_bytecode_to_objcode (u8vec),
20d47c39 277 SCM_BOOL_F, SCM_BOOL_F);
ba20f78a 278 SCM_SET_CELL_WORD_0 (ret, SCM_CELL_WORD_0 (ret) | SCM_F_PROGRAM_IS_BOOT);
5bd047ce 279
3b9e095b 280 return ret;
2fda0242 281}
d2d7acd5
AW
282#define NUM_BOOT_PROGS 8
283static SCM
284vm_make_boot_program (long nargs)
285{
286 static SCM programs[NUM_BOOT_PROGS] = { 0, };
287
288 if (SCM_UNLIKELY (!programs[0]))
289 {
290 int i;
291 for (i = 0; i < NUM_BOOT_PROGS; i++)
f39448c5 292 programs[i] = really_make_boot_program (i);
d2d7acd5
AW
293 }
294
295 if (SCM_LIKELY (nargs < NUM_BOOT_PROGS))
296 return programs[nargs];
297 else
298 return really_make_boot_program (nargs);
299}
2fda0242 300
a98cef7e
KN
301\f
302/*
303 * VM
304 */
305
b7393ea1
AW
306static SCM
307resolve_variable (SCM what, SCM program_module)
308{
9bd48cb1 309 if (SCM_LIKELY (scm_is_symbol (what)))
b7393ea1
AW
310 {
311 if (SCM_LIKELY (scm_module_system_booted_p
312 && scm_is_true (program_module)))
313 /* might longjmp */
314 return scm_module_lookup (program_module, what);
315 else
316 {
317 SCM v = scm_sym2var (what, SCM_BOOL_F, SCM_BOOL_F);
318 if (scm_is_false (v))
319 scm_misc_error (NULL, "unbound variable: ~S", scm_list_1 (what));
320 else
321 return v;
322 }
323 }
324 else
325 {
326 SCM mod;
327 /* compilation of @ or @@
328 `what' is a three-element list: (MODNAME SYM INTERFACE?)
329 INTERFACE? is #t if we compiled @ or #f if we compiled @@
330 */
331 mod = scm_resolve_module (SCM_CAR (what));
332 if (scm_is_true (SCM_CADDR (what)))
333 mod = scm_module_public_interface (mod);
5c8cefe5 334 if (scm_is_false (mod))
b7393ea1
AW
335 scm_misc_error (NULL, "no such module: ~S",
336 scm_list_1 (SCM_CAR (what)));
337 /* might longjmp */
338 return scm_module_lookup (mod, SCM_CADR (what));
339 }
340}
341
51e9ba2f 342#define VM_DEFAULT_STACK_SIZE (64 * 1024)
17e90c5e 343
17e90c5e 344#define VM_NAME vm_regular_engine
6d14383e
AW
345#define FUNC_NAME "vm-regular-engine"
346#define VM_ENGINE SCM_VM_REGULAR_ENGINE
83495480 347#include "vm-engine.c"
17e90c5e 348#undef VM_NAME
6d14383e 349#undef FUNC_NAME
17e90c5e 350#undef VM_ENGINE
17e90c5e
KN
351
352#define VM_NAME vm_debug_engine
6d14383e
AW
353#define FUNC_NAME "vm-debug-engine"
354#define VM_ENGINE SCM_VM_DEBUG_ENGINE
83495480 355#include "vm-engine.c"
17e90c5e 356#undef VM_NAME
6d14383e 357#undef FUNC_NAME
17e90c5e
KN
358#undef VM_ENGINE
359
6d14383e
AW
360static const scm_t_vm_engine vm_engines[] =
361 { vm_regular_engine, vm_debug_engine };
362
e3eb628d
LC
363#ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
364
365/* The GC "kind" for the VM stack. */
366static int vm_stack_gc_kind;
367
368#endif
369
a98cef7e 370static SCM
17e90c5e
KN
371make_vm (void)
372#define FUNC_NAME "make_vm"
a98cef7e 373{
17e90c5e 374 int i;
7f991c7d 375 struct scm_vm *vp;
747a1635 376
7f991c7d 377 vp = scm_gc_malloc (sizeof (struct scm_vm), "vm");
d8eeb67c 378
3d5ee0cd 379 vp->stack_size = VM_DEFAULT_STACK_SIZE;
e3eb628d
LC
380
381#ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
4168aa46
TTN
382 vp->stack_base = (SCM *)
383 GC_generic_malloc (vp->stack_size * sizeof (SCM), vm_stack_gc_kind);
e3eb628d
LC
384
385 /* Keep a pointer to VP so that `vm_stack_mark ()' can know what the stack
386 top is. */
387 *vp->stack_base = PTR2SCM (vp);
388 vp->stack_base++;
389 vp->stack_size--;
390#else
d8eeb67c
LC
391 vp->stack_base = scm_gc_malloc (vp->stack_size * sizeof (SCM),
392 "stack-base");
e3eb628d
LC
393#endif
394
2bbe1533
AW
395#ifdef VM_ENABLE_STACK_NULLING
396 memset (vp->stack_base, 0, vp->stack_size * sizeof (SCM));
397#endif
75d315e1 398 vp->stack_limit = vp->stack_base + vp->stack_size;
3616e9e9
KN
399 vp->ip = NULL;
400 vp->sp = vp->stack_base - 1;
401 vp->fp = NULL;
6d14383e 402 vp->engine = SCM_VM_DEBUG_ENGINE;
3d5ee0cd 403 vp->options = SCM_EOL;
7656f194 404 vp->trace_level = 0;
17e90c5e 405 for (i = 0; i < SCM_VM_NUM_HOOKS; i++)
3d5ee0cd 406 vp->hooks[i] = SCM_BOOL_F;
2d026f04 407 vp->cookie = 0;
6f3b0cc2 408 return scm_cell (scm_tc7_vm, (scm_t_bits)vp);
a98cef7e 409}
17e90c5e 410#undef FUNC_NAME
a98cef7e 411
e3eb628d
LC
412#ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
413
414/* Mark the VM stack region between its base and its current top. */
415static struct GC_ms_entry *
416vm_stack_mark (GC_word *addr, struct GC_ms_entry *mark_stack_ptr,
417 struct GC_ms_entry *mark_stack_limit, GC_word env)
418{
419 GC_word *word;
420 const struct scm_vm *vm;
421
422 /* The first word of the VM stack should contain a pointer to the
423 corresponding VM. */
424 vm = * ((struct scm_vm **) addr);
425
8071c490
LC
426 if (vm == NULL
427 || (SCM *) addr != vm->stack_base - 1
78747ac6 428 || vm->stack_limit - vm->stack_base != vm->stack_size)
e3eb628d
LC
429 /* ADDR must be a pointer to a free-list element, which we must ignore
430 (see warning in <gc/gc_mark.h>). */
431 return mark_stack_ptr;
432
e3eb628d
LC
433 for (word = (GC_word *) vm->stack_base; word <= (GC_word *) vm->sp; word++)
434 mark_stack_ptr = GC_MARK_AND_PUSH ((* (GC_word **) word),
435 mark_stack_ptr, mark_stack_limit,
436 NULL);
437
438 return mark_stack_ptr;
439}
440
441#endif /* VM_ENABLE_PRECISE_STACK_GC_SCAN */
442
443
6d14383e 444SCM
4abef68f 445scm_c_vm_run (SCM vm, SCM program, SCM *argv, int nargs)
6d14383e 446{
4abef68f 447 struct scm_vm *vp = SCM_VM_DATA (vm);
7656f194 448 return vm_engines[vp->engine](vm, program, argv, nargs);
6d14383e
AW
449}
450
6f3b0cc2
AW
451SCM_DEFINE (scm_vm_apply, "vm-apply", 3, 0, 0,
452 (SCM vm, SCM program, SCM args),
453 "")
454#define FUNC_NAME s_scm_vm_apply
a98cef7e 455{
6d14383e
AW
456 SCM *argv;
457 int i, nargs;
458
459 SCM_VALIDATE_VM (1, vm);
67e2d80a 460 SCM_VALIDATE_PROC (2, program);
6d14383e
AW
461
462 nargs = scm_ilength (args);
463 if (SCM_UNLIKELY (nargs < 0))
464 scm_wrong_type_arg_msg (FUNC_NAME, 3, args, "list");
465
466 argv = alloca(nargs * sizeof(SCM));
467 for (i = 0; i < nargs; i++)
468 {
469 argv[i] = SCM_CAR (args);
470 args = SCM_CDR (args);
471 }
472
4abef68f 473 return scm_c_vm_run (vm, program, argv, nargs);
a98cef7e 474}
17e90c5e 475#undef FUNC_NAME
a98cef7e 476
14aa25e4
AW
477SCM
478scm_vm_call_with_new_stack (SCM vm, SCM thunk, SCM id)
479{
480 return scm_c_vm_run (vm, thunk, NULL, 0);
481}
482
a98cef7e
KN
483/* Scheme interface */
484
485SCM_DEFINE (scm_vm_version, "vm-version", 0, 0, 0,
17e90c5e
KN
486 (void),
487 "")
a98cef7e
KN
488#define FUNC_NAME s_scm_vm_version
489{
d3518113 490 return scm_from_locale_string (PACKAGE_VERSION);
a98cef7e
KN
491}
492#undef FUNC_NAME
493
499a4c07 494SCM_DEFINE (scm_the_vm, "the-vm", 0, 0, 0,
fcd4901b 495 (void),
499a4c07
KN
496 "")
497#define FUNC_NAME s_scm_the_vm
498{
2bbe1533 499 scm_i_thread *t = SCM_I_CURRENT_THREAD;
f63ea2ce 500
8b22ed7a 501 if (SCM_UNLIKELY (scm_is_false ((t->vm))))
2bbe1533 502 t->vm = make_vm ();
f63ea2ce 503
2bbe1533 504 return t->vm;
499a4c07
KN
505}
506#undef FUNC_NAME
507
508
a98cef7e
KN
509SCM_DEFINE (scm_vm_p, "vm?", 1, 0, 0,
510 (SCM obj),
17e90c5e 511 "")
a98cef7e
KN
512#define FUNC_NAME s_scm_vm_p
513{
9bd48cb1 514 return scm_from_bool (SCM_VM_P (obj));
a98cef7e
KN
515}
516#undef FUNC_NAME
517
518SCM_DEFINE (scm_make_vm, "make-vm", 0, 0, 0,
17e90c5e
KN
519 (void),
520 "")
521#define FUNC_NAME s_scm_make_vm,
a98cef7e 522{
17e90c5e 523 return make_vm ();
a98cef7e
KN
524}
525#undef FUNC_NAME
526
17e90c5e 527SCM_DEFINE (scm_vm_ip, "vm:ip", 1, 0, 0,
a98cef7e 528 (SCM vm),
17e90c5e
KN
529 "")
530#define FUNC_NAME s_scm_vm_ip
a98cef7e
KN
531{
532 SCM_VALIDATE_VM (1, vm);
f41cb00c 533 return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->ip);
a98cef7e
KN
534}
535#undef FUNC_NAME
536
537SCM_DEFINE (scm_vm_sp, "vm:sp", 1, 0, 0,
538 (SCM vm),
17e90c5e 539 "")
a98cef7e
KN
540#define FUNC_NAME s_scm_vm_sp
541{
542 SCM_VALIDATE_VM (1, vm);
f41cb00c 543 return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->sp);
a98cef7e
KN
544}
545#undef FUNC_NAME
546
547SCM_DEFINE (scm_vm_fp, "vm:fp", 1, 0, 0,
548 (SCM vm),
17e90c5e 549 "")
a98cef7e
KN
550#define FUNC_NAME s_scm_vm_fp
551{
552 SCM_VALIDATE_VM (1, vm);
f41cb00c 553 return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->fp);
a98cef7e
KN
554}
555#undef FUNC_NAME
556
17e90c5e
KN
557#define VM_DEFINE_HOOK(n) \
558{ \
3d5ee0cd 559 struct scm_vm *vp; \
17e90c5e 560 SCM_VALIDATE_VM (1, vm); \
3d5ee0cd 561 vp = SCM_VM_DATA (vm); \
8b22ed7a 562 if (scm_is_false (vp->hooks[n])) \
238e7a11 563 vp->hooks[n] = scm_make_hook (SCM_I_MAKINUM (1)); \
3d5ee0cd 564 return vp->hooks[n]; \
17e90c5e
KN
565}
566
567SCM_DEFINE (scm_vm_boot_hook, "vm-boot-hook", 1, 0, 0,
a98cef7e 568 (SCM vm),
17e90c5e
KN
569 "")
570#define FUNC_NAME s_scm_vm_boot_hook
a98cef7e 571{
17e90c5e 572 VM_DEFINE_HOOK (SCM_VM_BOOT_HOOK);
a98cef7e
KN
573}
574#undef FUNC_NAME
575
17e90c5e
KN
576SCM_DEFINE (scm_vm_halt_hook, "vm-halt-hook", 1, 0, 0,
577 (SCM vm),
578 "")
579#define FUNC_NAME s_scm_vm_halt_hook
a98cef7e 580{
17e90c5e 581 VM_DEFINE_HOOK (SCM_VM_HALT_HOOK);
a98cef7e
KN
582}
583#undef FUNC_NAME
584
17e90c5e 585SCM_DEFINE (scm_vm_next_hook, "vm-next-hook", 1, 0, 0,
a98cef7e 586 (SCM vm),
17e90c5e
KN
587 "")
588#define FUNC_NAME s_scm_vm_next_hook
a98cef7e 589{
17e90c5e 590 VM_DEFINE_HOOK (SCM_VM_NEXT_HOOK);
a98cef7e
KN
591}
592#undef FUNC_NAME
593
7a0d0cee
KN
594SCM_DEFINE (scm_vm_break_hook, "vm-break-hook", 1, 0, 0,
595 (SCM vm),
596 "")
597#define FUNC_NAME s_scm_vm_break_hook
598{
599 VM_DEFINE_HOOK (SCM_VM_BREAK_HOOK);
600}
601#undef FUNC_NAME
602
17e90c5e
KN
603SCM_DEFINE (scm_vm_enter_hook, "vm-enter-hook", 1, 0, 0,
604 (SCM vm),
605 "")
606#define FUNC_NAME s_scm_vm_enter_hook
a98cef7e 607{
17e90c5e 608 VM_DEFINE_HOOK (SCM_VM_ENTER_HOOK);
a98cef7e
KN
609}
610#undef FUNC_NAME
611
17e90c5e
KN
612SCM_DEFINE (scm_vm_apply_hook, "vm-apply-hook", 1, 0, 0,
613 (SCM vm),
614 "")
615#define FUNC_NAME s_scm_vm_apply_hook
a98cef7e 616{
17e90c5e 617 VM_DEFINE_HOOK (SCM_VM_APPLY_HOOK);
a98cef7e
KN
618}
619#undef FUNC_NAME
620
17e90c5e 621SCM_DEFINE (scm_vm_exit_hook, "vm-exit-hook", 1, 0, 0,
a98cef7e 622 (SCM vm),
17e90c5e
KN
623 "")
624#define FUNC_NAME s_scm_vm_exit_hook
a98cef7e 625{
17e90c5e 626 VM_DEFINE_HOOK (SCM_VM_EXIT_HOOK);
a98cef7e
KN
627}
628#undef FUNC_NAME
629
17e90c5e 630SCM_DEFINE (scm_vm_return_hook, "vm-return-hook", 1, 0, 0,
a98cef7e 631 (SCM vm),
17e90c5e
KN
632 "")
633#define FUNC_NAME s_scm_vm_return_hook
a98cef7e 634{
17e90c5e 635 VM_DEFINE_HOOK (SCM_VM_RETURN_HOOK);
a98cef7e
KN
636}
637#undef FUNC_NAME
638
17e90c5e
KN
639SCM_DEFINE (scm_vm_option, "vm-option", 2, 0, 0,
640 (SCM vm, SCM key),
641 "")
642#define FUNC_NAME s_scm_vm_option
a98cef7e
KN
643{
644 SCM_VALIDATE_VM (1, vm);
17e90c5e 645 return scm_assq_ref (SCM_VM_DATA (vm)->options, key);
a98cef7e
KN
646}
647#undef FUNC_NAME
648
17e90c5e
KN
649SCM_DEFINE (scm_set_vm_option_x, "set-vm-option!", 3, 0, 0,
650 (SCM vm, SCM key, SCM val),
651 "")
652#define FUNC_NAME s_scm_set_vm_option_x
a98cef7e
KN
653{
654 SCM_VALIDATE_VM (1, vm);
17e90c5e
KN
655 SCM_VM_DATA (vm)->options
656 = scm_assq_set_x (SCM_VM_DATA (vm)->options, key, val);
657 return SCM_UNSPECIFIED;
a98cef7e
KN
658}
659#undef FUNC_NAME
660
7656f194 661SCM_DEFINE (scm_vm_trace_level, "vm-trace-level", 1, 0, 0,
17e90c5e
KN
662 (SCM vm),
663 "")
7656f194 664#define FUNC_NAME s_scm_vm_trace_level
a98cef7e 665{
a98cef7e 666 SCM_VALIDATE_VM (1, vm);
7656f194
AW
667 return scm_from_int (SCM_VM_DATA (vm)->trace_level);
668}
669#undef FUNC_NAME
670
671SCM_DEFINE (scm_set_vm_trace_level_x, "set-vm-trace-level!", 2, 0, 0,
672 (SCM vm, SCM level),
673 "")
674#define FUNC_NAME s_scm_set_vm_trace_level_x
675{
676 SCM_VALIDATE_VM (1, vm);
677 SCM_VM_DATA (vm)->trace_level = scm_to_int (level);
678 return SCM_UNSPECIFIED;
a98cef7e
KN
679}
680#undef FUNC_NAME
681
682\f
683/*
17e90c5e 684 * Initialize
a98cef7e
KN
685 */
686
07e56b27
AW
687SCM scm_load_compiled_with_vm (SCM file)
688{
53e28ed9 689 SCM program = scm_make_program (scm_load_objcode (file),
20d47c39 690 SCM_BOOL_F, SCM_BOOL_F);
07e56b27 691
4abef68f 692 return scm_c_vm_run (scm_the_vm (), program, NULL, 0);
07e56b27
AW
693}
694
17e90c5e 695void
07e56b27 696scm_bootstrap_vm (void)
17e90c5e 697{
60ae5ca2
AW
698 scm_c_register_extension ("libguile", "scm_init_vm",
699 (scm_t_extension_init_func)scm_init_vm, NULL);
700
e3eb628d
LC
701#ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
702 vm_stack_gc_kind =
703 GC_new_kind (GC_new_free_list (),
704 GC_MAKE_PROC (GC_new_proc (vm_stack_mark), 0),
705 0, 1);
706
707#endif
07e56b27
AW
708}
709
710void
711scm_init_vm (void)
712{
17e90c5e 713#ifndef SCM_MAGIC_SNARFER
aeeff258 714#include "libguile/vm.x"
17e90c5e 715#endif
a98cef7e 716}
17e90c5e
KN
717
718/*
719 Local Variables:
720 c-file-style: "gnu"
721 End:
722*/