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