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