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