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