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