in debug mode, make sure that calls to the vm can be captured via make-stack
[bpt/guile.git] / libguile / vm.c
CommitLineData
8f5cfc81 1/* Copyright (C) 2001 Free Software Foundation, Inc.
a98cef7e
KN
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
6 * any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; see the file COPYING. If not, write to
15 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
17 *
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
20 *
21 * The exception is that, if you link the GUILE library with other files
22 * to produce an executable, this does not by itself cause the
23 * resulting executable to be covered by the GNU General Public License.
24 * Your use of that executable is in no way restricted on account of
25 * linking the GUILE library code into it.
26 *
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
29 *
30 * This exception applies only to the code released by the
31 * Free Software Foundation under the name GUILE. If you copy
32 * code from other Free Software Foundation releases into a copy of
33 * GUILE, as the General Public License permits, the exception does
34 * not apply to the code that you add in this way. To avoid misleading
35 * anyone as to the status of such modified files, you must delete
36 * this exception notice from them.
37 *
38 * If you write modifications of your own for GUILE, it is your choice
39 * whether to permit this exception to apply to your modifications.
40 * If you do not wish that, delete this exception notice. */
41
13c47753
AW
42#if HAVE_CONFIG_H
43# include <config.h>
44#endif
45
6d14383e 46#include <alloca.h>
17e90c5e 47#include <string.h>
83495480 48#include "vm-bootstrap.h"
ac99cb0c 49#include "frames.h"
17e90c5e 50#include "instructions.h"
8f5cfc81 51#include "objcodes.h"
ac99cb0c 52#include "programs.h"
fb10a008 53#include "lang.h" /* NULL_OR_NIL_P */
a98cef7e
KN
54#include "vm.h"
55
a98cef7e
KN
56/* I sometimes use this for debugging. */
57#define vm_puts(OBJ) \
58{ \
22bcbe8c
AW
59 scm_display (OBJ, scm_current_error_port ()); \
60 scm_newline (scm_current_error_port ()); \
a98cef7e
KN
61}
62
11ea1aba
AW
63/* The VM has a number of internal assertions that shouldn't normally be
64 necessary, but might be if you think you found a bug in the VM. */
65#define VM_ENABLE_ASSERTIONS
66
67/* We can add a mode that ensures that all stack items above the stack pointer
68 are NULL. This is useful for checking the internal consistency of the VM's
69 assumptions and its operators, but isn't necessary for normal operation. It
616167fc 70 will ensure that assertions are enabled. Slows down the VM by about 30%. */
747a1635 71/* NB! If you enable this, search for NULLING in throw.c */
616167fc 72/* #define VM_ENABLE_STACK_NULLING */
11ea1aba 73
53e28ed9
AW
74/* #define VM_ENABLE_PARANOID_ASSERTIONS */
75
11ea1aba
AW
76#if defined (VM_ENABLE_STACK_NULLING) && !defined (VM_ENABLE_ASSERTIONS)
77#define VM_ENABLE_ASSERTIONS
78#endif
79
a98cef7e 80\f
a98cef7e
KN
81/*
82 * VM Continuation
83 */
84
f9e8c09d 85scm_t_bits scm_tc16_vm_cont;
17e90c5e 86
11ea1aba
AW
87static void
88vm_mark_stack (SCM *base, scm_t_ptrdiff size, SCM *fp, scm_t_ptrdiff reloc)
89{
90 SCM *sp, *upper, *lower;
91 sp = base + size - 1;
92
93 while (sp > base && fp)
94 {
95 upper = SCM_FRAME_UPPER_ADDRESS (fp);
96 lower = SCM_FRAME_LOWER_ADDRESS (fp);
97
98 for (; sp >= upper; sp--)
99 if (SCM_NIMP (*sp))
100 {
101 if (scm_in_heap_p (*sp))
102 scm_gc_mark (*sp);
103 else
104 fprintf (stderr, "BADNESS: crap on the stack: %p\n", *sp);
105 }
106
107
108 /* skip ra, mvra */
109 sp -= 2;
110
111 /* update fp from the dynamic link */
112 fp = (SCM*)*sp-- + reloc;
113
b1b942b7 114 /* mark from the el down to the lower address */
11ea1aba
AW
115 for (; sp >= lower; sp--)
116 if (*sp && SCM_NIMP (*sp))
117 scm_gc_mark (*sp);
118 }
119}
120
bfffd258
AW
121static SCM
122vm_cont_mark (SCM obj)
123{
11ea1aba 124 struct scm_vm_cont *p = SCM_VM_CONT_DATA (obj);
bfffd258 125
7aa6f86b
AW
126 if (p->stack_size)
127 vm_mark_stack (p->stack_base, p->stack_size, p->fp + p->reloc, p->reloc);
bfffd258
AW
128
129 return SCM_BOOL_F;
130}
131
132static scm_sizet
133vm_cont_free (SCM obj)
134{
135 struct scm_vm_cont *p = SCM_VM_CONT_DATA (obj);
136
137 scm_gc_free (p->stack_base, p->stack_size * sizeof (SCM), "stack-base");
138 scm_gc_free (p, sizeof (struct scm_vm), "vm");
139
140 return 0;
141}
a98cef7e
KN
142
143static SCM
3d5ee0cd 144capture_vm_cont (struct scm_vm *vp)
a98cef7e 145{
bfffd258
AW
146 struct scm_vm_cont *p = scm_gc_malloc (sizeof (*p), "capture_vm_cont");
147 p->stack_size = vp->sp - vp->stack_base + 1;
d8eeb67c
LC
148 p->stack_base = scm_gc_malloc (p->stack_size * sizeof (SCM),
149 "capture_vm_cont");
11ea1aba 150#ifdef VM_ENABLE_STACK_NULLING
66db076a
AW
151 if (vp->sp >= vp->stack_base)
152 if (!vp->sp[0] || vp->sp[1])
153 abort ();
11ea1aba
AW
154 memset (p->stack_base, 0, p->stack_size * sizeof (SCM));
155#endif
3d5ee0cd 156 p->ip = vp->ip;
7aa6f86b
AW
157 p->sp = vp->sp;
158 p->fp = vp->fp;
bfffd258 159 memcpy (p->stack_base, vp->stack_base, p->stack_size * sizeof (SCM));
11ea1aba 160 p->reloc = p->stack_base - vp->stack_base;
17e90c5e 161 SCM_RETURN_NEWSMOB (scm_tc16_vm_cont, p);
a98cef7e
KN
162}
163
164static void
3d5ee0cd 165reinstate_vm_cont (struct scm_vm *vp, SCM cont)
a98cef7e 166{
bfffd258 167 struct scm_vm_cont *p = SCM_VM_CONT_DATA (cont);
3d5ee0cd 168 if (vp->stack_size < p->stack_size)
a98cef7e 169 {
17e90c5e 170 /* puts ("FIXME: Need to expand"); */
a98cef7e
KN
171 abort ();
172 }
11ea1aba
AW
173#ifdef VM_ENABLE_STACK_NULLING
174 {
7aa6f86b 175 scm_t_ptrdiff nzero = (vp->sp - p->sp);
11ea1aba 176 if (nzero > 0)
66db076a
AW
177 memset (vp->stack_base + p->stack_size, 0, nzero * sizeof (SCM));
178 /* actually nzero should always be negative, because vm_reset_stack will
179 unwind the stack to some point *below* this continuation */
11ea1aba
AW
180 }
181#endif
3d5ee0cd 182 vp->ip = p->ip;
7aa6f86b
AW
183 vp->sp = p->sp;
184 vp->fp = p->fp;
bfffd258
AW
185 memcpy (vp->stack_base, p->stack_base, p->stack_size * sizeof (SCM));
186}
187
188/* In theory, a number of vm instances can be active in the call trace, and we
189 only want to reify the continuations of those in the current continuation
190 root. I don't see a nice way to do this -- ideally it would involve dynwinds,
191 and previous values of the *the-vm* fluid within the current continuation
192 root. But we don't have access to continuation roots in the dynwind stack.
193 So, just punt for now -- take the current value of *the-vm*.
194
195 While I'm on the topic, ideally we could avoid copying the C stack if the
196 continuation root is inside VM code, and call/cc was invoked within that same
197 call to vm_run; but that's currently not implemented.
198 */
199SCM
200scm_vm_capture_continuations (void)
201{
202 SCM vm = scm_the_vm ();
203 return scm_acons (vm, capture_vm_cont (SCM_VM_DATA (vm)), SCM_EOL);
204}
205
206void
207scm_vm_reinstate_continuations (SCM conts)
208{
209 for (; conts != SCM_EOL; conts = SCM_CDR (conts))
210 reinstate_vm_cont (SCM_VM_DATA (SCM_CAAR (conts)), SCM_CDAR (conts));
a98cef7e
KN
211}
212
b1b942b7
AW
213static void enfalsen_frame (void *p)
214{
215 struct scm_vm *vp = p;
216 vp->trace_frame = SCM_BOOL_F;
217}
218
219static void
6d14383e 220vm_dispatch_hook (struct scm_vm *vp, SCM hook, SCM hook_args)
b1b942b7 221{
b1b942b7
AW
222 if (!SCM_FALSEP (vp->trace_frame))
223 return;
224
225 scm_dynwind_begin (0);
6d14383e
AW
226 // FIXME, stack holder should be the vm
227 vp->trace_frame = scm_c_make_vm_frame (SCM_BOOL_F, vp->fp, vp->sp, vp->ip, 0);
b1b942b7
AW
228 scm_dynwind_unwind_handler (enfalsen_frame, vp, SCM_F_WIND_EXPLICITLY);
229
230 scm_c_run_hook (hook, hook_args);
231
232 scm_dynwind_end ();
233}
234
17e90c5e
KN
235\f
236/*
237 * VM Internal functions
238 */
239
90b0be20
AW
240static SCM sym_vm_run;
241static SCM sym_vm_error;
242static SCM sym_debug;
17e90c5e 243
53e28ed9 244static SCM make_u8vector (const scm_t_uint8 *bytes, size_t len)
a98cef7e 245{
53e28ed9
AW
246 scm_t_uint8 *new_bytes = scm_gc_malloc (len, "make-u8vector");
247 memcpy (new_bytes, bytes, len);
248 return scm_take_u8vector (new_bytes, len);
a98cef7e
KN
249}
250
2fda0242 251static SCM
d2d7acd5 252really_make_boot_program (long nargs)
2fda0242 253{
53e28ed9 254 scm_byte_t bytes[] = {0, 0, 0, 0,
9aeaabdc 255 0, 0, 0, 0,
53e28ed9
AW
256 0, 0, 0, 0,
257 scm_op_mv_call, 0, 0, 1, scm_op_make_int8_1, scm_op_halt};
9aeaabdc 258 ((scm_t_uint32*)bytes)[1] = 6; /* set len in current endianness, no meta */
53e28ed9 259 if (SCM_UNLIKELY (nargs > 255 || nargs < 0))
2fda0242 260 abort ();
9aeaabdc 261 bytes[13] = (scm_byte_t)nargs;
53e28ed9
AW
262 return scm_make_program (scm_bytecode_to_objcode (make_u8vector (bytes, sizeof(bytes))),
263 SCM_BOOL_F, SCM_EOL);
2fda0242 264}
d2d7acd5
AW
265#define NUM_BOOT_PROGS 8
266static SCM
267vm_make_boot_program (long nargs)
268{
269 static SCM programs[NUM_BOOT_PROGS] = { 0, };
270
271 if (SCM_UNLIKELY (!programs[0]))
272 {
273 int i;
274 for (i = 0; i < NUM_BOOT_PROGS; i++)
275 programs[i] = scm_permanent_object (really_make_boot_program (i));
276 }
277
278 if (SCM_LIKELY (nargs < NUM_BOOT_PROGS))
279 return programs[nargs];
280 else
281 return really_make_boot_program (nargs);
282}
2fda0242 283
a98cef7e
KN
284\f
285/*
286 * VM
287 */
288
c0a25ecc 289#define VM_DEFAULT_STACK_SIZE (16 * 1024)
17e90c5e 290
17e90c5e 291#define VM_NAME vm_regular_engine
6d14383e
AW
292#define FUNC_NAME "vm-regular-engine"
293#define VM_ENGINE SCM_VM_REGULAR_ENGINE
83495480 294#include "vm-engine.c"
17e90c5e 295#undef VM_NAME
6d14383e 296#undef FUNC_NAME
17e90c5e 297#undef VM_ENGINE
17e90c5e
KN
298
299#define VM_NAME vm_debug_engine
6d14383e
AW
300#define FUNC_NAME "vm-debug-engine"
301#define VM_ENGINE SCM_VM_DEBUG_ENGINE
83495480 302#include "vm-engine.c"
17e90c5e 303#undef VM_NAME
6d14383e 304#undef FUNC_NAME
17e90c5e
KN
305#undef VM_ENGINE
306
6d14383e
AW
307static const scm_t_vm_engine vm_engines[] =
308 { vm_regular_engine, vm_debug_engine };
309
f9e8c09d 310scm_t_bits scm_tc16_vm;
a98cef7e
KN
311
312static SCM
17e90c5e
KN
313make_vm (void)
314#define FUNC_NAME "make_vm"
a98cef7e 315{
17e90c5e 316 int i;
747a1635
AW
317
318 if (!scm_tc16_vm)
319 return SCM_BOOL_F; /* not booted yet */
320
d8eeb67c
LC
321 struct scm_vm *vp = scm_gc_malloc (sizeof (struct scm_vm), "vm");
322
3d5ee0cd 323 vp->stack_size = VM_DEFAULT_STACK_SIZE;
d8eeb67c
LC
324 vp->stack_base = scm_gc_malloc (vp->stack_size * sizeof (SCM),
325 "stack-base");
2bbe1533
AW
326#ifdef VM_ENABLE_STACK_NULLING
327 memset (vp->stack_base, 0, vp->stack_size * sizeof (SCM));
328#endif
3616e9e9
KN
329 vp->stack_limit = vp->stack_base + vp->stack_size - 3;
330 vp->ip = NULL;
331 vp->sp = vp->stack_base - 1;
332 vp->fp = NULL;
6d14383e 333 vp->engine = SCM_VM_DEBUG_ENGINE;
3d5ee0cd
KN
334 vp->time = 0;
335 vp->clock = 0;
336 vp->options = SCM_EOL;
17e90c5e 337 for (i = 0; i < SCM_VM_NUM_HOOKS; i++)
3d5ee0cd 338 vp->hooks[i] = SCM_BOOL_F;
b1b942b7 339 vp->trace_frame = SCM_BOOL_F;
3d5ee0cd 340 SCM_RETURN_NEWSMOB (scm_tc16_vm, vp);
a98cef7e 341}
17e90c5e 342#undef FUNC_NAME
a98cef7e
KN
343
344static SCM
17e90c5e 345vm_mark (SCM obj)
a98cef7e 346{
17e90c5e 347 int i;
3d5ee0cd 348 struct scm_vm *vp = SCM_VM_DATA (obj);
17e90c5e 349
11ea1aba
AW
350#ifdef VM_ENABLE_STACK_NULLING
351 if (vp->sp >= vp->stack_base)
352 if (!vp->sp[0] || vp->sp[1])
353 abort ();
354#endif
355
356 /* mark the stack, precisely */
357 vm_mark_stack (vp->stack_base, vp->sp + 1 - vp->stack_base, vp->fp, 0);
a98cef7e 358
af988bbf 359 /* mark other objects */
17e90c5e 360 for (i = 0; i < SCM_VM_NUM_HOOKS; i++)
3d5ee0cd 361 scm_gc_mark (vp->hooks[i]);
b1b942b7
AW
362
363 scm_gc_mark (vp->trace_frame);
364
3d5ee0cd 365 return vp->options;
a98cef7e
KN
366}
367
17e90c5e
KN
368static scm_sizet
369vm_free (SCM obj)
370{
3d5ee0cd 371 struct scm_vm *vp = SCM_VM_DATA (obj);
d8eeb67c
LC
372
373 scm_gc_free (vp->stack_base, vp->stack_size * sizeof (SCM),
374 "stack-base");
375 scm_gc_free (vp, sizeof (struct scm_vm), "vm");
376
377 return 0;
17e90c5e
KN
378}
379
6d14383e 380SCM
4abef68f 381scm_c_vm_run (SCM vm, SCM program, SCM *argv, int nargs)
6d14383e 382{
4abef68f 383 struct scm_vm *vp = SCM_VM_DATA (vm);
6d14383e
AW
384 return vm_engines[vp->engine](vp, program, argv, nargs);
385}
386
17e90c5e
KN
387SCM
388scm_vm_apply (SCM vm, SCM program, SCM args)
389#define FUNC_NAME "scm_vm_apply"
a98cef7e 390{
6d14383e
AW
391 SCM *argv;
392 int i, nargs;
393
394 SCM_VALIDATE_VM (1, vm);
395 SCM_VALIDATE_PROGRAM (2, program);
396
397 nargs = scm_ilength (args);
398 if (SCM_UNLIKELY (nargs < 0))
399 scm_wrong_type_arg_msg (FUNC_NAME, 3, args, "list");
400
401 argv = alloca(nargs * sizeof(SCM));
402 for (i = 0; i < nargs; i++)
403 {
404 argv[i] = SCM_CAR (args);
405 args = SCM_CDR (args);
406 }
407
4abef68f 408 return scm_c_vm_run (vm, program, argv, nargs);
a98cef7e 409}
17e90c5e 410#undef FUNC_NAME
a98cef7e
KN
411
412/* Scheme interface */
413
414SCM_DEFINE (scm_vm_version, "vm-version", 0, 0, 0,
17e90c5e
KN
415 (void),
416 "")
a98cef7e
KN
417#define FUNC_NAME s_scm_vm_version
418{
d3518113 419 return scm_from_locale_string (PACKAGE_VERSION);
a98cef7e
KN
420}
421#undef FUNC_NAME
422
499a4c07 423SCM_DEFINE (scm_the_vm, "the-vm", 0, 0, 0,
fcd4901b 424 (void),
499a4c07
KN
425 "")
426#define FUNC_NAME s_scm_the_vm
427{
2bbe1533 428 scm_i_thread *t = SCM_I_CURRENT_THREAD;
f63ea2ce 429
2bbe1533
AW
430 if (SCM_UNLIKELY (SCM_FALSEP ((t->vm))))
431 t->vm = make_vm ();
f63ea2ce 432
2bbe1533 433 return t->vm;
499a4c07
KN
434}
435#undef FUNC_NAME
436
437
a98cef7e
KN
438SCM_DEFINE (scm_vm_p, "vm?", 1, 0, 0,
439 (SCM obj),
17e90c5e 440 "")
a98cef7e
KN
441#define FUNC_NAME s_scm_vm_p
442{
443 return SCM_BOOL (SCM_VM_P (obj));
444}
445#undef FUNC_NAME
446
447SCM_DEFINE (scm_make_vm, "make-vm", 0, 0, 0,
17e90c5e
KN
448 (void),
449 "")
450#define FUNC_NAME s_scm_make_vm,
a98cef7e 451{
17e90c5e 452 return make_vm ();
a98cef7e
KN
453}
454#undef FUNC_NAME
455
17e90c5e 456SCM_DEFINE (scm_vm_ip, "vm:ip", 1, 0, 0,
a98cef7e 457 (SCM vm),
17e90c5e
KN
458 "")
459#define FUNC_NAME s_scm_vm_ip
a98cef7e
KN
460{
461 SCM_VALIDATE_VM (1, vm);
f41cb00c 462 return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->ip);
a98cef7e
KN
463}
464#undef FUNC_NAME
465
466SCM_DEFINE (scm_vm_sp, "vm:sp", 1, 0, 0,
467 (SCM vm),
17e90c5e 468 "")
a98cef7e
KN
469#define FUNC_NAME s_scm_vm_sp
470{
471 SCM_VALIDATE_VM (1, vm);
f41cb00c 472 return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->sp);
a98cef7e
KN
473}
474#undef FUNC_NAME
475
476SCM_DEFINE (scm_vm_fp, "vm:fp", 1, 0, 0,
477 (SCM vm),
17e90c5e 478 "")
a98cef7e
KN
479#define FUNC_NAME s_scm_vm_fp
480{
481 SCM_VALIDATE_VM (1, vm);
f41cb00c 482 return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->fp);
a98cef7e
KN
483}
484#undef FUNC_NAME
485
17e90c5e
KN
486#define VM_DEFINE_HOOK(n) \
487{ \
3d5ee0cd 488 struct scm_vm *vp; \
17e90c5e 489 SCM_VALIDATE_VM (1, vm); \
3d5ee0cd
KN
490 vp = SCM_VM_DATA (vm); \
491 if (SCM_FALSEP (vp->hooks[n])) \
238e7a11 492 vp->hooks[n] = scm_make_hook (SCM_I_MAKINUM (1)); \
3d5ee0cd 493 return vp->hooks[n]; \
17e90c5e
KN
494}
495
496SCM_DEFINE (scm_vm_boot_hook, "vm-boot-hook", 1, 0, 0,
a98cef7e 497 (SCM vm),
17e90c5e
KN
498 "")
499#define FUNC_NAME s_scm_vm_boot_hook
a98cef7e 500{
17e90c5e 501 VM_DEFINE_HOOK (SCM_VM_BOOT_HOOK);
a98cef7e
KN
502}
503#undef FUNC_NAME
504
17e90c5e
KN
505SCM_DEFINE (scm_vm_halt_hook, "vm-halt-hook", 1, 0, 0,
506 (SCM vm),
507 "")
508#define FUNC_NAME s_scm_vm_halt_hook
a98cef7e 509{
17e90c5e 510 VM_DEFINE_HOOK (SCM_VM_HALT_HOOK);
a98cef7e
KN
511}
512#undef FUNC_NAME
513
17e90c5e 514SCM_DEFINE (scm_vm_next_hook, "vm-next-hook", 1, 0, 0,
a98cef7e 515 (SCM vm),
17e90c5e
KN
516 "")
517#define FUNC_NAME s_scm_vm_next_hook
a98cef7e 518{
17e90c5e 519 VM_DEFINE_HOOK (SCM_VM_NEXT_HOOK);
a98cef7e
KN
520}
521#undef FUNC_NAME
522
7a0d0cee
KN
523SCM_DEFINE (scm_vm_break_hook, "vm-break-hook", 1, 0, 0,
524 (SCM vm),
525 "")
526#define FUNC_NAME s_scm_vm_break_hook
527{
528 VM_DEFINE_HOOK (SCM_VM_BREAK_HOOK);
529}
530#undef FUNC_NAME
531
17e90c5e
KN
532SCM_DEFINE (scm_vm_enter_hook, "vm-enter-hook", 1, 0, 0,
533 (SCM vm),
534 "")
535#define FUNC_NAME s_scm_vm_enter_hook
a98cef7e 536{
17e90c5e 537 VM_DEFINE_HOOK (SCM_VM_ENTER_HOOK);
a98cef7e
KN
538}
539#undef FUNC_NAME
540
17e90c5e
KN
541SCM_DEFINE (scm_vm_apply_hook, "vm-apply-hook", 1, 0, 0,
542 (SCM vm),
543 "")
544#define FUNC_NAME s_scm_vm_apply_hook
a98cef7e 545{
17e90c5e 546 VM_DEFINE_HOOK (SCM_VM_APPLY_HOOK);
a98cef7e
KN
547}
548#undef FUNC_NAME
549
17e90c5e 550SCM_DEFINE (scm_vm_exit_hook, "vm-exit-hook", 1, 0, 0,
a98cef7e 551 (SCM vm),
17e90c5e
KN
552 "")
553#define FUNC_NAME s_scm_vm_exit_hook
a98cef7e 554{
17e90c5e 555 VM_DEFINE_HOOK (SCM_VM_EXIT_HOOK);
a98cef7e
KN
556}
557#undef FUNC_NAME
558
17e90c5e 559SCM_DEFINE (scm_vm_return_hook, "vm-return-hook", 1, 0, 0,
a98cef7e 560 (SCM vm),
17e90c5e
KN
561 "")
562#define FUNC_NAME s_scm_vm_return_hook
a98cef7e 563{
17e90c5e 564 VM_DEFINE_HOOK (SCM_VM_RETURN_HOOK);
a98cef7e
KN
565}
566#undef FUNC_NAME
567
17e90c5e
KN
568SCM_DEFINE (scm_vm_option, "vm-option", 2, 0, 0,
569 (SCM vm, SCM key),
570 "")
571#define FUNC_NAME s_scm_vm_option
a98cef7e
KN
572{
573 SCM_VALIDATE_VM (1, vm);
17e90c5e 574 return scm_assq_ref (SCM_VM_DATA (vm)->options, key);
a98cef7e
KN
575}
576#undef FUNC_NAME
577
17e90c5e
KN
578SCM_DEFINE (scm_set_vm_option_x, "set-vm-option!", 3, 0, 0,
579 (SCM vm, SCM key, SCM val),
580 "")
581#define FUNC_NAME s_scm_set_vm_option_x
a98cef7e
KN
582{
583 SCM_VALIDATE_VM (1, vm);
17e90c5e
KN
584 SCM_VM_DATA (vm)->options
585 = scm_assq_set_x (SCM_VM_DATA (vm)->options, key, val);
586 return SCM_UNSPECIFIED;
a98cef7e
KN
587}
588#undef FUNC_NAME
589
17e90c5e 590SCM_DEFINE (scm_vm_stats, "vm-stats", 1, 0, 0,
a98cef7e 591 (SCM vm),
17e90c5e
KN
592 "")
593#define FUNC_NAME s_scm_vm_stats
a98cef7e 594{
17e90c5e
KN
595 SCM stats;
596
a98cef7e 597 SCM_VALIDATE_VM (1, vm);
17e90c5e 598
2d80426a
LC
599 stats = scm_make_vector (SCM_I_MAKINUM (2), SCM_UNSPECIFIED);
600 scm_vector_set_x (stats, SCM_I_MAKINUM (0),
f9e8c09d 601 scm_from_ulong (SCM_VM_DATA (vm)->time));
2d80426a 602 scm_vector_set_x (stats, SCM_I_MAKINUM (1),
f9e8c09d 603 scm_from_ulong (SCM_VM_DATA (vm)->clock));
17e90c5e
KN
604
605 return stats;
a98cef7e
KN
606}
607#undef FUNC_NAME
608
b1b942b7 609SCM_DEFINE (scm_vm_trace_frame, "vm-trace-frame", 1, 0, 0,
17e90c5e
KN
610 (SCM vm),
611 "")
b1b942b7 612#define FUNC_NAME s_scm_vm_trace_frame
a98cef7e 613{
a98cef7e 614 SCM_VALIDATE_VM (1, vm);
b1b942b7 615 return SCM_VM_DATA (vm)->trace_frame;
a98cef7e
KN
616}
617#undef FUNC_NAME
618
619\f
620/*
17e90c5e 621 * Initialize
a98cef7e
KN
622 */
623
07e56b27
AW
624SCM scm_load_compiled_with_vm (SCM file)
625{
53e28ed9
AW
626 SCM program = scm_make_program (scm_load_objcode (file),
627 SCM_BOOL_F, SCM_EOL);
07e56b27 628
4abef68f 629 return scm_c_vm_run (scm_the_vm (), program, NULL, 0);
07e56b27
AW
630}
631
17e90c5e 632void
07e56b27 633scm_bootstrap_vm (void)
17e90c5e 634{
07e56b27
AW
635 static int strappage = 0;
636
637 if (strappage)
638 return;
639
640 scm_bootstrap_frames ();
641 scm_bootstrap_instructions ();
642 scm_bootstrap_objcodes ();
643 scm_bootstrap_programs ();
a98cef7e 644
17e90c5e
KN
645 scm_tc16_vm_cont = scm_make_smob_type ("vm-cont", 0);
646 scm_set_smob_mark (scm_tc16_vm_cont, vm_cont_mark);
647 scm_set_smob_free (scm_tc16_vm_cont, vm_cont_free);
a98cef7e 648
17e90c5e
KN
649 scm_tc16_vm = scm_make_smob_type ("vm", 0);
650 scm_set_smob_mark (scm_tc16_vm, vm_mark);
651 scm_set_smob_free (scm_tc16_vm, vm_free);
652 scm_set_smob_apply (scm_tc16_vm, scm_vm_apply, 1, 0, 1);
a98cef7e 653
83495480
AW
654 scm_c_define ("load-compiled",
655 scm_c_make_gsubr ("load-compiled/vm", 1, 0, 0,
656 scm_load_compiled_with_vm));
07e56b27 657
90b0be20
AW
658 sym_vm_run = scm_permanent_object (scm_from_locale_symbol ("vm-run"));
659 sym_vm_error = scm_permanent_object (scm_from_locale_symbol ("vm-error"));
660 sym_debug = scm_permanent_object (scm_from_locale_symbol ("debug"));
661
07e56b27
AW
662 strappage = 1;
663}
664
665void
666scm_init_vm (void)
667{
668 scm_bootstrap_vm ();
669
17e90c5e 670#ifndef SCM_MAGIC_SNARFER
a98cef7e 671#include "vm.x"
17e90c5e 672#endif
a98cef7e 673}
17e90c5e
KN
674
675/*
676 Local Variables:
677 c-file-style: "gnu"
678 End:
679*/