eval.c closures are now applicable smobs, not tc3s
[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 */
aa3f6951 162 vp->trace_frame = scm_c_make_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
23f276de
AW
265static SCM
266apply_foreign (SCM proc, SCM *args, int nargs, int headroom)
267{
23f276de
AW
268 SCM_ASRTGO (SCM_NIMP (proc), badproc);
269
23f276de
AW
270 switch (SCM_TYP7 (proc))
271 {
23f276de
AW
272 case scm_tc7_smob:
273 if (!SCM_SMOB_APPLICABLE_P (proc))
274 goto badproc;
275 switch (nargs)
276 {
277 case 0:
278 return SCM_SMOB_APPLY_0 (proc);
279 case 1:
a941cde9 280 return SCM_SMOB_APPLY_1 (proc, args[0]);
23f276de 281 case 2:
a941cde9 282 return SCM_SMOB_APPLY_2 (proc, args[0], args[1]);
23f276de
AW
283 default:
284 {
285 SCM arglist = SCM_EOL;
286 while (nargs-- > 2)
287 arglist = scm_cons (args[nargs], arglist);
a941cde9 288 return SCM_SMOB_APPLY_3 (proc, args[0], args[1], arglist);
23f276de
AW
289 }
290 }
291 case scm_tc7_gsubr:
292 return scm_i_gsubr_apply_array (proc, args, nargs, headroom);
293 default:
294 badproc:
295 scm_wrong_type_arg ("apply", SCM_ARG1, proc);
296 }
297}
298
b7393ea1 299
51e9ba2f 300#define VM_DEFAULT_STACK_SIZE (64 * 1024)
17e90c5e 301
17e90c5e 302#define VM_NAME vm_regular_engine
6d14383e
AW
303#define FUNC_NAME "vm-regular-engine"
304#define VM_ENGINE SCM_VM_REGULAR_ENGINE
83495480 305#include "vm-engine.c"
17e90c5e 306#undef VM_NAME
6d14383e 307#undef FUNC_NAME
17e90c5e 308#undef VM_ENGINE
17e90c5e
KN
309
310#define VM_NAME vm_debug_engine
6d14383e
AW
311#define FUNC_NAME "vm-debug-engine"
312#define VM_ENGINE SCM_VM_DEBUG_ENGINE
83495480 313#include "vm-engine.c"
17e90c5e 314#undef VM_NAME
6d14383e 315#undef FUNC_NAME
17e90c5e
KN
316#undef VM_ENGINE
317
6d14383e
AW
318static const scm_t_vm_engine vm_engines[] =
319 { vm_regular_engine, vm_debug_engine };
320
f9e8c09d 321scm_t_bits scm_tc16_vm;
a98cef7e 322
e3eb628d
LC
323#ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
324
325/* The GC "kind" for the VM stack. */
326static int vm_stack_gc_kind;
327
328#endif
329
a98cef7e 330static SCM
17e90c5e
KN
331make_vm (void)
332#define FUNC_NAME "make_vm"
a98cef7e 333{
17e90c5e 334 int i;
7f991c7d 335 struct scm_vm *vp;
747a1635
AW
336
337 if (!scm_tc16_vm)
338 return SCM_BOOL_F; /* not booted yet */
339
7f991c7d 340 vp = scm_gc_malloc (sizeof (struct scm_vm), "vm");
d8eeb67c 341
3d5ee0cd 342 vp->stack_size = VM_DEFAULT_STACK_SIZE;
e3eb628d
LC
343
344#ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
345 vp->stack_base = GC_generic_malloc (vp->stack_size * sizeof (SCM),
346 vm_stack_gc_kind);
347
348 /* Keep a pointer to VP so that `vm_stack_mark ()' can know what the stack
349 top is. */
350 *vp->stack_base = PTR2SCM (vp);
351 vp->stack_base++;
352 vp->stack_size--;
353#else
d8eeb67c
LC
354 vp->stack_base = scm_gc_malloc (vp->stack_size * sizeof (SCM),
355 "stack-base");
e3eb628d
LC
356#endif
357
2bbe1533
AW
358#ifdef VM_ENABLE_STACK_NULLING
359 memset (vp->stack_base, 0, vp->stack_size * sizeof (SCM));
360#endif
75d315e1 361 vp->stack_limit = vp->stack_base + vp->stack_size;
3616e9e9
KN
362 vp->ip = NULL;
363 vp->sp = vp->stack_base - 1;
364 vp->fp = NULL;
6d14383e 365 vp->engine = SCM_VM_DEBUG_ENGINE;
3d5ee0cd
KN
366 vp->time = 0;
367 vp->clock = 0;
368 vp->options = SCM_EOL;
17e90c5e 369 for (i = 0; i < SCM_VM_NUM_HOOKS; i++)
3d5ee0cd 370 vp->hooks[i] = SCM_BOOL_F;
b1b942b7 371 vp->trace_frame = SCM_BOOL_F;
3d5ee0cd 372 SCM_RETURN_NEWSMOB (scm_tc16_vm, vp);
a98cef7e 373}
17e90c5e 374#undef FUNC_NAME
a98cef7e 375
e3eb628d
LC
376#ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
377
378/* Mark the VM stack region between its base and its current top. */
379static struct GC_ms_entry *
380vm_stack_mark (GC_word *addr, struct GC_ms_entry *mark_stack_ptr,
381 struct GC_ms_entry *mark_stack_limit, GC_word env)
382{
383 GC_word *word;
384 const struct scm_vm *vm;
385
386 /* The first word of the VM stack should contain a pointer to the
387 corresponding VM. */
388 vm = * ((struct scm_vm **) addr);
389
8071c490
LC
390 if (vm == NULL
391 || (SCM *) addr != vm->stack_base - 1
78747ac6 392 || vm->stack_limit - vm->stack_base != vm->stack_size)
e3eb628d
LC
393 /* ADDR must be a pointer to a free-list element, which we must ignore
394 (see warning in <gc/gc_mark.h>). */
395 return mark_stack_ptr;
396
e3eb628d
LC
397 for (word = (GC_word *) vm->stack_base; word <= (GC_word *) vm->sp; word++)
398 mark_stack_ptr = GC_MARK_AND_PUSH ((* (GC_word **) word),
399 mark_stack_ptr, mark_stack_limit,
400 NULL);
401
402 return mark_stack_ptr;
403}
404
405#endif /* VM_ENABLE_PRECISE_STACK_GC_SCAN */
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);
67e2d80a 423 SCM_VALIDATE_PROC (2, program);
6d14383e
AW
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 439
14aa25e4
AW
440SCM
441scm_vm_call_with_new_stack (SCM vm, SCM thunk, SCM id)
442{
443 return scm_c_vm_run (vm, thunk, NULL, 0);
444}
445
a98cef7e
KN
446/* Scheme interface */
447
448SCM_DEFINE (scm_vm_version, "vm-version", 0, 0, 0,
17e90c5e
KN
449 (void),
450 "")
a98cef7e
KN
451#define FUNC_NAME s_scm_vm_version
452{
d3518113 453 return scm_from_locale_string (PACKAGE_VERSION);
a98cef7e
KN
454}
455#undef FUNC_NAME
456
499a4c07 457SCM_DEFINE (scm_the_vm, "the-vm", 0, 0, 0,
fcd4901b 458 (void),
499a4c07
KN
459 "")
460#define FUNC_NAME s_scm_the_vm
461{
2bbe1533 462 scm_i_thread *t = SCM_I_CURRENT_THREAD;
f63ea2ce 463
8b22ed7a 464 if (SCM_UNLIKELY (scm_is_false ((t->vm))))
2bbe1533 465 t->vm = make_vm ();
f63ea2ce 466
2bbe1533 467 return t->vm;
499a4c07
KN
468}
469#undef FUNC_NAME
470
471
a98cef7e
KN
472SCM_DEFINE (scm_vm_p, "vm?", 1, 0, 0,
473 (SCM obj),
17e90c5e 474 "")
a98cef7e
KN
475#define FUNC_NAME s_scm_vm_p
476{
9bd48cb1 477 return scm_from_bool (SCM_VM_P (obj));
a98cef7e
KN
478}
479#undef FUNC_NAME
480
481SCM_DEFINE (scm_make_vm, "make-vm", 0, 0, 0,
17e90c5e
KN
482 (void),
483 "")
484#define FUNC_NAME s_scm_make_vm,
a98cef7e 485{
17e90c5e 486 return make_vm ();
a98cef7e
KN
487}
488#undef FUNC_NAME
489
17e90c5e 490SCM_DEFINE (scm_vm_ip, "vm:ip", 1, 0, 0,
a98cef7e 491 (SCM vm),
17e90c5e
KN
492 "")
493#define FUNC_NAME s_scm_vm_ip
a98cef7e
KN
494{
495 SCM_VALIDATE_VM (1, vm);
f41cb00c 496 return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->ip);
a98cef7e
KN
497}
498#undef FUNC_NAME
499
500SCM_DEFINE (scm_vm_sp, "vm:sp", 1, 0, 0,
501 (SCM vm),
17e90c5e 502 "")
a98cef7e
KN
503#define FUNC_NAME s_scm_vm_sp
504{
505 SCM_VALIDATE_VM (1, vm);
f41cb00c 506 return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->sp);
a98cef7e
KN
507}
508#undef FUNC_NAME
509
510SCM_DEFINE (scm_vm_fp, "vm:fp", 1, 0, 0,
511 (SCM vm),
17e90c5e 512 "")
a98cef7e
KN
513#define FUNC_NAME s_scm_vm_fp
514{
515 SCM_VALIDATE_VM (1, vm);
f41cb00c 516 return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->fp);
a98cef7e
KN
517}
518#undef FUNC_NAME
519
17e90c5e
KN
520#define VM_DEFINE_HOOK(n) \
521{ \
3d5ee0cd 522 struct scm_vm *vp; \
17e90c5e 523 SCM_VALIDATE_VM (1, vm); \
3d5ee0cd 524 vp = SCM_VM_DATA (vm); \
8b22ed7a 525 if (scm_is_false (vp->hooks[n])) \
238e7a11 526 vp->hooks[n] = scm_make_hook (SCM_I_MAKINUM (1)); \
3d5ee0cd 527 return vp->hooks[n]; \
17e90c5e
KN
528}
529
530SCM_DEFINE (scm_vm_boot_hook, "vm-boot-hook", 1, 0, 0,
a98cef7e 531 (SCM vm),
17e90c5e
KN
532 "")
533#define FUNC_NAME s_scm_vm_boot_hook
a98cef7e 534{
17e90c5e 535 VM_DEFINE_HOOK (SCM_VM_BOOT_HOOK);
a98cef7e
KN
536}
537#undef FUNC_NAME
538
17e90c5e
KN
539SCM_DEFINE (scm_vm_halt_hook, "vm-halt-hook", 1, 0, 0,
540 (SCM vm),
541 "")
542#define FUNC_NAME s_scm_vm_halt_hook
a98cef7e 543{
17e90c5e 544 VM_DEFINE_HOOK (SCM_VM_HALT_HOOK);
a98cef7e
KN
545}
546#undef FUNC_NAME
547
17e90c5e 548SCM_DEFINE (scm_vm_next_hook, "vm-next-hook", 1, 0, 0,
a98cef7e 549 (SCM vm),
17e90c5e
KN
550 "")
551#define FUNC_NAME s_scm_vm_next_hook
a98cef7e 552{
17e90c5e 553 VM_DEFINE_HOOK (SCM_VM_NEXT_HOOK);
a98cef7e
KN
554}
555#undef FUNC_NAME
556
7a0d0cee
KN
557SCM_DEFINE (scm_vm_break_hook, "vm-break-hook", 1, 0, 0,
558 (SCM vm),
559 "")
560#define FUNC_NAME s_scm_vm_break_hook
561{
562 VM_DEFINE_HOOK (SCM_VM_BREAK_HOOK);
563}
564#undef FUNC_NAME
565
17e90c5e
KN
566SCM_DEFINE (scm_vm_enter_hook, "vm-enter-hook", 1, 0, 0,
567 (SCM vm),
568 "")
569#define FUNC_NAME s_scm_vm_enter_hook
a98cef7e 570{
17e90c5e 571 VM_DEFINE_HOOK (SCM_VM_ENTER_HOOK);
a98cef7e
KN
572}
573#undef FUNC_NAME
574
17e90c5e
KN
575SCM_DEFINE (scm_vm_apply_hook, "vm-apply-hook", 1, 0, 0,
576 (SCM vm),
577 "")
578#define FUNC_NAME s_scm_vm_apply_hook
a98cef7e 579{
17e90c5e 580 VM_DEFINE_HOOK (SCM_VM_APPLY_HOOK);
a98cef7e
KN
581}
582#undef FUNC_NAME
583
17e90c5e 584SCM_DEFINE (scm_vm_exit_hook, "vm-exit-hook", 1, 0, 0,
a98cef7e 585 (SCM vm),
17e90c5e
KN
586 "")
587#define FUNC_NAME s_scm_vm_exit_hook
a98cef7e 588{
17e90c5e 589 VM_DEFINE_HOOK (SCM_VM_EXIT_HOOK);
a98cef7e
KN
590}
591#undef FUNC_NAME
592
17e90c5e 593SCM_DEFINE (scm_vm_return_hook, "vm-return-hook", 1, 0, 0,
a98cef7e 594 (SCM vm),
17e90c5e
KN
595 "")
596#define FUNC_NAME s_scm_vm_return_hook
a98cef7e 597{
17e90c5e 598 VM_DEFINE_HOOK (SCM_VM_RETURN_HOOK);
a98cef7e
KN
599}
600#undef FUNC_NAME
601
17e90c5e
KN
602SCM_DEFINE (scm_vm_option, "vm-option", 2, 0, 0,
603 (SCM vm, SCM key),
604 "")
605#define FUNC_NAME s_scm_vm_option
a98cef7e
KN
606{
607 SCM_VALIDATE_VM (1, vm);
17e90c5e 608 return scm_assq_ref (SCM_VM_DATA (vm)->options, key);
a98cef7e
KN
609}
610#undef FUNC_NAME
611
17e90c5e
KN
612SCM_DEFINE (scm_set_vm_option_x, "set-vm-option!", 3, 0, 0,
613 (SCM vm, SCM key, SCM val),
614 "")
615#define FUNC_NAME s_scm_set_vm_option_x
a98cef7e
KN
616{
617 SCM_VALIDATE_VM (1, vm);
17e90c5e
KN
618 SCM_VM_DATA (vm)->options
619 = scm_assq_set_x (SCM_VM_DATA (vm)->options, key, val);
620 return SCM_UNSPECIFIED;
a98cef7e
KN
621}
622#undef FUNC_NAME
623
17e90c5e 624SCM_DEFINE (scm_vm_stats, "vm-stats", 1, 0, 0,
a98cef7e 625 (SCM vm),
17e90c5e
KN
626 "")
627#define FUNC_NAME s_scm_vm_stats
a98cef7e 628{
17e90c5e
KN
629 SCM stats;
630
a98cef7e 631 SCM_VALIDATE_VM (1, vm);
17e90c5e 632
2d80426a
LC
633 stats = scm_make_vector (SCM_I_MAKINUM (2), SCM_UNSPECIFIED);
634 scm_vector_set_x (stats, SCM_I_MAKINUM (0),
f9e8c09d 635 scm_from_ulong (SCM_VM_DATA (vm)->time));
2d80426a 636 scm_vector_set_x (stats, SCM_I_MAKINUM (1),
f9e8c09d 637 scm_from_ulong (SCM_VM_DATA (vm)->clock));
17e90c5e
KN
638
639 return stats;
a98cef7e
KN
640}
641#undef FUNC_NAME
642
b1b942b7 643SCM_DEFINE (scm_vm_trace_frame, "vm-trace-frame", 1, 0, 0,
17e90c5e
KN
644 (SCM vm),
645 "")
b1b942b7 646#define FUNC_NAME s_scm_vm_trace_frame
a98cef7e 647{
a98cef7e 648 SCM_VALIDATE_VM (1, vm);
b1b942b7 649 return SCM_VM_DATA (vm)->trace_frame;
a98cef7e
KN
650}
651#undef FUNC_NAME
652
653\f
654/*
17e90c5e 655 * Initialize
a98cef7e
KN
656 */
657
07e56b27
AW
658SCM scm_load_compiled_with_vm (SCM file)
659{
53e28ed9 660 SCM program = scm_make_program (scm_load_objcode (file),
20d47c39 661 SCM_BOOL_F, SCM_BOOL_F);
07e56b27 662
4abef68f 663 return scm_c_vm_run (scm_the_vm (), program, NULL, 0);
07e56b27
AW
664}
665
17e90c5e 666void
07e56b27 667scm_bootstrap_vm (void)
17e90c5e 668{
07e56b27
AW
669 static int strappage = 0;
670
671 if (strappage)
672 return;
673
674 scm_bootstrap_frames ();
675 scm_bootstrap_instructions ();
676 scm_bootstrap_objcodes ();
677 scm_bootstrap_programs ();
a98cef7e 678
17e90c5e 679 scm_tc16_vm_cont = scm_make_smob_type ("vm-cont", 0);
a98cef7e 680
17e90c5e 681 scm_tc16_vm = scm_make_smob_type ("vm", 0);
17e90c5e 682 scm_set_smob_apply (scm_tc16_vm, scm_vm_apply, 1, 0, 1);
a98cef7e 683
83495480
AW
684 scm_c_define ("load-compiled",
685 scm_c_make_gsubr ("load-compiled/vm", 1, 0, 0,
686 scm_load_compiled_with_vm));
07e56b27 687
90b0be20
AW
688 sym_vm_run = scm_permanent_object (scm_from_locale_symbol ("vm-run"));
689 sym_vm_error = scm_permanent_object (scm_from_locale_symbol ("vm-error"));
690 sym_debug = scm_permanent_object (scm_from_locale_symbol ("debug"));
691
60ae5ca2
AW
692 scm_c_register_extension ("libguile", "scm_init_vm",
693 (scm_t_extension_init_func)scm_init_vm, NULL);
694
07e56b27 695 strappage = 1;
e3eb628d
LC
696
697#ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
698 vm_stack_gc_kind =
699 GC_new_kind (GC_new_free_list (),
700 GC_MAKE_PROC (GC_new_proc (vm_stack_mark), 0),
701 0, 1);
702
703#endif
07e56b27
AW
704}
705
706void
707scm_init_vm (void)
708{
709 scm_bootstrap_vm ();
710
17e90c5e 711#ifndef SCM_MAGIC_SNARFER
aeeff258 712#include "libguile/vm.x"
17e90c5e 713#endif
a98cef7e 714}
17e90c5e
KN
715
716/*
717 Local Variables:
718 c-file-style: "gnu"
719 End:
720*/