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