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