Add `program-free-variables' to `(system vm program)'.
[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"
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
6f3b0cc2
AW
74void
75scm_i_vm_cont_print (SCM x, SCM port, scm_print_state *pstate)
76{
77 scm_puts ("#<vm-continuation ", port);
78 scm_uintprint (SCM_UNPACK (x), 16, port);
79 scm_puts (">", port);
80}
17e90c5e 81
d8873dfe
AW
82/* In theory, a number of vm instances can be active in the call trace, and we
83 only want to reify the continuations of those in the current continuation
84 root. I don't see a nice way to do this -- ideally it would involve dynwinds,
85 and previous values of the *the-vm* fluid within the current continuation
86 root. But we don't have access to continuation roots in the dynwind stack.
87 So, just punt for now, we just capture the continuation for the current VM.
88
89 While I'm on the topic, ideally we could avoid copying the C stack if the
90 continuation root is inside VM code, and call/cc was invoked within that same
91 call to vm_run; but that's currently not implemented.
92 */
cee1d22c
AW
93SCM
94scm_i_vm_capture_stack (SCM *stack_base, SCM *fp, SCM *sp, scm_t_uint8 *ra,
95 scm_t_uint8 *mvra, scm_t_uint32 flags)
a98cef7e 96{
d8873dfe
AW
97 struct scm_vm_cont *p;
98
99 p = scm_gc_malloc (sizeof (*p), "capture_vm_cont");
100 p->stack_size = sp - stack_base + 1;
d8eeb67c
LC
101 p->stack_base = scm_gc_malloc (p->stack_size * sizeof (SCM),
102 "capture_vm_cont");
d8873dfe
AW
103#if defined(VM_ENABLE_STACK_NULLING) && 0
104 /* Tail continuations leave their frame on the stack for subsequent
105 application, but don't capture the frame -- so there are some elements on
106 the stack then, and this check doesn't work, so disable it for now. */
107 if (sp >= vp->stack_base)
66db076a
AW
108 if (!vp->sp[0] || vp->sp[1])
109 abort ();
11ea1aba
AW
110 memset (p->stack_base, 0, p->stack_size * sizeof (SCM));
111#endif
d8873dfe
AW
112 p->ra = ra;
113 p->mvra = mvra;
114 p->sp = sp;
115 p->fp = fp;
116 memcpy (p->stack_base, stack_base, (sp + 1 - stack_base) * sizeof (SCM));
117 p->reloc = p->stack_base - stack_base;
cee1d22c 118 p->flags = flags;
6f3b0cc2 119 return scm_cell (scm_tc7_vm_cont, (scm_t_bits)p);
a98cef7e
KN
120}
121
122static void
d8873dfe 123vm_return_to_continuation (SCM vm, SCM cont, size_t n, SCM *argv)
a98cef7e 124{
d8873dfe
AW
125 struct scm_vm *vp;
126 struct scm_vm_cont *cp;
127 SCM *argv_copy;
128
129 argv_copy = alloca (n * sizeof(SCM));
130 memcpy (argv_copy, argv, n * sizeof(SCM));
131
132 vp = SCM_VM_DATA (vm);
133 cp = SCM_VM_CONT_DATA (cont);
134
135 if (n == 0 && !cp->mvra)
136 scm_misc_error (NULL, "Too few values returned to continuation",
137 SCM_EOL);
138
139 if (vp->stack_size < cp->stack_size + n + 1)
29366989
AW
140 scm_misc_error ("vm-engine", "not enough space to reinstate continuation",
141 scm_list_2 (vm, cont));
142
11ea1aba
AW
143#ifdef VM_ENABLE_STACK_NULLING
144 {
d8873dfe 145 scm_t_ptrdiff nzero = (vp->sp - cp->sp);
11ea1aba 146 if (nzero > 0)
d8873dfe 147 memset (vp->stack_base + cp->stack_size, 0, nzero * sizeof (SCM));
66db076a
AW
148 /* actually nzero should always be negative, because vm_reset_stack will
149 unwind the stack to some point *below* this continuation */
11ea1aba
AW
150 }
151#endif
d8873dfe
AW
152 vp->sp = cp->sp;
153 vp->fp = cp->fp;
154 memcpy (vp->stack_base, cp->stack_base, cp->stack_size * sizeof (SCM));
bfffd258 155
d8873dfe
AW
156 if (n == 1 || !cp->mvra)
157 {
158 vp->ip = cp->ra;
159 vp->sp++;
160 *vp->sp = argv_copy[0];
161 }
162 else
163 {
164 size_t i;
165 for (i = 0; i < n; i++)
166 {
167 vp->sp++;
168 *vp->sp = argv_copy[i];
169 }
170 vp->sp++;
171 *vp->sp = scm_from_size_t (n);
172 vp->ip = cp->mvra;
173 }
174}
bfffd258 175
bfffd258 176SCM
269479e3 177scm_i_vm_capture_continuation (SCM vm)
bfffd258 178{
d8873dfe 179 struct scm_vm *vp = SCM_VM_DATA (vm);
cee1d22c 180 return scm_i_vm_capture_stack (vp->stack_base, vp->fp, vp->sp, vp->ip, NULL, 0);
a98cef7e
KN
181}
182
b1b942b7 183static void
7656f194 184vm_dispatch_hook (SCM vm, int hook_num)
b1b942b7 185{
7656f194
AW
186 struct scm_vm *vp;
187 SCM hook;
188 SCM frame;
b1b942b7 189
7656f194
AW
190 vp = SCM_VM_DATA (vm);
191 hook = vp->hooks[hook_num];
b1b942b7 192
7656f194
AW
193 if (SCM_LIKELY (scm_is_false (hook))
194 || scm_is_null (SCM_HOOK_PROCEDURES (hook)))
195 return;
196
197 vp->trace_level--;
198 frame = scm_c_make_frame (vm, vp->fp, vp->sp, vp->ip, 0);
199 scm_c_run_hookn (hook, &frame, 1);
200 vp->trace_level++;
b1b942b7
AW
201}
202
cee1d22c 203static void vm_abort (SCM vm, size_t n, scm_t_int64 cookie) SCM_NORETURN;
4f66bcde 204static void
cee1d22c 205vm_abort (SCM vm, size_t n, scm_t_int64 vm_cookie)
4f66bcde 206{
eaefabee 207 size_t i;
2d026f04
AW
208 ssize_t tail_len;
209 SCM tag, tail, *argv;
eaefabee 210
2d026f04
AW
211 /* FIXME: VM_ENABLE_STACK_NULLING */
212 tail = *(SCM_VM_DATA (vm)->sp--);
213 /* NULLSTACK (1) */
214 tail_len = scm_ilength (tail);
215 if (tail_len < 0)
29366989
AW
216 scm_misc_error ("vm-engine", "tail values to abort should be a list",
217 scm_list_1 (tail));
218
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,
adbdfd6d 233 size_t n, SCM *argv, scm_t_int64 vm_cookie)
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)
29366989
AW
250 scm_misc_error ("vm-engine",
251 "not enough space to instate partial continuation",
252 scm_list_2 (vm, cont));
07801437
AW
253
254 memcpy (base, cp->stack_base, cp->stack_size * sizeof (SCM));
255
256 /* now relocate frame pointers */
257 {
258 SCM *fp;
259 for (fp = RELOC (cp->fp);
260 SCM_FRAME_LOWER_ADDRESS (fp) > base;
261 fp = SCM_FRAME_DYNAMIC_LINK (fp))
262 SCM_FRAME_SET_DYNAMIC_LINK (fp, RELOC (SCM_FRAME_DYNAMIC_LINK (fp)));
263 }
264
265 vp->sp = base - 1 + cp->stack_size;
266 vp->fp = RELOC (cp->fp);
267 vp->ip = cp->mvra;
268
07801437
AW
269 /* now push args. ip is in a MV context. */
270 for (i = 0; i < n; i++)
271 {
272 vp->sp++;
273 *vp->sp = argv_copy[i];
274 }
275 vp->sp++;
276 *vp->sp = scm_from_size_t (n);
9a1c6f1f 277
adbdfd6d
AW
278 /* Finally, rewind the dynamic state.
279
280 We have to treat prompts specially, because we could be rewinding the
281 dynamic state from a different thread, or just a different position on the
282 C and/or VM stack -- so we need to reset the jump buffers so that an abort
283 comes back here, with appropriately adjusted sp and fp registers. */
9a1c6f1f
AW
284 {
285 long delta = 0;
286 SCM newwinds = scm_i_dynwinds ();
287 for (; scm_is_pair (intwinds); intwinds = scm_cdr (intwinds), delta--)
adbdfd6d
AW
288 {
289 SCM x = scm_car (intwinds);
290 if (SCM_PROMPT_P (x))
291 /* the jmpbuf will be reset by our caller */
292 x = scm_c_make_prompt (SCM_PROMPT_TAG (x),
293 RELOC (SCM_PROMPT_REGISTERS (x)->fp),
294 RELOC (SCM_PROMPT_REGISTERS (x)->sp),
295 SCM_PROMPT_REGISTERS (x)->ip,
296 SCM_PROMPT_ESCAPE_P (x),
297 vm_cookie,
298 newwinds);
299 newwinds = scm_cons (x, newwinds);
300 }
9a1c6f1f
AW
301 scm_dowinds (newwinds, delta);
302 }
adbdfd6d 303#undef RELOC
4f66bcde
AW
304}
305
306\f
17e90c5e
KN
307/*
308 * VM Internal functions
309 */
310
0404c97d
AW
311/* Unfortunately we can't snarf these: snarfed things are only loaded up from
312 (system vm vm), which might not be loaded before an error happens. */
313static SCM sym_vm_run, sym_vm_error, sym_keyword_argument_error, sym_debug;
17e90c5e 314
6f3b0cc2
AW
315void
316scm_i_vm_print (SCM x, SCM port, scm_print_state *pstate)
317{
0a935b2a
LC
318 const struct scm_vm *vm;
319
320 vm = SCM_VM_DATA (x);
321
6f3b0cc2 322 scm_puts ("#<vm ", port);
0a935b2a
LC
323 switch (vm->engine)
324 {
325 case SCM_VM_REGULAR_ENGINE:
326 scm_puts ("regular-engine ", port);
327 break;
328
329 case SCM_VM_DEBUG_ENGINE:
330 scm_puts ("debug-engine ", port);
331 break;
332
333 default:
334 scm_puts ("unknown-engine ", port);
335 }
6f3b0cc2
AW
336 scm_uintprint (SCM_UNPACK (x), 16, port);
337 scm_puts (">", port);
338}
339
2fda0242 340static SCM
d2d7acd5 341really_make_boot_program (long nargs)
2fda0242 342{
5bd047ce 343 SCM u8vec;
97fcf583
AW
344 scm_t_uint8 text[] = { scm_op_mv_call, 0, 0, 0, 1,
345 scm_op_make_int8_1, scm_op_halt };
28b119ee 346 struct scm_objcode *bp;
3b9e095b 347 SCM ret;
5bd047ce 348
53e28ed9 349 if (SCM_UNLIKELY (nargs > 255 || nargs < 0))
29366989
AW
350 scm_misc_error ("vm-engine", "too many args when making boot procedure",
351 scm_list_1 (scm_from_long (nargs)));
352
28b119ee
AW
353 text[1] = (scm_t_uint8)nargs;
354
d7e7a02a 355 bp = scm_malloc (sizeof (struct scm_objcode) + sizeof (text));
3dbbe28d 356 memcpy (SCM_C_OBJCODE_BASE (bp), text, sizeof (text));
28b119ee
AW
357 bp->len = sizeof(text);
358 bp->metalen = 0;
28b119ee 359
7055591c
AW
360 u8vec = scm_c_take_bytevector ((scm_t_int8*)bp,
361 sizeof (struct scm_objcode) + sizeof (text));
5bd047ce 362 ret = scm_make_program (scm_bytecode_to_objcode (u8vec),
20d47c39 363 SCM_BOOL_F, SCM_BOOL_F);
ba20f78a 364 SCM_SET_CELL_WORD_0 (ret, SCM_CELL_WORD_0 (ret) | SCM_F_PROGRAM_IS_BOOT);
5bd047ce 365
3b9e095b 366 return ret;
2fda0242 367}
d2d7acd5
AW
368#define NUM_BOOT_PROGS 8
369static SCM
370vm_make_boot_program (long nargs)
371{
372 static SCM programs[NUM_BOOT_PROGS] = { 0, };
373
374 if (SCM_UNLIKELY (!programs[0]))
375 {
376 int i;
377 for (i = 0; i < NUM_BOOT_PROGS; i++)
f39448c5 378 programs[i] = really_make_boot_program (i);
d2d7acd5
AW
379 }
380
381 if (SCM_LIKELY (nargs < NUM_BOOT_PROGS))
382 return programs[nargs];
383 else
384 return really_make_boot_program (nargs);
385}
2fda0242 386
a98cef7e
KN
387\f
388/*
389 * VM
390 */
391
b7393ea1
AW
392static SCM
393resolve_variable (SCM what, SCM program_module)
394{
9bd48cb1 395 if (SCM_LIKELY (scm_is_symbol (what)))
b7393ea1
AW
396 {
397 if (SCM_LIKELY (scm_module_system_booted_p
398 && scm_is_true (program_module)))
399 /* might longjmp */
400 return scm_module_lookup (program_module, what);
401 else
402 {
403 SCM v = scm_sym2var (what, SCM_BOOL_F, SCM_BOOL_F);
404 if (scm_is_false (v))
405 scm_misc_error (NULL, "unbound variable: ~S", scm_list_1 (what));
406 else
407 return v;
408 }
409 }
410 else
411 {
412 SCM mod;
413 /* compilation of @ or @@
414 `what' is a three-element list: (MODNAME SYM INTERFACE?)
415 INTERFACE? is #t if we compiled @ or #f if we compiled @@
416 */
417 mod = scm_resolve_module (SCM_CAR (what));
418 if (scm_is_true (SCM_CADDR (what)))
419 mod = scm_module_public_interface (mod);
5c8cefe5 420 if (scm_is_false (mod))
b7393ea1
AW
421 scm_misc_error (NULL, "no such module: ~S",
422 scm_list_1 (SCM_CAR (what)));
423 /* might longjmp */
424 return scm_module_lookup (mod, SCM_CADR (what));
425 }
426}
427
51e9ba2f 428#define VM_DEFAULT_STACK_SIZE (64 * 1024)
17e90c5e 429
17e90c5e 430#define VM_NAME vm_regular_engine
6d14383e
AW
431#define FUNC_NAME "vm-regular-engine"
432#define VM_ENGINE SCM_VM_REGULAR_ENGINE
83495480 433#include "vm-engine.c"
17e90c5e 434#undef VM_NAME
6d14383e 435#undef FUNC_NAME
17e90c5e 436#undef VM_ENGINE
17e90c5e
KN
437
438#define VM_NAME vm_debug_engine
6d14383e
AW
439#define FUNC_NAME "vm-debug-engine"
440#define VM_ENGINE SCM_VM_DEBUG_ENGINE
83495480 441#include "vm-engine.c"
17e90c5e 442#undef VM_NAME
6d14383e 443#undef FUNC_NAME
17e90c5e
KN
444#undef VM_ENGINE
445
6d14383e
AW
446static const scm_t_vm_engine vm_engines[] =
447 { vm_regular_engine, vm_debug_engine };
448
e3eb628d
LC
449#ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
450
451/* The GC "kind" for the VM stack. */
452static int vm_stack_gc_kind;
453
454#endif
455
a98cef7e 456static SCM
17e90c5e
KN
457make_vm (void)
458#define FUNC_NAME "make_vm"
a98cef7e 459{
17e90c5e 460 int i;
7f991c7d 461 struct scm_vm *vp;
747a1635 462
7f991c7d 463 vp = scm_gc_malloc (sizeof (struct scm_vm), "vm");
d8eeb67c 464
3d5ee0cd 465 vp->stack_size = VM_DEFAULT_STACK_SIZE;
e3eb628d
LC
466
467#ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
4168aa46
TTN
468 vp->stack_base = (SCM *)
469 GC_generic_malloc (vp->stack_size * sizeof (SCM), vm_stack_gc_kind);
e3eb628d
LC
470
471 /* Keep a pointer to VP so that `vm_stack_mark ()' can know what the stack
472 top is. */
473 *vp->stack_base = PTR2SCM (vp);
474 vp->stack_base++;
475 vp->stack_size--;
476#else
d8eeb67c
LC
477 vp->stack_base = scm_gc_malloc (vp->stack_size * sizeof (SCM),
478 "stack-base");
e3eb628d
LC
479#endif
480
2bbe1533
AW
481#ifdef VM_ENABLE_STACK_NULLING
482 memset (vp->stack_base, 0, vp->stack_size * sizeof (SCM));
483#endif
75d315e1 484 vp->stack_limit = vp->stack_base + vp->stack_size;
3616e9e9
KN
485 vp->ip = NULL;
486 vp->sp = vp->stack_base - 1;
487 vp->fp = NULL;
6d14383e 488 vp->engine = SCM_VM_DEBUG_ENGINE;
3d5ee0cd 489 vp->options = SCM_EOL;
7656f194 490 vp->trace_level = 0;
17e90c5e 491 for (i = 0; i < SCM_VM_NUM_HOOKS; i++)
3d5ee0cd 492 vp->hooks[i] = SCM_BOOL_F;
2d026f04 493 vp->cookie = 0;
6f3b0cc2 494 return scm_cell (scm_tc7_vm, (scm_t_bits)vp);
a98cef7e 495}
17e90c5e 496#undef FUNC_NAME
a98cef7e 497
e3eb628d
LC
498#ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
499
500/* Mark the VM stack region between its base and its current top. */
501static struct GC_ms_entry *
502vm_stack_mark (GC_word *addr, struct GC_ms_entry *mark_stack_ptr,
503 struct GC_ms_entry *mark_stack_limit, GC_word env)
504{
505 GC_word *word;
506 const struct scm_vm *vm;
507
508 /* The first word of the VM stack should contain a pointer to the
509 corresponding VM. */
510 vm = * ((struct scm_vm **) addr);
511
8071c490
LC
512 if (vm == NULL
513 || (SCM *) addr != vm->stack_base - 1
78747ac6 514 || vm->stack_limit - vm->stack_base != vm->stack_size)
e3eb628d
LC
515 /* ADDR must be a pointer to a free-list element, which we must ignore
516 (see warning in <gc/gc_mark.h>). */
517 return mark_stack_ptr;
518
e3eb628d
LC
519 for (word = (GC_word *) vm->stack_base; word <= (GC_word *) vm->sp; word++)
520 mark_stack_ptr = GC_MARK_AND_PUSH ((* (GC_word **) word),
521 mark_stack_ptr, mark_stack_limit,
522 NULL);
523
524 return mark_stack_ptr;
525}
526
527#endif /* VM_ENABLE_PRECISE_STACK_GC_SCAN */
528
529
6d14383e 530SCM
4abef68f 531scm_c_vm_run (SCM vm, SCM program, SCM *argv, int nargs)
6d14383e 532{
4abef68f 533 struct scm_vm *vp = SCM_VM_DATA (vm);
7656f194 534 return vm_engines[vp->engine](vm, program, argv, nargs);
6d14383e
AW
535}
536
6f3b0cc2
AW
537SCM_DEFINE (scm_vm_apply, "vm-apply", 3, 0, 0,
538 (SCM vm, SCM program, SCM args),
539 "")
540#define FUNC_NAME s_scm_vm_apply
a98cef7e 541{
6d14383e
AW
542 SCM *argv;
543 int i, nargs;
544
545 SCM_VALIDATE_VM (1, vm);
67e2d80a 546 SCM_VALIDATE_PROC (2, program);
6d14383e
AW
547
548 nargs = scm_ilength (args);
549 if (SCM_UNLIKELY (nargs < 0))
550 scm_wrong_type_arg_msg (FUNC_NAME, 3, args, "list");
551
552 argv = alloca(nargs * sizeof(SCM));
553 for (i = 0; i < nargs; i++)
554 {
555 argv[i] = SCM_CAR (args);
556 args = SCM_CDR (args);
557 }
558
4abef68f 559 return scm_c_vm_run (vm, program, argv, nargs);
a98cef7e 560}
17e90c5e 561#undef FUNC_NAME
a98cef7e
KN
562
563/* Scheme interface */
564
565SCM_DEFINE (scm_vm_version, "vm-version", 0, 0, 0,
17e90c5e
KN
566 (void),
567 "")
a98cef7e
KN
568#define FUNC_NAME s_scm_vm_version
569{
d3518113 570 return scm_from_locale_string (PACKAGE_VERSION);
a98cef7e
KN
571}
572#undef FUNC_NAME
573
499a4c07 574SCM_DEFINE (scm_the_vm, "the-vm", 0, 0, 0,
fcd4901b 575 (void),
499a4c07
KN
576 "")
577#define FUNC_NAME s_scm_the_vm
578{
2bbe1533 579 scm_i_thread *t = SCM_I_CURRENT_THREAD;
f63ea2ce 580
8b22ed7a 581 if (SCM_UNLIKELY (scm_is_false ((t->vm))))
2bbe1533 582 t->vm = make_vm ();
f63ea2ce 583
2bbe1533 584 return t->vm;
499a4c07
KN
585}
586#undef FUNC_NAME
587
588
a98cef7e
KN
589SCM_DEFINE (scm_vm_p, "vm?", 1, 0, 0,
590 (SCM obj),
17e90c5e 591 "")
a98cef7e
KN
592#define FUNC_NAME s_scm_vm_p
593{
9bd48cb1 594 return scm_from_bool (SCM_VM_P (obj));
a98cef7e
KN
595}
596#undef FUNC_NAME
597
598SCM_DEFINE (scm_make_vm, "make-vm", 0, 0, 0,
17e90c5e
KN
599 (void),
600 "")
601#define FUNC_NAME s_scm_make_vm,
a98cef7e 602{
17e90c5e 603 return make_vm ();
a98cef7e
KN
604}
605#undef FUNC_NAME
606
17e90c5e 607SCM_DEFINE (scm_vm_ip, "vm:ip", 1, 0, 0,
a98cef7e 608 (SCM vm),
17e90c5e
KN
609 "")
610#define FUNC_NAME s_scm_vm_ip
a98cef7e
KN
611{
612 SCM_VALIDATE_VM (1, vm);
f41cb00c 613 return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->ip);
a98cef7e
KN
614}
615#undef FUNC_NAME
616
617SCM_DEFINE (scm_vm_sp, "vm:sp", 1, 0, 0,
618 (SCM vm),
17e90c5e 619 "")
a98cef7e
KN
620#define FUNC_NAME s_scm_vm_sp
621{
622 SCM_VALIDATE_VM (1, vm);
f41cb00c 623 return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->sp);
a98cef7e
KN
624}
625#undef FUNC_NAME
626
627SCM_DEFINE (scm_vm_fp, "vm:fp", 1, 0, 0,
628 (SCM vm),
17e90c5e 629 "")
a98cef7e
KN
630#define FUNC_NAME s_scm_vm_fp
631{
632 SCM_VALIDATE_VM (1, vm);
f41cb00c 633 return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->fp);
a98cef7e
KN
634}
635#undef FUNC_NAME
636
17e90c5e
KN
637#define VM_DEFINE_HOOK(n) \
638{ \
3d5ee0cd 639 struct scm_vm *vp; \
17e90c5e 640 SCM_VALIDATE_VM (1, vm); \
3d5ee0cd 641 vp = SCM_VM_DATA (vm); \
8b22ed7a 642 if (scm_is_false (vp->hooks[n])) \
238e7a11 643 vp->hooks[n] = scm_make_hook (SCM_I_MAKINUM (1)); \
3d5ee0cd 644 return vp->hooks[n]; \
17e90c5e
KN
645}
646
647SCM_DEFINE (scm_vm_boot_hook, "vm-boot-hook", 1, 0, 0,
a98cef7e 648 (SCM vm),
17e90c5e
KN
649 "")
650#define FUNC_NAME s_scm_vm_boot_hook
a98cef7e 651{
17e90c5e 652 VM_DEFINE_HOOK (SCM_VM_BOOT_HOOK);
a98cef7e
KN
653}
654#undef FUNC_NAME
655
17e90c5e
KN
656SCM_DEFINE (scm_vm_halt_hook, "vm-halt-hook", 1, 0, 0,
657 (SCM vm),
658 "")
659#define FUNC_NAME s_scm_vm_halt_hook
a98cef7e 660{
17e90c5e 661 VM_DEFINE_HOOK (SCM_VM_HALT_HOOK);
a98cef7e
KN
662}
663#undef FUNC_NAME
664
17e90c5e 665SCM_DEFINE (scm_vm_next_hook, "vm-next-hook", 1, 0, 0,
a98cef7e 666 (SCM vm),
17e90c5e
KN
667 "")
668#define FUNC_NAME s_scm_vm_next_hook
a98cef7e 669{
17e90c5e 670 VM_DEFINE_HOOK (SCM_VM_NEXT_HOOK);
a98cef7e
KN
671}
672#undef FUNC_NAME
673
7a0d0cee
KN
674SCM_DEFINE (scm_vm_break_hook, "vm-break-hook", 1, 0, 0,
675 (SCM vm),
676 "")
677#define FUNC_NAME s_scm_vm_break_hook
678{
679 VM_DEFINE_HOOK (SCM_VM_BREAK_HOOK);
680}
681#undef FUNC_NAME
682
17e90c5e
KN
683SCM_DEFINE (scm_vm_enter_hook, "vm-enter-hook", 1, 0, 0,
684 (SCM vm),
685 "")
686#define FUNC_NAME s_scm_vm_enter_hook
a98cef7e 687{
17e90c5e 688 VM_DEFINE_HOOK (SCM_VM_ENTER_HOOK);
a98cef7e
KN
689}
690#undef FUNC_NAME
691
17e90c5e
KN
692SCM_DEFINE (scm_vm_apply_hook, "vm-apply-hook", 1, 0, 0,
693 (SCM vm),
694 "")
695#define FUNC_NAME s_scm_vm_apply_hook
a98cef7e 696{
17e90c5e 697 VM_DEFINE_HOOK (SCM_VM_APPLY_HOOK);
a98cef7e
KN
698}
699#undef FUNC_NAME
700
17e90c5e 701SCM_DEFINE (scm_vm_exit_hook, "vm-exit-hook", 1, 0, 0,
a98cef7e 702 (SCM vm),
17e90c5e
KN
703 "")
704#define FUNC_NAME s_scm_vm_exit_hook
a98cef7e 705{
17e90c5e 706 VM_DEFINE_HOOK (SCM_VM_EXIT_HOOK);
a98cef7e
KN
707}
708#undef FUNC_NAME
709
17e90c5e 710SCM_DEFINE (scm_vm_return_hook, "vm-return-hook", 1, 0, 0,
a98cef7e 711 (SCM vm),
17e90c5e
KN
712 "")
713#define FUNC_NAME s_scm_vm_return_hook
a98cef7e 714{
17e90c5e 715 VM_DEFINE_HOOK (SCM_VM_RETURN_HOOK);
a98cef7e
KN
716}
717#undef FUNC_NAME
718
17e90c5e
KN
719SCM_DEFINE (scm_vm_option, "vm-option", 2, 0, 0,
720 (SCM vm, SCM key),
721 "")
722#define FUNC_NAME s_scm_vm_option
a98cef7e
KN
723{
724 SCM_VALIDATE_VM (1, vm);
17e90c5e 725 return scm_assq_ref (SCM_VM_DATA (vm)->options, key);
a98cef7e
KN
726}
727#undef FUNC_NAME
728
17e90c5e
KN
729SCM_DEFINE (scm_set_vm_option_x, "set-vm-option!", 3, 0, 0,
730 (SCM vm, SCM key, SCM val),
731 "")
732#define FUNC_NAME s_scm_set_vm_option_x
a98cef7e
KN
733{
734 SCM_VALIDATE_VM (1, vm);
17e90c5e
KN
735 SCM_VM_DATA (vm)->options
736 = scm_assq_set_x (SCM_VM_DATA (vm)->options, key, val);
737 return SCM_UNSPECIFIED;
a98cef7e
KN
738}
739#undef FUNC_NAME
740
7656f194 741SCM_DEFINE (scm_vm_trace_level, "vm-trace-level", 1, 0, 0,
17e90c5e
KN
742 (SCM vm),
743 "")
7656f194 744#define FUNC_NAME s_scm_vm_trace_level
a98cef7e 745{
a98cef7e 746 SCM_VALIDATE_VM (1, vm);
7656f194
AW
747 return scm_from_int (SCM_VM_DATA (vm)->trace_level);
748}
749#undef FUNC_NAME
750
751SCM_DEFINE (scm_set_vm_trace_level_x, "set-vm-trace-level!", 2, 0, 0,
752 (SCM vm, SCM level),
753 "")
754#define FUNC_NAME s_scm_set_vm_trace_level_x
755{
756 SCM_VALIDATE_VM (1, vm);
757 SCM_VM_DATA (vm)->trace_level = scm_to_int (level);
758 return SCM_UNSPECIFIED;
a98cef7e
KN
759}
760#undef FUNC_NAME
761
762\f
763/*
17e90c5e 764 * Initialize
a98cef7e
KN
765 */
766
07e56b27
AW
767SCM scm_load_compiled_with_vm (SCM file)
768{
53e28ed9 769 SCM program = scm_make_program (scm_load_objcode (file),
20d47c39 770 SCM_BOOL_F, SCM_BOOL_F);
07e56b27 771
4abef68f 772 return scm_c_vm_run (scm_the_vm (), program, NULL, 0);
07e56b27
AW
773}
774
17e90c5e 775void
07e56b27 776scm_bootstrap_vm (void)
17e90c5e 777{
44602b08
AW
778 scm_c_register_extension ("libguile-" SCM_EFFECTIVE_VERSION,
779 "scm_init_vm",
60ae5ca2
AW
780 (scm_t_extension_init_func)scm_init_vm, NULL);
781
35ac7852
AW
782 sym_vm_run = scm_from_locale_symbol ("vm-run");
783 sym_vm_error = scm_from_locale_symbol ("vm-error");
784 sym_keyword_argument_error = scm_from_locale_symbol ("keyword-argument-error");
785 sym_debug = scm_from_locale_symbol ("debug");
0404c97d 786
e3eb628d
LC
787#ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
788 vm_stack_gc_kind =
789 GC_new_kind (GC_new_free_list (),
790 GC_MAKE_PROC (GC_new_proc (vm_stack_mark), 0),
791 0, 1);
792
793#endif
07e56b27
AW
794}
795
796void
797scm_init_vm (void)
798{
17e90c5e 799#ifndef SCM_MAGIC_SNARFER
aeeff258 800#include "libguile/vm.x"
17e90c5e 801#endif
a98cef7e 802}
17e90c5e
KN
803
804/*
805 Local Variables:
806 c-file-style: "gnu"
807 End:
808*/