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