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