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