rewind the dynamic state when entering a partial continuation
[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
07801437 232vm_reinstate_partial_continuation (SCM vm, SCM cont, SCM intwinds,
9a1c6f1f 233 size_t n, SCM *argv)
cee1d22c 234{
07801437
AW
235 struct scm_vm *vp;
236 struct scm_vm_cont *cp;
237 SCM *argv_copy, *base;
238 size_t i;
239
240 argv_copy = alloca (n * sizeof(SCM));
241 memcpy (argv_copy, argv, n * sizeof(SCM));
242
243 vp = SCM_VM_DATA (vm);
244 cp = SCM_VM_CONT_DATA (cont);
245 base = SCM_FRAME_UPPER_ADDRESS (vp->fp) + 1;
246
247#define RELOC(scm_p) (scm_p + cp->reloc + (base - cp->stack_base))
248
249 if ((base - vp->stack_base) + cp->stack_size + n + 1 > vp->stack_size)
250 {
251 /* puts ("FIXME: Need to expand"); */
252 abort ();
253 }
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#undef RELOC
271
272 /* now push args. ip is in a MV context. */
273 for (i = 0; i < n; i++)
274 {
275 vp->sp++;
276 *vp->sp = argv_copy[i];
277 }
278 vp->sp++;
279 *vp->sp = scm_from_size_t (n);
9a1c6f1f
AW
280
281 /* Finally, rewind the dynamic state. */
282 {
283 long delta = 0;
284 SCM newwinds = scm_i_dynwinds ();
285 for (; scm_is_pair (intwinds); intwinds = scm_cdr (intwinds), delta--)
286 newwinds = scm_cons (scm_car (intwinds), newwinds);
287 scm_dowinds (newwinds, delta);
288 }
4f66bcde
AW
289}
290
291\f
17e90c5e
KN
292/*
293 * VM Internal functions
294 */
295
f6a8e791
AW
296SCM_SYMBOL (sym_vm_run, "vm-run");
297SCM_SYMBOL (sym_vm_error, "vm-error");
298SCM_SYMBOL (sym_keyword_argument_error, "keyword-argument-error");
299SCM_SYMBOL (sym_debug, "debug");
17e90c5e 300
6f3b0cc2
AW
301void
302scm_i_vm_print (SCM x, SCM port, scm_print_state *pstate)
303{
304 scm_puts ("#<vm ", port);
305 scm_uintprint (SCM_UNPACK (x), 16, port);
306 scm_puts (">", port);
307}
308
2fda0242 309static SCM
d2d7acd5 310really_make_boot_program (long nargs)
2fda0242 311{
5bd047ce 312 SCM u8vec;
97fcf583
AW
313 scm_t_uint8 text[] = { scm_op_mv_call, 0, 0, 0, 1,
314 scm_op_make_int8_1, scm_op_halt };
28b119ee 315 struct scm_objcode *bp;
3b9e095b 316 SCM ret;
5bd047ce 317
53e28ed9 318 if (SCM_UNLIKELY (nargs > 255 || nargs < 0))
2fda0242 319 abort ();
28b119ee
AW
320 text[1] = (scm_t_uint8)nargs;
321
d7e7a02a 322 bp = scm_malloc (sizeof (struct scm_objcode) + sizeof (text));
3dbbe28d 323 memcpy (SCM_C_OBJCODE_BASE (bp), text, sizeof (text));
28b119ee
AW
324 bp->len = sizeof(text);
325 bp->metalen = 0;
28b119ee 326
7055591c
AW
327 u8vec = scm_c_take_bytevector ((scm_t_int8*)bp,
328 sizeof (struct scm_objcode) + sizeof (text));
5bd047ce 329 ret = scm_make_program (scm_bytecode_to_objcode (u8vec),
20d47c39 330 SCM_BOOL_F, SCM_BOOL_F);
ba20f78a 331 SCM_SET_CELL_WORD_0 (ret, SCM_CELL_WORD_0 (ret) | SCM_F_PROGRAM_IS_BOOT);
5bd047ce 332
3b9e095b 333 return ret;
2fda0242 334}
d2d7acd5
AW
335#define NUM_BOOT_PROGS 8
336static SCM
337vm_make_boot_program (long nargs)
338{
339 static SCM programs[NUM_BOOT_PROGS] = { 0, };
340
341 if (SCM_UNLIKELY (!programs[0]))
342 {
343 int i;
344 for (i = 0; i < NUM_BOOT_PROGS; i++)
f39448c5 345 programs[i] = really_make_boot_program (i);
d2d7acd5
AW
346 }
347
348 if (SCM_LIKELY (nargs < NUM_BOOT_PROGS))
349 return programs[nargs];
350 else
351 return really_make_boot_program (nargs);
352}
2fda0242 353
a98cef7e
KN
354\f
355/*
356 * VM
357 */
358
b7393ea1
AW
359static SCM
360resolve_variable (SCM what, SCM program_module)
361{
9bd48cb1 362 if (SCM_LIKELY (scm_is_symbol (what)))
b7393ea1
AW
363 {
364 if (SCM_LIKELY (scm_module_system_booted_p
365 && scm_is_true (program_module)))
366 /* might longjmp */
367 return scm_module_lookup (program_module, what);
368 else
369 {
370 SCM v = scm_sym2var (what, SCM_BOOL_F, SCM_BOOL_F);
371 if (scm_is_false (v))
372 scm_misc_error (NULL, "unbound variable: ~S", scm_list_1 (what));
373 else
374 return v;
375 }
376 }
377 else
378 {
379 SCM mod;
380 /* compilation of @ or @@
381 `what' is a three-element list: (MODNAME SYM INTERFACE?)
382 INTERFACE? is #t if we compiled @ or #f if we compiled @@
383 */
384 mod = scm_resolve_module (SCM_CAR (what));
385 if (scm_is_true (SCM_CADDR (what)))
386 mod = scm_module_public_interface (mod);
5c8cefe5 387 if (scm_is_false (mod))
b7393ea1
AW
388 scm_misc_error (NULL, "no such module: ~S",
389 scm_list_1 (SCM_CAR (what)));
390 /* might longjmp */
391 return scm_module_lookup (mod, SCM_CADR (what));
392 }
393}
394
51e9ba2f 395#define VM_DEFAULT_STACK_SIZE (64 * 1024)
17e90c5e 396
17e90c5e 397#define VM_NAME vm_regular_engine
6d14383e
AW
398#define FUNC_NAME "vm-regular-engine"
399#define VM_ENGINE SCM_VM_REGULAR_ENGINE
83495480 400#include "vm-engine.c"
17e90c5e 401#undef VM_NAME
6d14383e 402#undef FUNC_NAME
17e90c5e 403#undef VM_ENGINE
17e90c5e
KN
404
405#define VM_NAME vm_debug_engine
6d14383e
AW
406#define FUNC_NAME "vm-debug-engine"
407#define VM_ENGINE SCM_VM_DEBUG_ENGINE
83495480 408#include "vm-engine.c"
17e90c5e 409#undef VM_NAME
6d14383e 410#undef FUNC_NAME
17e90c5e
KN
411#undef VM_ENGINE
412
6d14383e
AW
413static const scm_t_vm_engine vm_engines[] =
414 { vm_regular_engine, vm_debug_engine };
415
e3eb628d
LC
416#ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
417
418/* The GC "kind" for the VM stack. */
419static int vm_stack_gc_kind;
420
421#endif
422
a98cef7e 423static SCM
17e90c5e
KN
424make_vm (void)
425#define FUNC_NAME "make_vm"
a98cef7e 426{
17e90c5e 427 int i;
7f991c7d 428 struct scm_vm *vp;
747a1635 429
7f991c7d 430 vp = scm_gc_malloc (sizeof (struct scm_vm), "vm");
d8eeb67c 431
3d5ee0cd 432 vp->stack_size = VM_DEFAULT_STACK_SIZE;
e3eb628d
LC
433
434#ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
4168aa46
TTN
435 vp->stack_base = (SCM *)
436 GC_generic_malloc (vp->stack_size * sizeof (SCM), vm_stack_gc_kind);
e3eb628d
LC
437
438 /* Keep a pointer to VP so that `vm_stack_mark ()' can know what the stack
439 top is. */
440 *vp->stack_base = PTR2SCM (vp);
441 vp->stack_base++;
442 vp->stack_size--;
443#else
d8eeb67c
LC
444 vp->stack_base = scm_gc_malloc (vp->stack_size * sizeof (SCM),
445 "stack-base");
e3eb628d
LC
446#endif
447
2bbe1533
AW
448#ifdef VM_ENABLE_STACK_NULLING
449 memset (vp->stack_base, 0, vp->stack_size * sizeof (SCM));
450#endif
75d315e1 451 vp->stack_limit = vp->stack_base + vp->stack_size;
3616e9e9
KN
452 vp->ip = NULL;
453 vp->sp = vp->stack_base - 1;
454 vp->fp = NULL;
6d14383e 455 vp->engine = SCM_VM_DEBUG_ENGINE;
3d5ee0cd 456 vp->options = SCM_EOL;
7656f194 457 vp->trace_level = 0;
17e90c5e 458 for (i = 0; i < SCM_VM_NUM_HOOKS; i++)
3d5ee0cd 459 vp->hooks[i] = SCM_BOOL_F;
2d026f04 460 vp->cookie = 0;
6f3b0cc2 461 return scm_cell (scm_tc7_vm, (scm_t_bits)vp);
a98cef7e 462}
17e90c5e 463#undef FUNC_NAME
a98cef7e 464
e3eb628d
LC
465#ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
466
467/* Mark the VM stack region between its base and its current top. */
468static struct GC_ms_entry *
469vm_stack_mark (GC_word *addr, struct GC_ms_entry *mark_stack_ptr,
470 struct GC_ms_entry *mark_stack_limit, GC_word env)
471{
472 GC_word *word;
473 const struct scm_vm *vm;
474
475 /* The first word of the VM stack should contain a pointer to the
476 corresponding VM. */
477 vm = * ((struct scm_vm **) addr);
478
8071c490
LC
479 if (vm == NULL
480 || (SCM *) addr != vm->stack_base - 1
78747ac6 481 || vm->stack_limit - vm->stack_base != vm->stack_size)
e3eb628d
LC
482 /* ADDR must be a pointer to a free-list element, which we must ignore
483 (see warning in <gc/gc_mark.h>). */
484 return mark_stack_ptr;
485
e3eb628d
LC
486 for (word = (GC_word *) vm->stack_base; word <= (GC_word *) vm->sp; word++)
487 mark_stack_ptr = GC_MARK_AND_PUSH ((* (GC_word **) word),
488 mark_stack_ptr, mark_stack_limit,
489 NULL);
490
491 return mark_stack_ptr;
492}
493
494#endif /* VM_ENABLE_PRECISE_STACK_GC_SCAN */
495
496
6d14383e 497SCM
4abef68f 498scm_c_vm_run (SCM vm, SCM program, SCM *argv, int nargs)
6d14383e 499{
4abef68f 500 struct scm_vm *vp = SCM_VM_DATA (vm);
7656f194 501 return vm_engines[vp->engine](vm, program, argv, nargs);
6d14383e
AW
502}
503
6f3b0cc2
AW
504SCM_DEFINE (scm_vm_apply, "vm-apply", 3, 0, 0,
505 (SCM vm, SCM program, SCM args),
506 "")
507#define FUNC_NAME s_scm_vm_apply
a98cef7e 508{
6d14383e
AW
509 SCM *argv;
510 int i, nargs;
511
512 SCM_VALIDATE_VM (1, vm);
67e2d80a 513 SCM_VALIDATE_PROC (2, program);
6d14383e
AW
514
515 nargs = scm_ilength (args);
516 if (SCM_UNLIKELY (nargs < 0))
517 scm_wrong_type_arg_msg (FUNC_NAME, 3, args, "list");
518
519 argv = alloca(nargs * sizeof(SCM));
520 for (i = 0; i < nargs; i++)
521 {
522 argv[i] = SCM_CAR (args);
523 args = SCM_CDR (args);
524 }
525
4abef68f 526 return scm_c_vm_run (vm, program, argv, nargs);
a98cef7e 527}
17e90c5e 528#undef FUNC_NAME
a98cef7e 529
14aa25e4
AW
530SCM
531scm_vm_call_with_new_stack (SCM vm, SCM thunk, SCM id)
532{
533 return scm_c_vm_run (vm, thunk, NULL, 0);
534}
535
a98cef7e
KN
536/* Scheme interface */
537
538SCM_DEFINE (scm_vm_version, "vm-version", 0, 0, 0,
17e90c5e
KN
539 (void),
540 "")
a98cef7e
KN
541#define FUNC_NAME s_scm_vm_version
542{
d3518113 543 return scm_from_locale_string (PACKAGE_VERSION);
a98cef7e
KN
544}
545#undef FUNC_NAME
546
499a4c07 547SCM_DEFINE (scm_the_vm, "the-vm", 0, 0, 0,
fcd4901b 548 (void),
499a4c07
KN
549 "")
550#define FUNC_NAME s_scm_the_vm
551{
2bbe1533 552 scm_i_thread *t = SCM_I_CURRENT_THREAD;
f63ea2ce 553
8b22ed7a 554 if (SCM_UNLIKELY (scm_is_false ((t->vm))))
2bbe1533 555 t->vm = make_vm ();
f63ea2ce 556
2bbe1533 557 return t->vm;
499a4c07
KN
558}
559#undef FUNC_NAME
560
561
a98cef7e
KN
562SCM_DEFINE (scm_vm_p, "vm?", 1, 0, 0,
563 (SCM obj),
17e90c5e 564 "")
a98cef7e
KN
565#define FUNC_NAME s_scm_vm_p
566{
9bd48cb1 567 return scm_from_bool (SCM_VM_P (obj));
a98cef7e
KN
568}
569#undef FUNC_NAME
570
571SCM_DEFINE (scm_make_vm, "make-vm", 0, 0, 0,
17e90c5e
KN
572 (void),
573 "")
574#define FUNC_NAME s_scm_make_vm,
a98cef7e 575{
17e90c5e 576 return make_vm ();
a98cef7e
KN
577}
578#undef FUNC_NAME
579
17e90c5e 580SCM_DEFINE (scm_vm_ip, "vm:ip", 1, 0, 0,
a98cef7e 581 (SCM vm),
17e90c5e
KN
582 "")
583#define FUNC_NAME s_scm_vm_ip
a98cef7e
KN
584{
585 SCM_VALIDATE_VM (1, vm);
f41cb00c 586 return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->ip);
a98cef7e
KN
587}
588#undef FUNC_NAME
589
590SCM_DEFINE (scm_vm_sp, "vm:sp", 1, 0, 0,
591 (SCM vm),
17e90c5e 592 "")
a98cef7e
KN
593#define FUNC_NAME s_scm_vm_sp
594{
595 SCM_VALIDATE_VM (1, vm);
f41cb00c 596 return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->sp);
a98cef7e
KN
597}
598#undef FUNC_NAME
599
600SCM_DEFINE (scm_vm_fp, "vm:fp", 1, 0, 0,
601 (SCM vm),
17e90c5e 602 "")
a98cef7e
KN
603#define FUNC_NAME s_scm_vm_fp
604{
605 SCM_VALIDATE_VM (1, vm);
f41cb00c 606 return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->fp);
a98cef7e
KN
607}
608#undef FUNC_NAME
609
17e90c5e
KN
610#define VM_DEFINE_HOOK(n) \
611{ \
3d5ee0cd 612 struct scm_vm *vp; \
17e90c5e 613 SCM_VALIDATE_VM (1, vm); \
3d5ee0cd 614 vp = SCM_VM_DATA (vm); \
8b22ed7a 615 if (scm_is_false (vp->hooks[n])) \
238e7a11 616 vp->hooks[n] = scm_make_hook (SCM_I_MAKINUM (1)); \
3d5ee0cd 617 return vp->hooks[n]; \
17e90c5e
KN
618}
619
620SCM_DEFINE (scm_vm_boot_hook, "vm-boot-hook", 1, 0, 0,
a98cef7e 621 (SCM vm),
17e90c5e
KN
622 "")
623#define FUNC_NAME s_scm_vm_boot_hook
a98cef7e 624{
17e90c5e 625 VM_DEFINE_HOOK (SCM_VM_BOOT_HOOK);
a98cef7e
KN
626}
627#undef FUNC_NAME
628
17e90c5e
KN
629SCM_DEFINE (scm_vm_halt_hook, "vm-halt-hook", 1, 0, 0,
630 (SCM vm),
631 "")
632#define FUNC_NAME s_scm_vm_halt_hook
a98cef7e 633{
17e90c5e 634 VM_DEFINE_HOOK (SCM_VM_HALT_HOOK);
a98cef7e
KN
635}
636#undef FUNC_NAME
637
17e90c5e 638SCM_DEFINE (scm_vm_next_hook, "vm-next-hook", 1, 0, 0,
a98cef7e 639 (SCM vm),
17e90c5e
KN
640 "")
641#define FUNC_NAME s_scm_vm_next_hook
a98cef7e 642{
17e90c5e 643 VM_DEFINE_HOOK (SCM_VM_NEXT_HOOK);
a98cef7e
KN
644}
645#undef FUNC_NAME
646
7a0d0cee
KN
647SCM_DEFINE (scm_vm_break_hook, "vm-break-hook", 1, 0, 0,
648 (SCM vm),
649 "")
650#define FUNC_NAME s_scm_vm_break_hook
651{
652 VM_DEFINE_HOOK (SCM_VM_BREAK_HOOK);
653}
654#undef FUNC_NAME
655
17e90c5e
KN
656SCM_DEFINE (scm_vm_enter_hook, "vm-enter-hook", 1, 0, 0,
657 (SCM vm),
658 "")
659#define FUNC_NAME s_scm_vm_enter_hook
a98cef7e 660{
17e90c5e 661 VM_DEFINE_HOOK (SCM_VM_ENTER_HOOK);
a98cef7e
KN
662}
663#undef FUNC_NAME
664
17e90c5e
KN
665SCM_DEFINE (scm_vm_apply_hook, "vm-apply-hook", 1, 0, 0,
666 (SCM vm),
667 "")
668#define FUNC_NAME s_scm_vm_apply_hook
a98cef7e 669{
17e90c5e 670 VM_DEFINE_HOOK (SCM_VM_APPLY_HOOK);
a98cef7e
KN
671}
672#undef FUNC_NAME
673
17e90c5e 674SCM_DEFINE (scm_vm_exit_hook, "vm-exit-hook", 1, 0, 0,
a98cef7e 675 (SCM vm),
17e90c5e
KN
676 "")
677#define FUNC_NAME s_scm_vm_exit_hook
a98cef7e 678{
17e90c5e 679 VM_DEFINE_HOOK (SCM_VM_EXIT_HOOK);
a98cef7e
KN
680}
681#undef FUNC_NAME
682
17e90c5e 683SCM_DEFINE (scm_vm_return_hook, "vm-return-hook", 1, 0, 0,
a98cef7e 684 (SCM vm),
17e90c5e
KN
685 "")
686#define FUNC_NAME s_scm_vm_return_hook
a98cef7e 687{
17e90c5e 688 VM_DEFINE_HOOK (SCM_VM_RETURN_HOOK);
a98cef7e
KN
689}
690#undef FUNC_NAME
691
17e90c5e
KN
692SCM_DEFINE (scm_vm_option, "vm-option", 2, 0, 0,
693 (SCM vm, SCM key),
694 "")
695#define FUNC_NAME s_scm_vm_option
a98cef7e
KN
696{
697 SCM_VALIDATE_VM (1, vm);
17e90c5e 698 return scm_assq_ref (SCM_VM_DATA (vm)->options, key);
a98cef7e
KN
699}
700#undef FUNC_NAME
701
17e90c5e
KN
702SCM_DEFINE (scm_set_vm_option_x, "set-vm-option!", 3, 0, 0,
703 (SCM vm, SCM key, SCM val),
704 "")
705#define FUNC_NAME s_scm_set_vm_option_x
a98cef7e
KN
706{
707 SCM_VALIDATE_VM (1, vm);
17e90c5e
KN
708 SCM_VM_DATA (vm)->options
709 = scm_assq_set_x (SCM_VM_DATA (vm)->options, key, val);
710 return SCM_UNSPECIFIED;
a98cef7e
KN
711}
712#undef FUNC_NAME
713
7656f194 714SCM_DEFINE (scm_vm_trace_level, "vm-trace-level", 1, 0, 0,
17e90c5e
KN
715 (SCM vm),
716 "")
7656f194 717#define FUNC_NAME s_scm_vm_trace_level
a98cef7e 718{
a98cef7e 719 SCM_VALIDATE_VM (1, vm);
7656f194
AW
720 return scm_from_int (SCM_VM_DATA (vm)->trace_level);
721}
722#undef FUNC_NAME
723
724SCM_DEFINE (scm_set_vm_trace_level_x, "set-vm-trace-level!", 2, 0, 0,
725 (SCM vm, SCM level),
726 "")
727#define FUNC_NAME s_scm_set_vm_trace_level_x
728{
729 SCM_VALIDATE_VM (1, vm);
730 SCM_VM_DATA (vm)->trace_level = scm_to_int (level);
731 return SCM_UNSPECIFIED;
a98cef7e
KN
732}
733#undef FUNC_NAME
734
735\f
736/*
17e90c5e 737 * Initialize
a98cef7e
KN
738 */
739
07e56b27
AW
740SCM scm_load_compiled_with_vm (SCM file)
741{
53e28ed9 742 SCM program = scm_make_program (scm_load_objcode (file),
20d47c39 743 SCM_BOOL_F, SCM_BOOL_F);
07e56b27 744
4abef68f 745 return scm_c_vm_run (scm_the_vm (), program, NULL, 0);
07e56b27
AW
746}
747
17e90c5e 748void
07e56b27 749scm_bootstrap_vm (void)
17e90c5e 750{
60ae5ca2
AW
751 scm_c_register_extension ("libguile", "scm_init_vm",
752 (scm_t_extension_init_func)scm_init_vm, NULL);
753
e3eb628d
LC
754#ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
755 vm_stack_gc_kind =
756 GC_new_kind (GC_new_free_list (),
757 GC_MAKE_PROC (GC_new_proc (vm_stack_mark), 0),
758 0, 1);
759
760#endif
07e56b27
AW
761}
762
763void
764scm_init_vm (void)
765{
17e90c5e 766#ifndef SCM_MAGIC_SNARFER
aeeff258 767#include "libguile/vm.x"
17e90c5e 768#endif
a98cef7e 769}
17e90c5e
KN
770
771/*
772 Local Variables:
773 c-file-style: "gnu"
774 End:
775*/