fix distcheck hopefully, by cleaning the vm-i-*.i files
[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};
3b9e095b 258 SCM ret;
9aeaabdc 259 ((scm_t_uint32*)bytes)[1] = 6; /* set len in current endianness, no meta */
53e28ed9 260 if (SCM_UNLIKELY (nargs > 255 || nargs < 0))
2fda0242 261 abort ();
9aeaabdc 262 bytes[13] = (scm_byte_t)nargs;
3b9e095b
AW
263 ret = scm_make_program (scm_bytecode_to_objcode (make_u8vector (bytes, sizeof(bytes))),
264 SCM_BOOL_F, SCM_EOL);
265 SCM_SET_SMOB_FLAGS (ret, SCM_F_PROGRAM_IS_BOOT);
266 return ret;
2fda0242 267}
d2d7acd5
AW
268#define NUM_BOOT_PROGS 8
269static SCM
270vm_make_boot_program (long nargs)
271{
272 static SCM programs[NUM_BOOT_PROGS] = { 0, };
273
274 if (SCM_UNLIKELY (!programs[0]))
275 {
276 int i;
277 for (i = 0; i < NUM_BOOT_PROGS; i++)
278 programs[i] = scm_permanent_object (really_make_boot_program (i));
279 }
280
281 if (SCM_LIKELY (nargs < NUM_BOOT_PROGS))
282 return programs[nargs];
283 else
284 return really_make_boot_program (nargs);
285}
2fda0242 286
a98cef7e
KN
287\f
288/*
289 * VM
290 */
291
c0a25ecc 292#define VM_DEFAULT_STACK_SIZE (16 * 1024)
17e90c5e 293
17e90c5e 294#define VM_NAME vm_regular_engine
6d14383e
AW
295#define FUNC_NAME "vm-regular-engine"
296#define VM_ENGINE SCM_VM_REGULAR_ENGINE
83495480 297#include "vm-engine.c"
17e90c5e 298#undef VM_NAME
6d14383e 299#undef FUNC_NAME
17e90c5e 300#undef VM_ENGINE
17e90c5e
KN
301
302#define VM_NAME vm_debug_engine
6d14383e
AW
303#define FUNC_NAME "vm-debug-engine"
304#define VM_ENGINE SCM_VM_DEBUG_ENGINE
83495480 305#include "vm-engine.c"
17e90c5e 306#undef VM_NAME
6d14383e 307#undef FUNC_NAME
17e90c5e
KN
308#undef VM_ENGINE
309
6d14383e
AW
310static const scm_t_vm_engine vm_engines[] =
311 { vm_regular_engine, vm_debug_engine };
312
f9e8c09d 313scm_t_bits scm_tc16_vm;
a98cef7e
KN
314
315static SCM
17e90c5e
KN
316make_vm (void)
317#define FUNC_NAME "make_vm"
a98cef7e 318{
17e90c5e 319 int i;
747a1635
AW
320
321 if (!scm_tc16_vm)
322 return SCM_BOOL_F; /* not booted yet */
323
d8eeb67c
LC
324 struct scm_vm *vp = scm_gc_malloc (sizeof (struct scm_vm), "vm");
325
3d5ee0cd 326 vp->stack_size = VM_DEFAULT_STACK_SIZE;
d8eeb67c
LC
327 vp->stack_base = scm_gc_malloc (vp->stack_size * sizeof (SCM),
328 "stack-base");
2bbe1533
AW
329#ifdef VM_ENABLE_STACK_NULLING
330 memset (vp->stack_base, 0, vp->stack_size * sizeof (SCM));
331#endif
3616e9e9
KN
332 vp->stack_limit = vp->stack_base + vp->stack_size - 3;
333 vp->ip = NULL;
334 vp->sp = vp->stack_base - 1;
335 vp->fp = NULL;
6d14383e 336 vp->engine = SCM_VM_DEBUG_ENGINE;
3d5ee0cd
KN
337 vp->time = 0;
338 vp->clock = 0;
339 vp->options = SCM_EOL;
17e90c5e 340 for (i = 0; i < SCM_VM_NUM_HOOKS; i++)
3d5ee0cd 341 vp->hooks[i] = SCM_BOOL_F;
b1b942b7 342 vp->trace_frame = SCM_BOOL_F;
3d5ee0cd 343 SCM_RETURN_NEWSMOB (scm_tc16_vm, vp);
a98cef7e 344}
17e90c5e 345#undef FUNC_NAME
a98cef7e
KN
346
347static SCM
17e90c5e 348vm_mark (SCM obj)
a98cef7e 349{
17e90c5e 350 int i;
3d5ee0cd 351 struct scm_vm *vp = SCM_VM_DATA (obj);
17e90c5e 352
11ea1aba
AW
353#ifdef VM_ENABLE_STACK_NULLING
354 if (vp->sp >= vp->stack_base)
355 if (!vp->sp[0] || vp->sp[1])
356 abort ();
357#endif
358
359 /* mark the stack, precisely */
360 vm_mark_stack (vp->stack_base, vp->sp + 1 - vp->stack_base, vp->fp, 0);
a98cef7e 361
af988bbf 362 /* mark other objects */
17e90c5e 363 for (i = 0; i < SCM_VM_NUM_HOOKS; i++)
3d5ee0cd 364 scm_gc_mark (vp->hooks[i]);
b1b942b7
AW
365
366 scm_gc_mark (vp->trace_frame);
367
3d5ee0cd 368 return vp->options;
a98cef7e
KN
369}
370
17e90c5e
KN
371static scm_sizet
372vm_free (SCM obj)
373{
3d5ee0cd 374 struct scm_vm *vp = SCM_VM_DATA (obj);
d8eeb67c
LC
375
376 scm_gc_free (vp->stack_base, vp->stack_size * sizeof (SCM),
377 "stack-base");
378 scm_gc_free (vp, sizeof (struct scm_vm), "vm");
379
380 return 0;
17e90c5e
KN
381}
382
6d14383e 383SCM
4abef68f 384scm_c_vm_run (SCM vm, SCM program, SCM *argv, int nargs)
6d14383e 385{
4abef68f 386 struct scm_vm *vp = SCM_VM_DATA (vm);
6d14383e
AW
387 return vm_engines[vp->engine](vp, program, argv, nargs);
388}
389
17e90c5e
KN
390SCM
391scm_vm_apply (SCM vm, SCM program, SCM args)
392#define FUNC_NAME "scm_vm_apply"
a98cef7e 393{
6d14383e
AW
394 SCM *argv;
395 int i, nargs;
396
397 SCM_VALIDATE_VM (1, vm);
398 SCM_VALIDATE_PROGRAM (2, program);
399
400 nargs = scm_ilength (args);
401 if (SCM_UNLIKELY (nargs < 0))
402 scm_wrong_type_arg_msg (FUNC_NAME, 3, args, "list");
403
404 argv = alloca(nargs * sizeof(SCM));
405 for (i = 0; i < nargs; i++)
406 {
407 argv[i] = SCM_CAR (args);
408 args = SCM_CDR (args);
409 }
410
4abef68f 411 return scm_c_vm_run (vm, program, argv, nargs);
a98cef7e 412}
17e90c5e 413#undef FUNC_NAME
a98cef7e
KN
414
415/* Scheme interface */
416
417SCM_DEFINE (scm_vm_version, "vm-version", 0, 0, 0,
17e90c5e
KN
418 (void),
419 "")
a98cef7e
KN
420#define FUNC_NAME s_scm_vm_version
421{
d3518113 422 return scm_from_locale_string (PACKAGE_VERSION);
a98cef7e
KN
423}
424#undef FUNC_NAME
425
499a4c07 426SCM_DEFINE (scm_the_vm, "the-vm", 0, 0, 0,
fcd4901b 427 (void),
499a4c07
KN
428 "")
429#define FUNC_NAME s_scm_the_vm
430{
2bbe1533 431 scm_i_thread *t = SCM_I_CURRENT_THREAD;
f63ea2ce 432
2bbe1533
AW
433 if (SCM_UNLIKELY (SCM_FALSEP ((t->vm))))
434 t->vm = make_vm ();
f63ea2ce 435
2bbe1533 436 return t->vm;
499a4c07
KN
437}
438#undef FUNC_NAME
439
440
a98cef7e
KN
441SCM_DEFINE (scm_vm_p, "vm?", 1, 0, 0,
442 (SCM obj),
17e90c5e 443 "")
a98cef7e
KN
444#define FUNC_NAME s_scm_vm_p
445{
446 return SCM_BOOL (SCM_VM_P (obj));
447}
448#undef FUNC_NAME
449
450SCM_DEFINE (scm_make_vm, "make-vm", 0, 0, 0,
17e90c5e
KN
451 (void),
452 "")
453#define FUNC_NAME s_scm_make_vm,
a98cef7e 454{
17e90c5e 455 return make_vm ();
a98cef7e
KN
456}
457#undef FUNC_NAME
458
17e90c5e 459SCM_DEFINE (scm_vm_ip, "vm:ip", 1, 0, 0,
a98cef7e 460 (SCM vm),
17e90c5e
KN
461 "")
462#define FUNC_NAME s_scm_vm_ip
a98cef7e
KN
463{
464 SCM_VALIDATE_VM (1, vm);
f41cb00c 465 return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->ip);
a98cef7e
KN
466}
467#undef FUNC_NAME
468
469SCM_DEFINE (scm_vm_sp, "vm:sp", 1, 0, 0,
470 (SCM vm),
17e90c5e 471 "")
a98cef7e
KN
472#define FUNC_NAME s_scm_vm_sp
473{
474 SCM_VALIDATE_VM (1, vm);
f41cb00c 475 return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->sp);
a98cef7e
KN
476}
477#undef FUNC_NAME
478
479SCM_DEFINE (scm_vm_fp, "vm:fp", 1, 0, 0,
480 (SCM vm),
17e90c5e 481 "")
a98cef7e
KN
482#define FUNC_NAME s_scm_vm_fp
483{
484 SCM_VALIDATE_VM (1, vm);
f41cb00c 485 return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->fp);
a98cef7e
KN
486}
487#undef FUNC_NAME
488
17e90c5e
KN
489#define VM_DEFINE_HOOK(n) \
490{ \
3d5ee0cd 491 struct scm_vm *vp; \
17e90c5e 492 SCM_VALIDATE_VM (1, vm); \
3d5ee0cd
KN
493 vp = SCM_VM_DATA (vm); \
494 if (SCM_FALSEP (vp->hooks[n])) \
238e7a11 495 vp->hooks[n] = scm_make_hook (SCM_I_MAKINUM (1)); \
3d5ee0cd 496 return vp->hooks[n]; \
17e90c5e
KN
497}
498
499SCM_DEFINE (scm_vm_boot_hook, "vm-boot-hook", 1, 0, 0,
a98cef7e 500 (SCM vm),
17e90c5e
KN
501 "")
502#define FUNC_NAME s_scm_vm_boot_hook
a98cef7e 503{
17e90c5e 504 VM_DEFINE_HOOK (SCM_VM_BOOT_HOOK);
a98cef7e
KN
505}
506#undef FUNC_NAME
507
17e90c5e
KN
508SCM_DEFINE (scm_vm_halt_hook, "vm-halt-hook", 1, 0, 0,
509 (SCM vm),
510 "")
511#define FUNC_NAME s_scm_vm_halt_hook
a98cef7e 512{
17e90c5e 513 VM_DEFINE_HOOK (SCM_VM_HALT_HOOK);
a98cef7e
KN
514}
515#undef FUNC_NAME
516
17e90c5e 517SCM_DEFINE (scm_vm_next_hook, "vm-next-hook", 1, 0, 0,
a98cef7e 518 (SCM vm),
17e90c5e
KN
519 "")
520#define FUNC_NAME s_scm_vm_next_hook
a98cef7e 521{
17e90c5e 522 VM_DEFINE_HOOK (SCM_VM_NEXT_HOOK);
a98cef7e
KN
523}
524#undef FUNC_NAME
525
7a0d0cee
KN
526SCM_DEFINE (scm_vm_break_hook, "vm-break-hook", 1, 0, 0,
527 (SCM vm),
528 "")
529#define FUNC_NAME s_scm_vm_break_hook
530{
531 VM_DEFINE_HOOK (SCM_VM_BREAK_HOOK);
532}
533#undef FUNC_NAME
534
17e90c5e
KN
535SCM_DEFINE (scm_vm_enter_hook, "vm-enter-hook", 1, 0, 0,
536 (SCM vm),
537 "")
538#define FUNC_NAME s_scm_vm_enter_hook
a98cef7e 539{
17e90c5e 540 VM_DEFINE_HOOK (SCM_VM_ENTER_HOOK);
a98cef7e
KN
541}
542#undef FUNC_NAME
543
17e90c5e
KN
544SCM_DEFINE (scm_vm_apply_hook, "vm-apply-hook", 1, 0, 0,
545 (SCM vm),
546 "")
547#define FUNC_NAME s_scm_vm_apply_hook
a98cef7e 548{
17e90c5e 549 VM_DEFINE_HOOK (SCM_VM_APPLY_HOOK);
a98cef7e
KN
550}
551#undef FUNC_NAME
552
17e90c5e 553SCM_DEFINE (scm_vm_exit_hook, "vm-exit-hook", 1, 0, 0,
a98cef7e 554 (SCM vm),
17e90c5e
KN
555 "")
556#define FUNC_NAME s_scm_vm_exit_hook
a98cef7e 557{
17e90c5e 558 VM_DEFINE_HOOK (SCM_VM_EXIT_HOOK);
a98cef7e
KN
559}
560#undef FUNC_NAME
561
17e90c5e 562SCM_DEFINE (scm_vm_return_hook, "vm-return-hook", 1, 0, 0,
a98cef7e 563 (SCM vm),
17e90c5e
KN
564 "")
565#define FUNC_NAME s_scm_vm_return_hook
a98cef7e 566{
17e90c5e 567 VM_DEFINE_HOOK (SCM_VM_RETURN_HOOK);
a98cef7e
KN
568}
569#undef FUNC_NAME
570
17e90c5e
KN
571SCM_DEFINE (scm_vm_option, "vm-option", 2, 0, 0,
572 (SCM vm, SCM key),
573 "")
574#define FUNC_NAME s_scm_vm_option
a98cef7e
KN
575{
576 SCM_VALIDATE_VM (1, vm);
17e90c5e 577 return scm_assq_ref (SCM_VM_DATA (vm)->options, key);
a98cef7e
KN
578}
579#undef FUNC_NAME
580
17e90c5e
KN
581SCM_DEFINE (scm_set_vm_option_x, "set-vm-option!", 3, 0, 0,
582 (SCM vm, SCM key, SCM val),
583 "")
584#define FUNC_NAME s_scm_set_vm_option_x
a98cef7e
KN
585{
586 SCM_VALIDATE_VM (1, vm);
17e90c5e
KN
587 SCM_VM_DATA (vm)->options
588 = scm_assq_set_x (SCM_VM_DATA (vm)->options, key, val);
589 return SCM_UNSPECIFIED;
a98cef7e
KN
590}
591#undef FUNC_NAME
592
17e90c5e 593SCM_DEFINE (scm_vm_stats, "vm-stats", 1, 0, 0,
a98cef7e 594 (SCM vm),
17e90c5e
KN
595 "")
596#define FUNC_NAME s_scm_vm_stats
a98cef7e 597{
17e90c5e
KN
598 SCM stats;
599
a98cef7e 600 SCM_VALIDATE_VM (1, vm);
17e90c5e 601
2d80426a
LC
602 stats = scm_make_vector (SCM_I_MAKINUM (2), SCM_UNSPECIFIED);
603 scm_vector_set_x (stats, SCM_I_MAKINUM (0),
f9e8c09d 604 scm_from_ulong (SCM_VM_DATA (vm)->time));
2d80426a 605 scm_vector_set_x (stats, SCM_I_MAKINUM (1),
f9e8c09d 606 scm_from_ulong (SCM_VM_DATA (vm)->clock));
17e90c5e
KN
607
608 return stats;
a98cef7e
KN
609}
610#undef FUNC_NAME
611
b1b942b7 612SCM_DEFINE (scm_vm_trace_frame, "vm-trace-frame", 1, 0, 0,
17e90c5e
KN
613 (SCM vm),
614 "")
b1b942b7 615#define FUNC_NAME s_scm_vm_trace_frame
a98cef7e 616{
a98cef7e 617 SCM_VALIDATE_VM (1, vm);
b1b942b7 618 return SCM_VM_DATA (vm)->trace_frame;
a98cef7e
KN
619}
620#undef FUNC_NAME
621
622\f
623/*
17e90c5e 624 * Initialize
a98cef7e
KN
625 */
626
07e56b27
AW
627SCM scm_load_compiled_with_vm (SCM file)
628{
53e28ed9
AW
629 SCM program = scm_make_program (scm_load_objcode (file),
630 SCM_BOOL_F, SCM_EOL);
07e56b27 631
4abef68f 632 return scm_c_vm_run (scm_the_vm (), program, NULL, 0);
07e56b27
AW
633}
634
17e90c5e 635void
07e56b27 636scm_bootstrap_vm (void)
17e90c5e 637{
07e56b27
AW
638 static int strappage = 0;
639
640 if (strappage)
641 return;
642
643 scm_bootstrap_frames ();
644 scm_bootstrap_instructions ();
645 scm_bootstrap_objcodes ();
646 scm_bootstrap_programs ();
a98cef7e 647
17e90c5e
KN
648 scm_tc16_vm_cont = scm_make_smob_type ("vm-cont", 0);
649 scm_set_smob_mark (scm_tc16_vm_cont, vm_cont_mark);
650 scm_set_smob_free (scm_tc16_vm_cont, vm_cont_free);
a98cef7e 651
17e90c5e
KN
652 scm_tc16_vm = scm_make_smob_type ("vm", 0);
653 scm_set_smob_mark (scm_tc16_vm, vm_mark);
654 scm_set_smob_free (scm_tc16_vm, vm_free);
655 scm_set_smob_apply (scm_tc16_vm, scm_vm_apply, 1, 0, 1);
a98cef7e 656
83495480
AW
657 scm_c_define ("load-compiled",
658 scm_c_make_gsubr ("load-compiled/vm", 1, 0, 0,
659 scm_load_compiled_with_vm));
07e56b27 660
90b0be20
AW
661 sym_vm_run = scm_permanent_object (scm_from_locale_symbol ("vm-run"));
662 sym_vm_error = scm_permanent_object (scm_from_locale_symbol ("vm-error"));
663 sym_debug = scm_permanent_object (scm_from_locale_symbol ("debug"));
664
07e56b27
AW
665 strappage = 1;
666}
667
668void
669scm_init_vm (void)
670{
671 scm_bootstrap_vm ();
672
17e90c5e 673#ifndef SCM_MAGIC_SNARFER
aeeff258 674#include "libguile/vm.x"
17e90c5e 675#endif
a98cef7e 676}
17e90c5e
KN
677
678/*
679 Local Variables:
680 c-file-style: "gnu"
681 End:
682*/