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