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