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