recompiling with compile environments, fluid languages, cleanups
[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"
a98cef7e
KN
52#include "vm.h"
53
a98cef7e
KN
54/* I sometimes use this for debugging. */
55#define vm_puts(OBJ) \
56{ \
22bcbe8c
AW
57 scm_display (OBJ, scm_current_error_port ()); \
58 scm_newline (scm_current_error_port ()); \
a98cef7e
KN
59}
60
11ea1aba
AW
61/* The VM has a number of internal assertions that shouldn't normally be
62 necessary, but might be if you think you found a bug in the VM. */
63#define VM_ENABLE_ASSERTIONS
64
65/* We can add a mode that ensures that all stack items above the stack pointer
66 are NULL. This is useful for checking the internal consistency of the VM's
67 assumptions and its operators, but isn't necessary for normal operation. It
68 will ensure that assertions are enabled. */
69#define VM_ENABLE_STACK_NULLING
70
71#if defined (VM_ENABLE_STACK_NULLING) && !defined (VM_ENABLE_ASSERTIONS)
72#define VM_ENABLE_ASSERTIONS
73#endif
74
a98cef7e 75\f
a98cef7e
KN
76/*
77 * VM Continuation
78 */
79
f9e8c09d 80scm_t_bits scm_tc16_vm_cont;
17e90c5e 81
bfffd258
AW
82struct scm_vm_cont {
83 scm_byte_t *ip;
84 scm_t_ptrdiff sp;
85 scm_t_ptrdiff fp;
86 scm_t_ptrdiff stack_size;
87 SCM *stack_base;
11ea1aba 88 scm_t_ptrdiff reloc;
bfffd258
AW
89};
90
17e90c5e
KN
91
92#define SCM_VM_CONT_P(OBJ) SCM_SMOB_PREDICATE (scm_tc16_vm_cont, OBJ)
bfffd258
AW
93#define SCM_VM_CONT_DATA(CONT) ((struct scm_vm_cont *) SCM_CELL_WORD_1 (CONT))
94
11ea1aba
AW
95static void
96vm_mark_stack (SCM *base, scm_t_ptrdiff size, SCM *fp, scm_t_ptrdiff reloc)
97{
98 SCM *sp, *upper, *lower;
99 sp = base + size - 1;
100
101 while (sp > base && fp)
102 {
103 upper = SCM_FRAME_UPPER_ADDRESS (fp);
104 lower = SCM_FRAME_LOWER_ADDRESS (fp);
105
106 for (; sp >= upper; sp--)
107 if (SCM_NIMP (*sp))
108 {
109 if (scm_in_heap_p (*sp))
110 scm_gc_mark (*sp);
111 else
112 fprintf (stderr, "BADNESS: crap on the stack: %p\n", *sp);
113 }
114
115
116 /* skip ra, mvra */
117 sp -= 2;
118
119 /* update fp from the dynamic link */
120 fp = (SCM*)*sp-- + reloc;
121
122 /* mark from the hl down to the lower address */
123 for (; sp >= lower; sp--)
124 if (*sp && SCM_NIMP (*sp))
125 scm_gc_mark (*sp);
126 }
127}
128
bfffd258
AW
129static SCM
130vm_cont_mark (SCM obj)
131{
11ea1aba 132 struct scm_vm_cont *p = SCM_VM_CONT_DATA (obj);
bfffd258 133
11ea1aba 134 vm_mark_stack (p->stack_base, p->stack_size, p->stack_base + p->fp, p->reloc);
bfffd258
AW
135
136 return SCM_BOOL_F;
137}
138
139static scm_sizet
140vm_cont_free (SCM obj)
141{
142 struct scm_vm_cont *p = SCM_VM_CONT_DATA (obj);
143
144 scm_gc_free (p->stack_base, p->stack_size * sizeof (SCM), "stack-base");
145 scm_gc_free (p, sizeof (struct scm_vm), "vm");
146
147 return 0;
148}
a98cef7e
KN
149
150static SCM
3d5ee0cd 151capture_vm_cont (struct scm_vm *vp)
a98cef7e 152{
bfffd258
AW
153 struct scm_vm_cont *p = scm_gc_malloc (sizeof (*p), "capture_vm_cont");
154 p->stack_size = vp->sp - vp->stack_base + 1;
d8eeb67c
LC
155 p->stack_base = scm_gc_malloc (p->stack_size * sizeof (SCM),
156 "capture_vm_cont");
11ea1aba 157#ifdef VM_ENABLE_STACK_NULLING
66db076a
AW
158 if (vp->sp >= vp->stack_base)
159 if (!vp->sp[0] || vp->sp[1])
160 abort ();
11ea1aba
AW
161 memset (p->stack_base, 0, p->stack_size * sizeof (SCM));
162#endif
3d5ee0cd 163 p->ip = vp->ip;
bfffd258
AW
164 p->sp = vp->sp - vp->stack_base;
165 p->fp = vp->fp - vp->stack_base;
166 memcpy (p->stack_base, vp->stack_base, p->stack_size * sizeof (SCM));
11ea1aba 167 p->reloc = p->stack_base - vp->stack_base;
17e90c5e 168 SCM_RETURN_NEWSMOB (scm_tc16_vm_cont, p);
a98cef7e
KN
169}
170
171static void
3d5ee0cd 172reinstate_vm_cont (struct scm_vm *vp, SCM cont)
a98cef7e 173{
bfffd258 174 struct scm_vm_cont *p = SCM_VM_CONT_DATA (cont);
3d5ee0cd 175 if (vp->stack_size < p->stack_size)
a98cef7e 176 {
17e90c5e 177 /* puts ("FIXME: Need to expand"); */
a98cef7e
KN
178 abort ();
179 }
11ea1aba
AW
180#ifdef VM_ENABLE_STACK_NULLING
181 {
182 scm_t_ptrdiff nzero = (vp->sp - vp->stack_base) - p->sp;
183 if (nzero > 0)
66db076a
AW
184 memset (vp->stack_base + p->stack_size, 0, nzero * sizeof (SCM));
185 /* actually nzero should always be negative, because vm_reset_stack will
186 unwind the stack to some point *below* this continuation */
11ea1aba
AW
187 }
188#endif
3d5ee0cd 189 vp->ip = p->ip;
bfffd258
AW
190 vp->sp = vp->stack_base + p->sp;
191 vp->fp = vp->stack_base + p->fp;
192 memcpy (vp->stack_base, p->stack_base, p->stack_size * sizeof (SCM));
193}
194
195/* In theory, a number of vm instances can be active in the call trace, and we
196 only want to reify the continuations of those in the current continuation
197 root. I don't see a nice way to do this -- ideally it would involve dynwinds,
198 and previous values of the *the-vm* fluid within the current continuation
199 root. But we don't have access to continuation roots in the dynwind stack.
200 So, just punt for now -- take the current value of *the-vm*.
201
202 While I'm on the topic, ideally we could avoid copying the C stack if the
203 continuation root is inside VM code, and call/cc was invoked within that same
204 call to vm_run; but that's currently not implemented.
205 */
206SCM
207scm_vm_capture_continuations (void)
208{
209 SCM vm = scm_the_vm ();
210 return scm_acons (vm, capture_vm_cont (SCM_VM_DATA (vm)), SCM_EOL);
211}
212
213void
214scm_vm_reinstate_continuations (SCM conts)
215{
216 for (; conts != SCM_EOL; conts = SCM_CDR (conts))
217 reinstate_vm_cont (SCM_VM_DATA (SCM_CAAR (conts)), SCM_CDAR (conts));
a98cef7e
KN
218}
219
17d1b4bf
AW
220struct vm_unwind_data
221{
222 struct scm_vm *vp;
223 SCM *sp;
224 SCM *fp;
225 SCM this_frame;
226};
227
228static void
229vm_reset_stack (void *data)
230{
231 struct vm_unwind_data *w = data;
66db076a 232 struct scm_vm *vp = w->vp;
17d1b4bf 233
66db076a
AW
234 vp->sp = w->sp;
235 vp->fp = w->fp;
236 vp->this_frame = w->this_frame;
11ea1aba 237#ifdef VM_ENABLE_STACK_NULLING
66db076a 238 memset (vp->sp + 1, 0, (vp->stack_size - (vp->sp + 1 - vp->stack_base)) * sizeof(SCM));
11ea1aba 239#endif
17d1b4bf
AW
240}
241
17e90c5e
KN
242\f
243/*
244 * VM Internal functions
245 */
246
90b0be20
AW
247static SCM sym_vm_run;
248static SCM sym_vm_error;
249static SCM sym_debug;
17e90c5e
KN
250
251static scm_byte_t *
252vm_fetch_length (scm_byte_t *ip, size_t *lenp)
a98cef7e 253{
4bfb26f5 254 /* NOTE: format defined in system/vm/conv.scm */
17e90c5e
KN
255 *lenp = *ip++;
256 if (*lenp < 254)
257 return ip;
258 else if (*lenp == 254)
46cd9a34
KN
259 {
260 int b1 = *ip++;
261 int b2 = *ip++;
262 *lenp = (b1 << 8) + b2;
263 }
17e90c5e 264 else
46cd9a34
KN
265 {
266 int b1 = *ip++;
267 int b2 = *ip++;
268 int b3 = *ip++;
269 int b4 = *ip++;
270 *lenp = (b1 << 24) + (b2 << 16) + (b3 << 8) + b4;
271 }
17e90c5e 272 return ip;
a98cef7e
KN
273}
274
af988bbf 275static SCM
a6df585a 276vm_heapify_frames_1 (struct scm_vm *vp, SCM *fp, SCM *sp, SCM **destp)
af988bbf 277{
a6df585a 278 SCM frame;
af988bbf 279 SCM *dl = SCM_FRAME_DYNAMIC_LINK (fp);
fcd4901b 280#if 0
a6df585a 281 SCM *src = SCM_FRAME_UPPER_ADDRESS (fp);
fcd4901b 282#endif
a6df585a 283 SCM *dest = SCM_FRAME_LOWER_ADDRESS (fp);
af988bbf
KN
284
285 if (!dl)
286 {
287 /* The top frame */
af988bbf
KN
288 frame = scm_c_make_heap_frame (fp);
289 fp = SCM_HEAP_FRAME_POINTER (frame);
290 SCM_FRAME_HEAP_LINK (fp) = SCM_BOOL_T;
291 }
292 else
293 {
a6df585a 294 /* Child frames */
af988bbf
KN
295 SCM link = SCM_FRAME_HEAP_LINK (dl);
296 if (!SCM_FALSEP (link))
a6df585a 297 link = SCM_FRAME_LOWER_ADDRESS (dl)[-1]; /* self link */
af988bbf 298 else
a6df585a 299 link = vm_heapify_frames_1 (vp, dl, dest - 1, &dest);
af988bbf
KN
300 frame = scm_c_make_heap_frame (fp);
301 fp = SCM_HEAP_FRAME_POINTER (frame);
0570c3f1 302 /* FIXME: I don't think we should be storing heap links on the stack. */
af988bbf 303 SCM_FRAME_HEAP_LINK (fp) = link;
b6368dbb 304 SCM_FRAME_SET_DYNAMIC_LINK (fp, SCM_HEAP_FRAME_POINTER (link));
af988bbf
KN
305 }
306
17d1b4bf
AW
307 /* Apparently the intention here is to be able to have a frame on the heap,
308 but data on the stack, so that you can push as much as you want on the
309 stack; but I think that it's currently causing borkage with nonlocal exits
310 and the unwind handler, which reinstates the sp and fp, but it's no longer
311 pointing at a valid stack frame. So disable for now, we'll get back to
312 this later. */
313#if 0
af988bbf 314 /* Move stack data */
a6df585a
KN
315 for (; src <= sp; src++, dest++)
316 *dest = *src;
317 *destp = dest;
17d1b4bf 318#endif
af988bbf
KN
319
320 return frame;
321}
322
323static SCM
324vm_heapify_frames (SCM vm)
325{
326 struct scm_vm *vp = SCM_VM_DATA (vm);
327 if (SCM_FALSEP (SCM_FRAME_HEAP_LINK (vp->fp)))
328 {
a6df585a
KN
329 SCM *dest;
330 vp->this_frame = vm_heapify_frames_1 (vp, vp->fp, vp->sp, &dest);
af988bbf 331 vp->fp = SCM_HEAP_FRAME_POINTER (vp->this_frame);
a6df585a 332 vp->sp = dest - 1;
af988bbf
KN
333 }
334 return vp->this_frame;
335}
336
a98cef7e
KN
337\f
338/*
339 * VM
340 */
341
c0a25ecc 342#define VM_DEFAULT_STACK_SIZE (16 * 1024)
17e90c5e
KN
343
344#define VM_REGULAR_ENGINE 0
345#define VM_DEBUG_ENGINE 1
346
347#if 0
348#define VM_NAME vm_regular_engine
349#define VM_ENGINE VM_REGULAR_ENGINE
83495480 350#include "vm-engine.c"
17e90c5e
KN
351#undef VM_NAME
352#undef VM_ENGINE
353#endif
354
355#define VM_NAME vm_debug_engine
356#define VM_ENGINE VM_DEBUG_ENGINE
83495480 357#include "vm-engine.c"
17e90c5e
KN
358#undef VM_NAME
359#undef VM_ENGINE
360
f9e8c09d 361scm_t_bits scm_tc16_vm;
a98cef7e
KN
362
363static SCM
17e90c5e
KN
364make_vm (void)
365#define FUNC_NAME "make_vm"
a98cef7e 366{
17e90c5e 367 int i;
d8eeb67c
LC
368 struct scm_vm *vp = scm_gc_malloc (sizeof (struct scm_vm), "vm");
369
3d5ee0cd 370 vp->stack_size = VM_DEFAULT_STACK_SIZE;
d8eeb67c
LC
371 vp->stack_base = scm_gc_malloc (vp->stack_size * sizeof (SCM),
372 "stack-base");
2bbe1533
AW
373#ifdef VM_ENABLE_STACK_NULLING
374 memset (vp->stack_base, 0, vp->stack_size * sizeof (SCM));
375#endif
3616e9e9
KN
376 vp->stack_limit = vp->stack_base + vp->stack_size - 3;
377 vp->ip = NULL;
378 vp->sp = vp->stack_base - 1;
379 vp->fp = NULL;
3d5ee0cd
KN
380 vp->time = 0;
381 vp->clock = 0;
382 vp->options = SCM_EOL;
af988bbf 383 vp->this_frame = SCM_BOOL_F;
ac99cb0c 384 vp->last_frame = SCM_BOOL_F;
d0168f3d 385 vp->last_ip = NULL;
17e90c5e 386 for (i = 0; i < SCM_VM_NUM_HOOKS; i++)
3d5ee0cd
KN
387 vp->hooks[i] = SCM_BOOL_F;
388 SCM_RETURN_NEWSMOB (scm_tc16_vm, vp);
a98cef7e 389}
17e90c5e 390#undef FUNC_NAME
a98cef7e
KN
391
392static SCM
17e90c5e 393vm_mark (SCM obj)
a98cef7e 394{
17e90c5e 395 int i;
3d5ee0cd 396 struct scm_vm *vp = SCM_VM_DATA (obj);
17e90c5e 397
11ea1aba
AW
398#ifdef VM_ENABLE_STACK_NULLING
399 if (vp->sp >= vp->stack_base)
400 if (!vp->sp[0] || vp->sp[1])
401 abort ();
402#endif
403
404 /* mark the stack, precisely */
405 vm_mark_stack (vp->stack_base, vp->sp + 1 - vp->stack_base, vp->fp, 0);
a98cef7e 406
af988bbf 407 /* mark other objects */
17e90c5e 408 for (i = 0; i < SCM_VM_NUM_HOOKS; i++)
3d5ee0cd 409 scm_gc_mark (vp->hooks[i]);
af988bbf 410 scm_gc_mark (vp->this_frame);
ac99cb0c 411 scm_gc_mark (vp->last_frame);
3d5ee0cd 412 return vp->options;
a98cef7e
KN
413}
414
17e90c5e
KN
415static scm_sizet
416vm_free (SCM obj)
417{
3d5ee0cd 418 struct scm_vm *vp = SCM_VM_DATA (obj);
d8eeb67c
LC
419
420 scm_gc_free (vp->stack_base, vp->stack_size * sizeof (SCM),
421 "stack-base");
422 scm_gc_free (vp, sizeof (struct scm_vm), "vm");
423
424 return 0;
17e90c5e
KN
425}
426
17e90c5e
KN
427SCM
428scm_vm_apply (SCM vm, SCM program, SCM args)
429#define FUNC_NAME "scm_vm_apply"
a98cef7e 430{
17e90c5e 431 SCM_VALIDATE_PROGRAM (1, program);
41f248a8 432 return vm_run (vm, program, args);
a98cef7e 433}
17e90c5e 434#undef FUNC_NAME
a98cef7e
KN
435
436/* Scheme interface */
437
438SCM_DEFINE (scm_vm_version, "vm-version", 0, 0, 0,
17e90c5e
KN
439 (void),
440 "")
a98cef7e
KN
441#define FUNC_NAME s_scm_vm_version
442{
d3518113 443 return scm_from_locale_string (PACKAGE_VERSION);
a98cef7e
KN
444}
445#undef FUNC_NAME
446
499a4c07 447SCM_DEFINE (scm_the_vm, "the-vm", 0, 0, 0,
fcd4901b 448 (void),
499a4c07
KN
449 "")
450#define FUNC_NAME s_scm_the_vm
451{
2bbe1533 452 scm_i_thread *t = SCM_I_CURRENT_THREAD;
f63ea2ce 453
2bbe1533
AW
454 if (SCM_UNLIKELY (SCM_FALSEP ((t->vm))))
455 t->vm = make_vm ();
f63ea2ce 456
2bbe1533 457 return t->vm;
499a4c07
KN
458}
459#undef FUNC_NAME
460
461
a98cef7e
KN
462SCM_DEFINE (scm_vm_p, "vm?", 1, 0, 0,
463 (SCM obj),
17e90c5e 464 "")
a98cef7e
KN
465#define FUNC_NAME s_scm_vm_p
466{
467 return SCM_BOOL (SCM_VM_P (obj));
468}
469#undef FUNC_NAME
470
471SCM_DEFINE (scm_make_vm, "make-vm", 0, 0, 0,
17e90c5e
KN
472 (void),
473 "")
474#define FUNC_NAME s_scm_make_vm,
a98cef7e 475{
17e90c5e 476 return make_vm ();
a98cef7e
KN
477}
478#undef FUNC_NAME
479
17e90c5e 480SCM_DEFINE (scm_vm_ip, "vm:ip", 1, 0, 0,
a98cef7e 481 (SCM vm),
17e90c5e
KN
482 "")
483#define FUNC_NAME s_scm_vm_ip
a98cef7e
KN
484{
485 SCM_VALIDATE_VM (1, vm);
f41cb00c 486 return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->ip);
a98cef7e
KN
487}
488#undef FUNC_NAME
489
490SCM_DEFINE (scm_vm_sp, "vm:sp", 1, 0, 0,
491 (SCM vm),
17e90c5e 492 "")
a98cef7e
KN
493#define FUNC_NAME s_scm_vm_sp
494{
495 SCM_VALIDATE_VM (1, vm);
f41cb00c 496 return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->sp);
a98cef7e
KN
497}
498#undef FUNC_NAME
499
500SCM_DEFINE (scm_vm_fp, "vm:fp", 1, 0, 0,
501 (SCM vm),
17e90c5e 502 "")
a98cef7e
KN
503#define FUNC_NAME s_scm_vm_fp
504{
505 SCM_VALIDATE_VM (1, vm);
f41cb00c 506 return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->fp);
a98cef7e
KN
507}
508#undef FUNC_NAME
509
17e90c5e
KN
510#define VM_DEFINE_HOOK(n) \
511{ \
3d5ee0cd 512 struct scm_vm *vp; \
17e90c5e 513 SCM_VALIDATE_VM (1, vm); \
3d5ee0cd
KN
514 vp = SCM_VM_DATA (vm); \
515 if (SCM_FALSEP (vp->hooks[n])) \
238e7a11 516 vp->hooks[n] = scm_make_hook (SCM_I_MAKINUM (1)); \
3d5ee0cd 517 return vp->hooks[n]; \
17e90c5e
KN
518}
519
520SCM_DEFINE (scm_vm_boot_hook, "vm-boot-hook", 1, 0, 0,
a98cef7e 521 (SCM vm),
17e90c5e
KN
522 "")
523#define FUNC_NAME s_scm_vm_boot_hook
a98cef7e 524{
17e90c5e 525 VM_DEFINE_HOOK (SCM_VM_BOOT_HOOK);
a98cef7e
KN
526}
527#undef FUNC_NAME
528
17e90c5e
KN
529SCM_DEFINE (scm_vm_halt_hook, "vm-halt-hook", 1, 0, 0,
530 (SCM vm),
531 "")
532#define FUNC_NAME s_scm_vm_halt_hook
a98cef7e 533{
17e90c5e 534 VM_DEFINE_HOOK (SCM_VM_HALT_HOOK);
a98cef7e
KN
535}
536#undef FUNC_NAME
537
17e90c5e 538SCM_DEFINE (scm_vm_next_hook, "vm-next-hook", 1, 0, 0,
a98cef7e 539 (SCM vm),
17e90c5e
KN
540 "")
541#define FUNC_NAME s_scm_vm_next_hook
a98cef7e 542{
17e90c5e 543 VM_DEFINE_HOOK (SCM_VM_NEXT_HOOK);
a98cef7e
KN
544}
545#undef FUNC_NAME
546
7a0d0cee
KN
547SCM_DEFINE (scm_vm_break_hook, "vm-break-hook", 1, 0, 0,
548 (SCM vm),
549 "")
550#define FUNC_NAME s_scm_vm_break_hook
551{
552 VM_DEFINE_HOOK (SCM_VM_BREAK_HOOK);
553}
554#undef FUNC_NAME
555
17e90c5e
KN
556SCM_DEFINE (scm_vm_enter_hook, "vm-enter-hook", 1, 0, 0,
557 (SCM vm),
558 "")
559#define FUNC_NAME s_scm_vm_enter_hook
a98cef7e 560{
17e90c5e 561 VM_DEFINE_HOOK (SCM_VM_ENTER_HOOK);
a98cef7e
KN
562}
563#undef FUNC_NAME
564
17e90c5e
KN
565SCM_DEFINE (scm_vm_apply_hook, "vm-apply-hook", 1, 0, 0,
566 (SCM vm),
567 "")
568#define FUNC_NAME s_scm_vm_apply_hook
a98cef7e 569{
17e90c5e 570 VM_DEFINE_HOOK (SCM_VM_APPLY_HOOK);
a98cef7e
KN
571}
572#undef FUNC_NAME
573
17e90c5e 574SCM_DEFINE (scm_vm_exit_hook, "vm-exit-hook", 1, 0, 0,
a98cef7e 575 (SCM vm),
17e90c5e
KN
576 "")
577#define FUNC_NAME s_scm_vm_exit_hook
a98cef7e 578{
17e90c5e 579 VM_DEFINE_HOOK (SCM_VM_EXIT_HOOK);
a98cef7e
KN
580}
581#undef FUNC_NAME
582
17e90c5e 583SCM_DEFINE (scm_vm_return_hook, "vm-return-hook", 1, 0, 0,
a98cef7e 584 (SCM vm),
17e90c5e
KN
585 "")
586#define FUNC_NAME s_scm_vm_return_hook
a98cef7e 587{
17e90c5e 588 VM_DEFINE_HOOK (SCM_VM_RETURN_HOOK);
a98cef7e
KN
589}
590#undef FUNC_NAME
591
17e90c5e
KN
592SCM_DEFINE (scm_vm_option, "vm-option", 2, 0, 0,
593 (SCM vm, SCM key),
594 "")
595#define FUNC_NAME s_scm_vm_option
a98cef7e
KN
596{
597 SCM_VALIDATE_VM (1, vm);
17e90c5e 598 return scm_assq_ref (SCM_VM_DATA (vm)->options, key);
a98cef7e
KN
599}
600#undef FUNC_NAME
601
17e90c5e
KN
602SCM_DEFINE (scm_set_vm_option_x, "set-vm-option!", 3, 0, 0,
603 (SCM vm, SCM key, SCM val),
604 "")
605#define FUNC_NAME s_scm_set_vm_option_x
a98cef7e
KN
606{
607 SCM_VALIDATE_VM (1, vm);
17e90c5e
KN
608 SCM_VM_DATA (vm)->options
609 = scm_assq_set_x (SCM_VM_DATA (vm)->options, key, val);
610 return SCM_UNSPECIFIED;
a98cef7e
KN
611}
612#undef FUNC_NAME
613
17e90c5e 614SCM_DEFINE (scm_vm_stats, "vm-stats", 1, 0, 0,
a98cef7e 615 (SCM vm),
17e90c5e
KN
616 "")
617#define FUNC_NAME s_scm_vm_stats
a98cef7e 618{
17e90c5e
KN
619 SCM stats;
620
a98cef7e 621 SCM_VALIDATE_VM (1, vm);
17e90c5e 622
2d80426a
LC
623 stats = scm_make_vector (SCM_I_MAKINUM (2), SCM_UNSPECIFIED);
624 scm_vector_set_x (stats, SCM_I_MAKINUM (0),
f9e8c09d 625 scm_from_ulong (SCM_VM_DATA (vm)->time));
2d80426a 626 scm_vector_set_x (stats, SCM_I_MAKINUM (1),
f9e8c09d 627 scm_from_ulong (SCM_VM_DATA (vm)->clock));
17e90c5e
KN
628
629 return stats;
a98cef7e
KN
630}
631#undef FUNC_NAME
632
17e90c5e
KN
633#define VM_CHECK_RUNNING(vm) \
634 if (!SCM_VM_DATA (vm)->ip) \
635 SCM_MISC_ERROR ("Not running", SCM_LIST1 (vm))
636
af988bbf 637SCM_DEFINE (scm_vm_this_frame, "vm-this-frame", 1, 0, 0,
a98cef7e 638 (SCM vm),
17e90c5e 639 "")
af988bbf 640#define FUNC_NAME s_scm_vm_this_frame
a98cef7e
KN
641{
642 SCM_VALIDATE_VM (1, vm);
af988bbf 643 return SCM_VM_DATA (vm)->this_frame;
ac99cb0c
KN
644}
645#undef FUNC_NAME
646
647SCM_DEFINE (scm_vm_last_frame, "vm-last-frame", 1, 0, 0,
648 (SCM vm),
649 "")
650#define FUNC_NAME s_scm_vm_last_frame
651{
652 SCM_VALIDATE_VM (1, vm);
653 return SCM_VM_DATA (vm)->last_frame;
a98cef7e
KN
654}
655#undef FUNC_NAME
656
d0168f3d
AW
657SCM_DEFINE (scm_vm_last_ip, "vm:last-ip", 1, 0, 0,
658 (SCM vm),
659 "")
660#define FUNC_NAME s_scm_vm_last_ip
661{
662 SCM_VALIDATE_VM (1, vm);
663 return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->last_ip);
664}
665#undef FUNC_NAME
666
68a2e18a
AW
667SCM_DEFINE (scm_vm_save_stack, "vm-save-stack", 1, 0, 0,
668 (SCM vm),
669 "")
670#define FUNC_NAME s_scm_vm_save_stack
671{
17d1b4bf
AW
672 struct scm_vm *vp;
673 SCM *dest;
68a2e18a 674 SCM_VALIDATE_VM (1, vm);
17d1b4bf 675 vp = SCM_VM_DATA (vm);
7e4760e4
AW
676
677 if (vp->fp)
678 {
0570c3f1
AW
679#ifdef VM_ENABLE_STACK_NULLING
680 if (vp->sp >= vp->stack_base)
681 if (!vp->sp[0] || vp->sp[1])
682 abort ();
683#endif
7e4760e4
AW
684 vp->last_frame = vm_heapify_frames_1 (vp, vp->fp, vp->sp, &dest);
685 vp->last_ip = vp->ip;
686 }
687 else
688 {
689 vp->last_frame = SCM_BOOL_F;
690 }
691
692
17d1b4bf 693 return vp->last_frame;
68a2e18a
AW
694}
695#undef FUNC_NAME
696
17e90c5e
KN
697SCM_DEFINE (scm_vm_fetch_code, "vm-fetch-code", 1, 0, 0,
698 (SCM vm),
699 "")
700#define FUNC_NAME s_scm_vm_fetch_code
701{
702 int i;
703 SCM list;
704 scm_byte_t *ip;
705 struct scm_instruction *p;
a98cef7e 706
17e90c5e
KN
707 SCM_VALIDATE_VM (1, vm);
708 VM_CHECK_RUNNING (vm);
a98cef7e 709
17e90c5e
KN
710 ip = SCM_VM_DATA (vm)->ip;
711 p = SCM_INSTRUCTION (*ip);
a98cef7e 712
17e90c5e
KN
713 list = SCM_LIST1 (scm_str2symbol (p->name));
714 for (i = 1; i <= p->len; i++)
2d80426a 715 list = scm_cons (SCM_I_MAKINUM (ip[i]), list);
17e90c5e
KN
716 return scm_reverse_x (list, SCM_EOL);
717}
718#undef FUNC_NAME
719
720SCM_DEFINE (scm_vm_fetch_stack, "vm-fetch-stack", 1, 0, 0,
721 (SCM vm),
722 "")
723#define FUNC_NAME s_scm_vm_fetch_stack
a98cef7e 724{
3616e9e9
KN
725 SCM *sp;
726 SCM ls = SCM_EOL;
727 struct scm_vm *vp;
a98cef7e
KN
728
729 SCM_VALIDATE_VM (1, vm);
17e90c5e 730 VM_CHECK_RUNNING (vm);
a98cef7e 731
3616e9e9 732 vp = SCM_VM_DATA (vm);
af988bbf 733 for (sp = vp->stack_base; sp <= vp->sp; sp++)
3616e9e9
KN
734 ls = scm_cons (*sp, ls);
735 return ls;
a98cef7e
KN
736}
737#undef FUNC_NAME
738
739\f
740/*
17e90c5e 741 * Initialize
a98cef7e
KN
742 */
743
07e56b27
AW
744SCM scm_load_compiled_with_vm (SCM file)
745{
3de80ed5 746 SCM program = scm_objcode_to_program (scm_load_objcode (file), SCM_EOL);
07e56b27 747
7bbed518 748 return vm_run (scm_the_vm (), program, SCM_EOL);
07e56b27
AW
749}
750
17e90c5e 751void
07e56b27 752scm_bootstrap_vm (void)
17e90c5e 753{
07e56b27
AW
754 static int strappage = 0;
755
756 if (strappage)
757 return;
758
759 scm_bootstrap_frames ();
760 scm_bootstrap_instructions ();
761 scm_bootstrap_objcodes ();
762 scm_bootstrap_programs ();
a98cef7e 763
17e90c5e
KN
764 scm_tc16_vm_cont = scm_make_smob_type ("vm-cont", 0);
765 scm_set_smob_mark (scm_tc16_vm_cont, vm_cont_mark);
766 scm_set_smob_free (scm_tc16_vm_cont, vm_cont_free);
a98cef7e 767
17e90c5e
KN
768 scm_tc16_vm = scm_make_smob_type ("vm", 0);
769 scm_set_smob_mark (scm_tc16_vm, vm_mark);
770 scm_set_smob_free (scm_tc16_vm, vm_free);
771 scm_set_smob_apply (scm_tc16_vm, scm_vm_apply, 1, 0, 1);
a98cef7e 772
83495480
AW
773 scm_c_define ("load-compiled",
774 scm_c_make_gsubr ("load-compiled/vm", 1, 0, 0,
775 scm_load_compiled_with_vm));
07e56b27 776
90b0be20
AW
777 sym_vm_run = scm_permanent_object (scm_from_locale_symbol ("vm-run"));
778 sym_vm_error = scm_permanent_object (scm_from_locale_symbol ("vm-error"));
779 sym_debug = scm_permanent_object (scm_from_locale_symbol ("debug"));
780
07e56b27
AW
781 strappage = 1;
782}
783
784void
785scm_init_vm (void)
786{
787 scm_bootstrap_vm ();
788
17e90c5e 789#ifndef SCM_MAGIC_SNARFER
a98cef7e 790#include "vm.x"
17e90c5e 791#endif
a98cef7e 792}
17e90c5e
KN
793
794/*
795 Local Variables:
796 c-file-style: "gnu"
797 End:
798*/