Remove MVRA accessors in libguile
[bpt/guile.git] / libguile / vm.c
CommitLineData
aab9d46c 1/* Copyright (C) 2001, 2009, 2010, 2011, 2012, 2013 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>
daccfef4 25#include <alignof.h>
17e90c5e 26#include <string.h>
e78d4bf9 27#include <stdint.h>
e3eb628d 28
1c44468d 29#include "libguile/bdw-gc.h"
e3eb628d
LC
30#include <gc/gc_mark.h>
31
560b9c25 32#include "_scm.h"
adaf86ec 33#include "control.h"
ac99cb0c 34#include "frames.h"
17e90c5e 35#include "instructions.h"
8f5cfc81 36#include "objcodes.h"
ac99cb0c 37#include "programs.h"
a98cef7e 38#include "vm.h"
486013d6 39#include "vm-builtins.h"
a98cef7e 40
aab9d46c
SIT
41#include "private-gc.h" /* scm_getenv_int */
42
97b18a66 43static int vm_default_engine = SCM_VM_REGULAR_ENGINE;
ea9f4f4b
AW
44
45/* Unfortunately we can't snarf these: snarfed things are only loaded up from
46 (system vm vm), which might not be loaded before an error happens. */
47static SCM sym_vm_run;
48static SCM sym_vm_error;
49static SCM sym_keyword_argument_error;
50static SCM sym_regular;
51static SCM sym_debug;
a98cef7e 52
11ea1aba
AW
53/* The VM has a number of internal assertions that shouldn't normally be
54 necessary, but might be if you think you found a bug in the VM. */
55#define VM_ENABLE_ASSERTIONS
56
57/* We can add a mode that ensures that all stack items above the stack pointer
58 are NULL. This is useful for checking the internal consistency of the VM's
59 assumptions and its operators, but isn't necessary for normal operation. It
616167fc 60 will ensure that assertions are enabled. Slows down the VM by about 30%. */
747a1635 61/* NB! If you enable this, search for NULLING in throw.c */
616167fc 62/* #define VM_ENABLE_STACK_NULLING */
11ea1aba 63
53e28ed9
AW
64/* #define VM_ENABLE_PARANOID_ASSERTIONS */
65
11ea1aba
AW
66#if defined (VM_ENABLE_STACK_NULLING) && !defined (VM_ENABLE_ASSERTIONS)
67#define VM_ENABLE_ASSERTIONS
68#endif
69
e3eb628d
LC
70/* When defined, arrange so that the GC doesn't scan the VM stack beyond its
71 current SP. This should help avoid excess data retention. See
72 http://thread.gmane.org/gmane.comp.programming.garbage-collection.boehmgc/3001
73 for a discussion. */
74#define VM_ENABLE_PRECISE_STACK_GC_SCAN
75
f1046e6b
LC
76/* Size in SCM objects of the stack reserve. The reserve is used to run
77 exception handling code in case of a VM stack overflow. */
78#define VM_STACK_RESERVE_SIZE 512
79
e3eb628d 80
a98cef7e 81\f
a98cef7e
KN
82/*
83 * VM Continuation
84 */
85
6f3b0cc2
AW
86void
87scm_i_vm_cont_print (SCM x, SCM port, scm_print_state *pstate)
88{
0607ebbf 89 scm_puts_unlocked ("#<vm-continuation ", port);
6f3b0cc2 90 scm_uintprint (SCM_UNPACK (x), 16, port);
0607ebbf 91 scm_puts_unlocked (">", port);
6f3b0cc2 92}
17e90c5e 93
d8873dfe
AW
94/* In theory, a number of vm instances can be active in the call trace, and we
95 only want to reify the continuations of those in the current continuation
96 root. I don't see a nice way to do this -- ideally it would involve dynwinds,
97 and previous values of the *the-vm* fluid within the current continuation
98 root. But we don't have access to continuation roots in the dynwind stack.
99 So, just punt for now, we just capture the continuation for the current VM.
100
101 While I'm on the topic, ideally we could avoid copying the C stack if the
102 continuation root is inside VM code, and call/cc was invoked within that same
103 call to vm_run; but that's currently not implemented.
104 */
cee1d22c
AW
105SCM
106scm_i_vm_capture_stack (SCM *stack_base, SCM *fp, SCM *sp, scm_t_uint8 *ra,
840ec334 107 scm_t_dynstack *dynstack, scm_t_uint32 flags)
a98cef7e 108{
d8873dfe
AW
109 struct scm_vm_cont *p;
110
111 p = scm_gc_malloc (sizeof (*p), "capture_vm_cont");
112 p->stack_size = sp - stack_base + 1;
d8eeb67c
LC
113 p->stack_base = scm_gc_malloc (p->stack_size * sizeof (SCM),
114 "capture_vm_cont");
d8873dfe
AW
115#if defined(VM_ENABLE_STACK_NULLING) && 0
116 /* Tail continuations leave their frame on the stack for subsequent
117 application, but don't capture the frame -- so there are some elements on
118 the stack then, and this check doesn't work, so disable it for now. */
119 if (sp >= vp->stack_base)
66db076a
AW
120 if (!vp->sp[0] || vp->sp[1])
121 abort ();
11ea1aba
AW
122 memset (p->stack_base, 0, p->stack_size * sizeof (SCM));
123#endif
d8873dfe 124 p->ra = ra;
d8873dfe
AW
125 p->sp = sp;
126 p->fp = fp;
127 memcpy (p->stack_base, stack_base, (sp + 1 - stack_base) * sizeof (SCM));
128 p->reloc = p->stack_base - stack_base;
9ede013f 129 p->dynstack = dynstack;
cee1d22c 130 p->flags = flags;
6f3b0cc2 131 return scm_cell (scm_tc7_vm_cont, (scm_t_bits)p);
a98cef7e
KN
132}
133
134static void
d8873dfe 135vm_return_to_continuation (SCM vm, SCM cont, size_t n, SCM *argv)
a98cef7e 136{
d8873dfe
AW
137 struct scm_vm *vp;
138 struct scm_vm_cont *cp;
139 SCM *argv_copy;
140
141 argv_copy = alloca (n * sizeof(SCM));
142 memcpy (argv_copy, argv, n * sizeof(SCM));
143
144 vp = SCM_VM_DATA (vm);
145 cp = SCM_VM_CONT_DATA (cont);
146
03f16599 147 if (vp->stack_size < cp->stack_size + n + 4)
29366989
AW
148 scm_misc_error ("vm-engine", "not enough space to reinstate continuation",
149 scm_list_2 (vm, cont));
150
11ea1aba
AW
151#ifdef VM_ENABLE_STACK_NULLING
152 {
d8873dfe 153 scm_t_ptrdiff nzero = (vp->sp - cp->sp);
11ea1aba 154 if (nzero > 0)
d8873dfe 155 memset (vp->stack_base + cp->stack_size, 0, nzero * sizeof (SCM));
66db076a
AW
156 /* actually nzero should always be negative, because vm_reset_stack will
157 unwind the stack to some point *below* this continuation */
11ea1aba
AW
158 }
159#endif
d8873dfe
AW
160 vp->sp = cp->sp;
161 vp->fp = cp->fp;
162 memcpy (vp->stack_base, cp->stack_base, cp->stack_size * sizeof (SCM));
bfffd258 163
03f16599
AW
164 {
165 size_t i;
166
167 /* Push on an empty frame, as the continuation expects. */
168 for (i = 0; i < 4; i++)
169 {
170 vp->sp++;
171 *vp->sp = SCM_BOOL_F;
172 }
173
174 /* Push the return values. */
175 for (i = 0; i < n; i++)
176 {
177 vp->sp++;
178 *vp->sp = argv_copy[i];
179 }
840ec334 180 vp->ip = cp->ra;
03f16599 181 }
d8873dfe 182}
bfffd258 183
bfffd258 184SCM
9ede013f 185scm_i_capture_current_stack (void)
bfffd258 186{
9ede013f
AW
187 scm_i_thread *thread;
188 SCM vm;
189 struct scm_vm *vp;
190
191 thread = SCM_I_CURRENT_THREAD;
192 vm = scm_the_vm ();
193 vp = SCM_VM_DATA (vm);
194
840ec334 195 return scm_i_vm_capture_stack (vp->stack_base, vp->fp, vp->sp, vp->ip,
9ede013f
AW
196 scm_dynstack_capture_all (&thread->dynstack),
197 0);
a98cef7e
KN
198}
199
c850a0ff
AW
200static void vm_dispatch_hook (SCM vm, int hook_num,
201 SCM *argv, int n) SCM_NOINLINE;
202
b1b942b7 203static void
c850a0ff 204vm_dispatch_hook (SCM vm, int hook_num, SCM *argv, int n)
b1b942b7 205{
7656f194
AW
206 struct scm_vm *vp;
207 SCM hook;
b3567435 208 struct scm_frame c_frame;
8e4c60ff 209 scm_t_cell *frame;
893fb8d0 210 int saved_trace_level;
b1b942b7 211
7656f194
AW
212 vp = SCM_VM_DATA (vm);
213 hook = vp->hooks[hook_num];
b1b942b7 214
7656f194
AW
215 if (SCM_LIKELY (scm_is_false (hook))
216 || scm_is_null (SCM_HOOK_PROCEDURES (hook)))
217 return;
b3567435 218
893fb8d0
AW
219 saved_trace_level = vp->trace_level;
220 vp->trace_level = 0;
b3567435
LC
221
222 /* Allocate a frame object on the stack. This is more efficient than calling
223 `scm_c_make_frame ()' to allocate on the heap, but it forces hooks to not
224 capture frame objects.
225
226 At the same time, procedures such as `frame-procedure' make sense only
227 while the stack frame represented by the frame object is visible, so it
228 seems reasonable to limit the lifetime of frame objects. */
229
230 c_frame.stack_holder = vm;
231 c_frame.fp = vp->fp;
232 c_frame.sp = vp->sp;
233 c_frame.ip = vp->ip;
234 c_frame.offset = 0;
8e4c60ff
LC
235
236 /* Arrange for FRAME to be 8-byte aligned, like any other cell. */
237 frame = alloca (sizeof (*frame) + 8);
238 frame = (scm_t_cell *) ROUND_UP ((scm_t_uintptr) frame, 8UL);
239
240 frame->word_0 = SCM_PACK (scm_tc7_frame);
21041372 241 frame->word_1 = SCM_PACK_POINTER (&c_frame);
b3567435 242
c850a0ff
AW
243 if (n == 0)
244 {
245 SCM args[1];
246
247 args[0] = SCM_PACK_POINTER (frame);
248 scm_c_run_hookn (hook, args, 1);
249 }
250 else if (n == 1)
251 {
252 SCM args[2];
253
254 args[0] = SCM_PACK_POINTER (frame);
255 args[1] = argv[0];
256 scm_c_run_hookn (hook, args, 2);
257 }
258 else
259 {
260 SCM args = SCM_EOL;
261
262 while (n--)
263 args = scm_cons (argv[n], args);
264 scm_c_run_hook (hook, scm_cons (SCM_PACK_POINTER (frame), args));
265 }
b3567435 266
893fb8d0 267 vp->trace_level = saved_trace_level;
b1b942b7
AW
268}
269
4f66bcde 270static void
99511cd0
AW
271vm_abort (SCM vm, SCM tag, size_t nstack, SCM *stack_args, SCM tail, SCM *sp,
272 scm_i_jmp_buf *current_registers) SCM_NORETURN;
9d381ba4
AW
273
274static void
99511cd0
AW
275vm_abort (SCM vm, SCM tag, size_t nstack, SCM *stack_args, SCM tail, SCM *sp,
276 scm_i_jmp_buf *current_registers)
4f66bcde 277{
eaefabee 278 size_t i;
2d026f04 279 ssize_t tail_len;
99511cd0 280 SCM *argv;
eaefabee 281
2d026f04
AW
282 tail_len = scm_ilength (tail);
283 if (tail_len < 0)
29366989
AW
284 scm_misc_error ("vm-engine", "tail values to abort should be a list",
285 scm_list_1 (tail));
286
99511cd0
AW
287 argv = alloca ((nstack + tail_len) * sizeof (SCM));
288 for (i = 0; i < nstack; i++)
289 argv[i] = stack_args[i];
290 for (; i < nstack + tail_len; i++, tail = scm_cdr (tail))
2d026f04 291 argv[i] = scm_car (tail);
eaefabee 292
99511cd0
AW
293 /* FIXME: NULLSTACK (SCM_VM_DATA (vp)->sp - sp) */
294 SCM_VM_DATA (vm)->sp = sp;
295
296 scm_c_abort (vm, tag, nstack + tail_len, argv, current_registers);
cee1d22c
AW
297}
298
9d381ba4
AW
299static void
300vm_reinstate_partial_continuation (SCM vm, SCM cont, size_t n, SCM *argv,
301 scm_t_dynstack *dynstack,
302 scm_i_jmp_buf *registers)
cee1d22c 303{
07801437
AW
304 struct scm_vm *vp;
305 struct scm_vm_cont *cp;
306 SCM *argv_copy, *base;
9ede013f 307 scm_t_ptrdiff reloc;
07801437
AW
308 size_t i;
309
310 argv_copy = alloca (n * sizeof(SCM));
311 memcpy (argv_copy, argv, n * sizeof(SCM));
312
313 vp = SCM_VM_DATA (vm);
314 cp = SCM_VM_CONT_DATA (cont);
315 base = SCM_FRAME_UPPER_ADDRESS (vp->fp) + 1;
9ede013f 316 reloc = cp->reloc + (base - cp->stack_base);
07801437 317
0fc9040f 318#define RELOC(scm_p) \
9ede013f 319 (((SCM *) (scm_p)) + reloc)
07801437
AW
320
321 if ((base - vp->stack_base) + cp->stack_size + n + 1 > vp->stack_size)
29366989
AW
322 scm_misc_error ("vm-engine",
323 "not enough space to instate partial continuation",
324 scm_list_2 (vm, cont));
07801437
AW
325
326 memcpy (base, cp->stack_base, cp->stack_size * sizeof (SCM));
327
328 /* now relocate frame pointers */
329 {
330 SCM *fp;
331 for (fp = RELOC (cp->fp);
332 SCM_FRAME_LOWER_ADDRESS (fp) > base;
333 fp = SCM_FRAME_DYNAMIC_LINK (fp))
334 SCM_FRAME_SET_DYNAMIC_LINK (fp, RELOC (SCM_FRAME_DYNAMIC_LINK (fp)));
335 }
336
337 vp->sp = base - 1 + cp->stack_size;
338 vp->fp = RELOC (cp->fp);
840ec334 339 vp->ip = cp->ra;
07801437 340
840ec334 341 /* Push the arguments. */
07801437
AW
342 for (i = 0; i < n; i++)
343 {
344 vp->sp++;
345 *vp->sp = argv_copy[i];
346 }
9a1c6f1f 347
9d381ba4
AW
348 /* The prompt captured a slice of the dynamic stack. Here we wind
349 those entries onto the current thread's stack. We also have to
350 relocate any prompts that we see along the way. */
351 {
352 scm_t_bits *walk;
353
354 for (walk = SCM_DYNSTACK_FIRST (cp->dynstack);
355 SCM_DYNSTACK_TAG (walk);
356 walk = SCM_DYNSTACK_NEXT (walk))
357 {
358 scm_t_bits tag = SCM_DYNSTACK_TAG (walk);
359
360 if (SCM_DYNSTACK_TAG_TYPE (tag) == SCM_DYNSTACK_TYPE_PROMPT)
361 scm_dynstack_wind_prompt (dynstack, walk, reloc, registers);
362 else
363 scm_dynstack_wind_1 (dynstack, walk);
364 }
365 }
adbdfd6d 366#undef RELOC
4f66bcde
AW
367}
368
369\f
17e90c5e
KN
370/*
371 * VM Internal functions
372 */
373
6f3b0cc2
AW
374void
375scm_i_vm_print (SCM x, SCM port, scm_print_state *pstate)
376{
0a935b2a
LC
377 const struct scm_vm *vm;
378
379 vm = SCM_VM_DATA (x);
380
0607ebbf 381 scm_puts_unlocked ("#<vm ", port);
0a935b2a
LC
382 switch (vm->engine)
383 {
384 case SCM_VM_REGULAR_ENGINE:
0607ebbf 385 scm_puts_unlocked ("regular-engine ", port);
0a935b2a
LC
386 break;
387
388 case SCM_VM_DEBUG_ENGINE:
0607ebbf 389 scm_puts_unlocked ("debug-engine ", port);
0a935b2a
LC
390 break;
391
392 default:
0607ebbf 393 scm_puts_unlocked ("unknown-engine ", port);
0a935b2a 394 }
6f3b0cc2 395 scm_uintprint (SCM_UNPACK (x), 16, port);
0607ebbf 396 scm_puts_unlocked (">", port);
6f3b0cc2
AW
397}
398
53bdfcf0
AW
399\f
400/*
401 * VM Error Handling
402 */
403
404static void vm_error (const char *msg, SCM arg) SCM_NORETURN;
4d497b62
AW
405static void vm_error_bad_instruction (scm_t_uint32 inst) SCM_NORETURN SCM_NOINLINE;
406static void vm_error_unbound (SCM proc, SCM sym) SCM_NORETURN SCM_NOINLINE;
407static void vm_error_unbound_fluid (SCM proc, SCM fluid) SCM_NORETURN SCM_NOINLINE;
408static void vm_error_not_a_variable (const char *func_name, SCM x) SCM_NORETURN SCM_NOINLINE;
409static void vm_error_apply_to_non_list (SCM x) SCM_NORETURN SCM_NOINLINE;
410static void vm_error_kwargs_length_not_even (SCM proc) SCM_NORETURN SCM_NOINLINE;
28d5d253
MW
411static void vm_error_kwargs_invalid_keyword (SCM proc, SCM obj) SCM_NORETURN SCM_NOINLINE;
412static void vm_error_kwargs_unrecognized_keyword (SCM proc, SCM kw) SCM_NORETURN SCM_NOINLINE;
4d497b62
AW
413static void vm_error_too_many_args (int nargs) SCM_NORETURN SCM_NOINLINE;
414static void vm_error_wrong_num_args (SCM proc) SCM_NORETURN SCM_NOINLINE;
415static void vm_error_wrong_type_apply (SCM proc) SCM_NORETURN SCM_NOINLINE;
416static void vm_error_stack_overflow (struct scm_vm *vp) SCM_NORETURN SCM_NOINLINE;
417static void vm_error_stack_underflow (void) SCM_NORETURN SCM_NOINLINE;
418static void vm_error_improper_list (SCM x) SCM_NORETURN SCM_NOINLINE;
419static void vm_error_not_a_pair (const char *subr, SCM x) SCM_NORETURN SCM_NOINLINE;
420static void vm_error_not_a_bytevector (const char *subr, SCM x) SCM_NORETURN SCM_NOINLINE;
421static void vm_error_not_a_struct (const char *subr, SCM x) SCM_NORETURN SCM_NOINLINE;
422static void vm_error_no_values (void) SCM_NORETURN SCM_NOINLINE;
423static void vm_error_not_enough_values (void) SCM_NORETURN SCM_NOINLINE;
82f4bac4 424static void vm_error_wrong_number_of_values (scm_t_uint32 expected) SCM_NORETURN SCM_NOINLINE;
4d497b62
AW
425static void vm_error_continuation_not_rewindable (SCM cont) SCM_NORETURN SCM_NOINLINE;
426static void vm_error_bad_wide_string_length (size_t len) SCM_NORETURN SCM_NOINLINE;
53bdfcf0
AW
427
428static void
429vm_error (const char *msg, SCM arg)
430{
431 scm_throw (sym_vm_error,
432 scm_list_3 (sym_vm_run, scm_from_latin1_string (msg),
433 SCM_UNBNDP (arg) ? SCM_EOL : scm_list_1 (arg)));
434 abort(); /* not reached */
435}
436
437static void
438vm_error_bad_instruction (scm_t_uint32 inst)
439{
440 vm_error ("VM: Bad instruction: ~s", scm_from_uint32 (inst));
441}
442
443static void
444vm_error_unbound (SCM proc, SCM sym)
445{
446 scm_error_scm (scm_misc_error_key, proc,
447 scm_from_latin1_string ("Unbound variable: ~s"),
448 scm_list_1 (sym), SCM_BOOL_F);
449}
450
451static void
452vm_error_unbound_fluid (SCM proc, SCM fluid)
453{
454 scm_error_scm (scm_misc_error_key, proc,
455 scm_from_latin1_string ("Unbound fluid: ~s"),
456 scm_list_1 (fluid), SCM_BOOL_F);
457}
458
459static void
460vm_error_not_a_variable (const char *func_name, SCM x)
461{
462 scm_error (scm_arg_type_key, func_name, "Not a variable: ~S",
463 scm_list_1 (x), scm_list_1 (x));
464}
465
53bdfcf0
AW
466static void
467vm_error_apply_to_non_list (SCM x)
468{
469 scm_error (scm_arg_type_key, "apply", "Apply to non-list: ~S",
470 scm_list_1 (x), scm_list_1 (x));
471}
472
473static void
474vm_error_kwargs_length_not_even (SCM proc)
475{
476 scm_error_scm (sym_keyword_argument_error, proc,
477 scm_from_latin1_string ("Odd length of keyword argument list"),
478 SCM_EOL, SCM_BOOL_F);
479}
480
481static void
4af0d97e 482vm_error_kwargs_invalid_keyword (SCM proc, SCM obj)
53bdfcf0
AW
483{
484 scm_error_scm (sym_keyword_argument_error, proc,
485 scm_from_latin1_string ("Invalid keyword"),
4af0d97e 486 SCM_EOL, scm_list_1 (obj));
53bdfcf0
AW
487}
488
489static void
4af0d97e 490vm_error_kwargs_unrecognized_keyword (SCM proc, SCM kw)
53bdfcf0
AW
491{
492 scm_error_scm (sym_keyword_argument_error, proc,
493 scm_from_latin1_string ("Unrecognized keyword"),
4af0d97e 494 SCM_EOL, scm_list_1 (kw));
53bdfcf0
AW
495}
496
497static void
498vm_error_too_many_args (int nargs)
499{
500 vm_error ("VM: Too many arguments", scm_from_int (nargs));
501}
502
503static void
504vm_error_wrong_num_args (SCM proc)
505{
506 scm_wrong_num_args (proc);
507}
508
509static void
510vm_error_wrong_type_apply (SCM proc)
511{
512 scm_error (scm_arg_type_key, NULL, "Wrong type to apply: ~S",
513 scm_list_1 (proc), scm_list_1 (proc));
514}
515
516static void
517vm_error_stack_overflow (struct scm_vm *vp)
518{
519 if (vp->stack_limit < vp->stack_base + vp->stack_size)
520 /* There are VM_STACK_RESERVE_SIZE bytes left. Make them available so
521 that `throw' below can run on this VM. */
522 vp->stack_limit = vp->stack_base + vp->stack_size;
523 else
524 /* There is no space left on the stack. FIXME: Do something more
525 sensible here! */
526 abort ();
527 vm_error ("VM: Stack overflow", SCM_UNDEFINED);
528}
529
530static void
531vm_error_stack_underflow (void)
532{
533 vm_error ("VM: Stack underflow", SCM_UNDEFINED);
534}
535
536static void
537vm_error_improper_list (SCM x)
538{
539 vm_error ("Expected a proper list, but got object with tail ~s", x);
540}
541
542static void
543vm_error_not_a_pair (const char *subr, SCM x)
544{
545 scm_wrong_type_arg_msg (subr, 1, x, "pair");
546}
547
548static void
549vm_error_not_a_bytevector (const char *subr, SCM x)
550{
551 scm_wrong_type_arg_msg (subr, 1, x, "bytevector");
552}
553
554static void
555vm_error_not_a_struct (const char *subr, SCM x)
556{
557 scm_wrong_type_arg_msg (subr, 1, x, "struct");
558}
559
560static void
561vm_error_no_values (void)
562{
563 vm_error ("Zero values returned to single-valued continuation",
564 SCM_UNDEFINED);
565}
566
567static void
568vm_error_not_enough_values (void)
569{
570 vm_error ("Too few values returned to continuation", SCM_UNDEFINED);
571}
572
82f4bac4
AW
573static void
574vm_error_wrong_number_of_values (scm_t_uint32 expected)
575{
576 vm_error ("Wrong number of values returned to continuation (expected ~a)",
577 scm_from_uint32 (expected));
578}
579
53bdfcf0
AW
580static void
581vm_error_continuation_not_rewindable (SCM cont)
582{
583 vm_error ("Unrewindable partial continuation", cont);
584}
585
586static void
587vm_error_bad_wide_string_length (size_t len)
588{
589 vm_error ("VM: Bad wide string length: ~S", scm_from_size_t (len));
590}
591
53bdfcf0
AW
592
593\f
28b119ee 594
510ca126 595static SCM rtl_boot_continuation;
486013d6
AW
596static SCM vm_builtin_apply;
597static SCM vm_builtin_values;
598static SCM vm_builtin_abort_to_prompt;
599static SCM vm_builtin_call_with_values;
600static SCM vm_builtin_call_with_current_continuation;
510ca126
AW
601
602static const scm_t_uint32 rtl_boot_continuation_code[] = {
7396d216 603 SCM_PACK_RTL_24 (scm_rtl_op_halt, 0)
510ca126
AW
604};
605
486013d6
AW
606static const scm_t_uint32 vm_builtin_apply_code[] = {
607 SCM_PACK_RTL_24 (scm_rtl_op_assert_nargs_ge, 3),
608 SCM_PACK_RTL_24 (scm_rtl_op_tail_apply, 0), /* proc in r1, args from r2 */
510ca126
AW
609};
610
486013d6 611static const scm_t_uint32 vm_builtin_values_code[] = {
af95414f 612 SCM_PACK_RTL_24 (scm_rtl_op_return_values, 0) /* vals from r1 */
510ca126
AW
613};
614
486013d6
AW
615static const scm_t_uint32 vm_builtin_abort_to_prompt_code[] = {
616 SCM_PACK_RTL_24 (scm_rtl_op_assert_nargs_ge, 2),
617 SCM_PACK_RTL_24 (scm_rtl_op_abort, 0), /* tag in r1, vals from r2 */
618 /* FIXME: Partial continuation should capture caller regs. */
619 SCM_PACK_RTL_24 (scm_rtl_op_return_values, 0) /* vals from r1 */
620};
621
622static const scm_t_uint32 vm_builtin_call_with_values_code[] = {
623 SCM_PACK_RTL_24 (scm_rtl_op_assert_nargs_ee, 3),
624 SCM_PACK_RTL_24 (scm_rtl_op_alloc_frame, 7),
625 SCM_PACK_RTL_12_12 (scm_rtl_op_mov, 6, 1),
626 SCM_PACK_RTL_24 (scm_rtl_op_call, 6), SCM_PACK_RTL_24 (0, 1),
627 SCM_PACK_RTL_12_12 (scm_rtl_op_mov, 0, 2),
628 SCM_PACK_RTL_24 (scm_rtl_op_tail_call_shuffle, 7)
629};
630
631static const scm_t_uint32 vm_builtin_call_with_current_continuation_code[] = {
632 SCM_PACK_RTL_24 (scm_rtl_op_assert_nargs_ee, 2),
633 SCM_PACK_RTL_24 (scm_rtl_op_call_cc, 0)
634};
635
636
637static SCM
638scm_vm_builtin_ref (unsigned idx)
639{
640 switch (idx)
641 {
9f309e2c 642#define INDEX_TO_NAME(builtin, BUILTIN, req, opt, rest) \
486013d6
AW
643 case SCM_VM_BUILTIN_##BUILTIN: return vm_builtin_##builtin;
644 FOR_EACH_VM_BUILTIN(INDEX_TO_NAME)
645#undef INDEX_TO_NAME
646 default: abort();
647 }
648}
649
9f309e2c 650SCM scm_sym_apply;
486013d6
AW
651static SCM scm_sym_values;
652static SCM scm_sym_abort_to_prompt;
653static SCM scm_sym_call_with_values;
654static SCM scm_sym_call_with_current_continuation;
655
656SCM
657scm_vm_builtin_name_to_index (SCM name)
658#define FUNC_NAME "builtin-name->index"
659{
660 SCM_VALIDATE_SYMBOL (1, name);
661
9f309e2c 662#define NAME_TO_INDEX(builtin, BUILTIN, req, opt, rest) \
486013d6
AW
663 if (scm_is_eq (name, scm_sym_##builtin)) \
664 return scm_from_uint (SCM_VM_BUILTIN_##BUILTIN);
665 FOR_EACH_VM_BUILTIN(NAME_TO_INDEX)
666#undef NAME_TO_INDEX
667
668 return SCM_BOOL_F;
669}
670#undef FUNC_NAME
671
672SCM
673scm_vm_builtin_index_to_name (SCM index)
674#define FUNC_NAME "builtin-index->name"
675{
676 unsigned idx;
677
678 SCM_VALIDATE_UINT_COPY (1, index, idx);
679
680 switch (idx)
681 {
9f309e2c 682#define INDEX_TO_NAME(builtin, BUILTIN, req, opt, rest) \
486013d6
AW
683 case SCM_VM_BUILTIN_##BUILTIN: return scm_sym_##builtin;
684 FOR_EACH_VM_BUILTIN(INDEX_TO_NAME)
685#undef INDEX_TO_NAME
686 default: return SCM_BOOL_F;
687 }
688}
689#undef FUNC_NAME
690
691static void
692scm_init_vm_builtins (void)
693{
486013d6
AW
694 scm_c_define_gsubr ("builtin-name->index", 1, 0, 0,
695 scm_vm_builtin_name_to_index);
696 scm_c_define_gsubr ("builtin-index->name", 1, 0, 0,
697 scm_vm_builtin_index_to_name);
698}
699
700SCM
701scm_i_call_with_current_continuation (SCM proc)
702{
703 return scm_call_1 (vm_builtin_call_with_current_continuation, proc);
704}
510ca126 705
a98cef7e
KN
706\f
707/*
708 * VM
709 */
710
b7393ea1 711static SCM
b782ed01 712resolve_variable (SCM what, SCM module)
b7393ea1 713{
9bd48cb1 714 if (SCM_LIKELY (scm_is_symbol (what)))
b7393ea1 715 {
b782ed01
AW
716 if (scm_is_true (module))
717 return scm_module_lookup (module, what);
b7393ea1 718 else
62e15979 719 return scm_module_lookup (scm_the_root_module (), what);
b7393ea1
AW
720 }
721 else
722 {
b782ed01
AW
723 SCM modname, sym, public;
724
725 modname = SCM_CAR (what);
726 sym = SCM_CADR (what);
727 public = SCM_CADDR (what);
728
d6fbf0c0
AW
729 if (!scm_module_system_booted_p)
730 {
731#ifdef VM_ENABLE_PARANOID_ASSERTIONS
732 ASSERT (scm_is_false (public));
733 ASSERT (scm_is_true
734 (scm_equal_p (modname,
735 scm_list_1 (scm_from_utf8_symbol ("guile")))));
736#endif
737 return scm_lookup (sym);
738 }
739 else if (scm_is_true (public))
b782ed01
AW
740 return scm_public_lookup (modname, sym);
741 else
742 return scm_private_lookup (modname, sym);
b7393ea1
AW
743 }
744}
745
aab9d46c 746#define VM_MIN_STACK_SIZE (1024)
486013d6 747#define VM_DEFAULT_STACK_SIZE (256 * 1024)
aab9d46c
SIT
748static size_t vm_stack_size = VM_DEFAULT_STACK_SIZE;
749
750static void
751initialize_default_stack_size (void)
752{
753 int size = scm_getenv_int ("GUILE_STACK_SIZE", vm_stack_size);
754 if (size >= VM_MIN_STACK_SIZE)
755 vm_stack_size = size;
756}
17e90c5e 757
510ca126 758#define RTL_VM_NAME rtl_vm_regular_engine
6d14383e
AW
759#define FUNC_NAME "vm-regular-engine"
760#define VM_ENGINE SCM_VM_REGULAR_ENGINE
83495480 761#include "vm-engine.c"
510ca126 762#undef RTL_VM_NAME
6d14383e 763#undef FUNC_NAME
17e90c5e 764#undef VM_ENGINE
17e90c5e 765
510ca126 766#define RTL_VM_NAME rtl_vm_debug_engine
6d14383e
AW
767#define FUNC_NAME "vm-debug-engine"
768#define VM_ENGINE SCM_VM_DEBUG_ENGINE
83495480 769#include "vm-engine.c"
510ca126 770#undef RTL_VM_NAME
6d14383e 771#undef FUNC_NAME
17e90c5e
KN
772#undef VM_ENGINE
773
73c3db66
AW
774typedef SCM (*scm_t_rtl_vm_engine) (SCM vm, SCM program, SCM *argv, size_t nargs);
775
776static const scm_t_rtl_vm_engine rtl_vm_engines[] =
777 { rtl_vm_regular_engine, rtl_vm_debug_engine };
778
e3eb628d
LC
779#ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
780
781/* The GC "kind" for the VM stack. */
782static int vm_stack_gc_kind;
783
784#endif
785
a98cef7e 786static SCM
17e90c5e
KN
787make_vm (void)
788#define FUNC_NAME "make_vm"
a98cef7e 789{
17e90c5e 790 int i;
7f991c7d 791 struct scm_vm *vp;
747a1635 792
7f991c7d 793 vp = scm_gc_malloc (sizeof (struct scm_vm), "vm");
d8eeb67c 794
aab9d46c 795 vp->stack_size= vm_stack_size;
e3eb628d
LC
796
797#ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
4168aa46
TTN
798 vp->stack_base = (SCM *)
799 GC_generic_malloc (vp->stack_size * sizeof (SCM), vm_stack_gc_kind);
e3eb628d
LC
800
801 /* Keep a pointer to VP so that `vm_stack_mark ()' can know what the stack
802 top is. */
21041372 803 *vp->stack_base = SCM_PACK_POINTER (vp);
e3eb628d
LC
804 vp->stack_base++;
805 vp->stack_size--;
806#else
d8eeb67c
LC
807 vp->stack_base = scm_gc_malloc (vp->stack_size * sizeof (SCM),
808 "stack-base");
e3eb628d
LC
809#endif
810
2bbe1533
AW
811#ifdef VM_ENABLE_STACK_NULLING
812 memset (vp->stack_base, 0, vp->stack_size * sizeof (SCM));
813#endif
f1046e6b 814 vp->stack_limit = vp->stack_base + vp->stack_size - VM_STACK_RESERVE_SIZE;
3616e9e9
KN
815 vp->ip = NULL;
816 vp->sp = vp->stack_base - 1;
817 vp->fp = NULL;
ea9f4f4b 818 vp->engine = vm_default_engine;
7656f194 819 vp->trace_level = 0;
17e90c5e 820 for (i = 0; i < SCM_VM_NUM_HOOKS; i++)
3d5ee0cd 821 vp->hooks[i] = SCM_BOOL_F;
6f3b0cc2 822 return scm_cell (scm_tc7_vm, (scm_t_bits)vp);
a98cef7e 823}
17e90c5e 824#undef FUNC_NAME
a98cef7e 825
e3eb628d
LC
826#ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
827
828/* Mark the VM stack region between its base and its current top. */
829static struct GC_ms_entry *
830vm_stack_mark (GC_word *addr, struct GC_ms_entry *mark_stack_ptr,
831 struct GC_ms_entry *mark_stack_limit, GC_word env)
832{
833 GC_word *word;
834 const struct scm_vm *vm;
835
836 /* The first word of the VM stack should contain a pointer to the
837 corresponding VM. */
838 vm = * ((struct scm_vm **) addr);
839
8071c490 840 if (vm == NULL
f1046e6b 841 || (SCM *) addr != vm->stack_base - 1)
e3eb628d
LC
842 /* ADDR must be a pointer to a free-list element, which we must ignore
843 (see warning in <gc/gc_mark.h>). */
844 return mark_stack_ptr;
845
e3eb628d
LC
846 for (word = (GC_word *) vm->stack_base; word <= (GC_word *) vm->sp; word++)
847 mark_stack_ptr = GC_MARK_AND_PUSH ((* (GC_word **) word),
848 mark_stack_ptr, mark_stack_limit,
849 NULL);
850
851 return mark_stack_ptr;
852}
853
854#endif /* VM_ENABLE_PRECISE_STACK_GC_SCAN */
855
856
6d14383e 857SCM
4abef68f 858scm_c_vm_run (SCM vm, SCM program, SCM *argv, int nargs)
6d14383e 859{
4abef68f 860 struct scm_vm *vp = SCM_VM_DATA (vm);
b95d76fc 861 SCM_CHECK_STACK;
1c33be99 862 return rtl_vm_engines[vp->engine](vm, program, argv, nargs);
6d14383e
AW
863}
864
a98cef7e
KN
865/* Scheme interface */
866
271c3d31
LC
867SCM_DEFINE (scm_the_vm, "the-vm", 0, 0, 0,
868 (void),
869 "Return the current thread's VM.")
870#define FUNC_NAME s_scm_the_vm
871{
ea9f4f4b
AW
872 scm_i_thread *t = SCM_I_CURRENT_THREAD;
873
874 if (SCM_UNLIKELY (scm_is_false (t->vm)))
875 t->vm = make_vm ();
876
877 return t->vm;
271c3d31 878}
499a4c07
KN
879#undef FUNC_NAME
880
881
a98cef7e
KN
882SCM_DEFINE (scm_vm_p, "vm?", 1, 0, 0,
883 (SCM obj),
17e90c5e 884 "")
a98cef7e
KN
885#define FUNC_NAME s_scm_vm_p
886{
9bd48cb1 887 return scm_from_bool (SCM_VM_P (obj));
a98cef7e
KN
888}
889#undef FUNC_NAME
890
891SCM_DEFINE (scm_make_vm, "make-vm", 0, 0, 0,
17e90c5e
KN
892 (void),
893 "")
894#define FUNC_NAME s_scm_make_vm,
a98cef7e 895{
17e90c5e 896 return make_vm ();
a98cef7e
KN
897}
898#undef FUNC_NAME
899
17e90c5e 900SCM_DEFINE (scm_vm_ip, "vm:ip", 1, 0, 0,
a98cef7e 901 (SCM vm),
17e90c5e
KN
902 "")
903#define FUNC_NAME s_scm_vm_ip
a98cef7e
KN
904{
905 SCM_VALIDATE_VM (1, vm);
3d27ef4b 906 return scm_from_unsigned_integer ((scm_t_bits) SCM_VM_DATA (vm)->ip);
a98cef7e
KN
907}
908#undef FUNC_NAME
909
910SCM_DEFINE (scm_vm_sp, "vm:sp", 1, 0, 0,
911 (SCM vm),
17e90c5e 912 "")
a98cef7e
KN
913#define FUNC_NAME s_scm_vm_sp
914{
915 SCM_VALIDATE_VM (1, vm);
3d27ef4b 916 return scm_from_unsigned_integer ((scm_t_bits) SCM_VM_DATA (vm)->sp);
a98cef7e
KN
917}
918#undef FUNC_NAME
919
920SCM_DEFINE (scm_vm_fp, "vm:fp", 1, 0, 0,
921 (SCM vm),
17e90c5e 922 "")
a98cef7e
KN
923#define FUNC_NAME s_scm_vm_fp
924{
925 SCM_VALIDATE_VM (1, vm);
3d27ef4b 926 return scm_from_unsigned_integer ((scm_t_bits) SCM_VM_DATA (vm)->fp);
a98cef7e
KN
927}
928#undef FUNC_NAME
929
17e90c5e
KN
930#define VM_DEFINE_HOOK(n) \
931{ \
3d5ee0cd 932 struct scm_vm *vp; \
17e90c5e 933 SCM_VALIDATE_VM (1, vm); \
3d5ee0cd 934 vp = SCM_VM_DATA (vm); \
8b22ed7a 935 if (scm_is_false (vp->hooks[n])) \
238e7a11 936 vp->hooks[n] = scm_make_hook (SCM_I_MAKINUM (1)); \
3d5ee0cd 937 return vp->hooks[n]; \
17e90c5e
KN
938}
939
c45d4d77 940SCM_DEFINE (scm_vm_apply_hook, "vm-apply-hook", 1, 0, 0,
17e90c5e
KN
941 (SCM vm),
942 "")
c45d4d77 943#define FUNC_NAME s_scm_vm_apply_hook
a98cef7e 944{
c45d4d77 945 VM_DEFINE_HOOK (SCM_VM_APPLY_HOOK);
a98cef7e
KN
946}
947#undef FUNC_NAME
948
c45d4d77 949SCM_DEFINE (scm_vm_push_continuation_hook, "vm-push-continuation-hook", 1, 0, 0,
17e90c5e
KN
950 (SCM vm),
951 "")
c45d4d77 952#define FUNC_NAME s_scm_vm_push_continuation_hook
a98cef7e 953{
c45d4d77 954 VM_DEFINE_HOOK (SCM_VM_PUSH_CONTINUATION_HOOK);
a98cef7e
KN
955}
956#undef FUNC_NAME
957
c45d4d77 958SCM_DEFINE (scm_vm_pop_continuation_hook, "vm-pop-continuation-hook", 1, 0, 0,
a98cef7e 959 (SCM vm),
17e90c5e 960 "")
c45d4d77 961#define FUNC_NAME s_scm_vm_pop_continuation_hook
a98cef7e 962{
c45d4d77 963 VM_DEFINE_HOOK (SCM_VM_POP_CONTINUATION_HOOK);
a98cef7e
KN
964}
965#undef FUNC_NAME
966
c45d4d77 967SCM_DEFINE (scm_vm_next_hook, "vm-next-hook", 1, 0, 0,
a98cef7e 968 (SCM vm),
17e90c5e 969 "")
c45d4d77 970#define FUNC_NAME s_scm_vm_next_hook
a98cef7e 971{
c45d4d77 972 VM_DEFINE_HOOK (SCM_VM_NEXT_HOOK);
a98cef7e
KN
973}
974#undef FUNC_NAME
f3120251
AW
975
976SCM_DEFINE (scm_vm_abort_continuation_hook, "vm-abort-continuation-hook", 1, 0, 0,
977 (SCM vm),
978 "")
979#define FUNC_NAME s_scm_vm_abort_continuation_hook
980{
981 VM_DEFINE_HOOK (SCM_VM_ABORT_CONTINUATION_HOOK);
982}
983#undef FUNC_NAME
984
985SCM_DEFINE (scm_vm_restore_continuation_hook, "vm-restore-continuation-hook", 1, 0, 0,
986 (SCM vm),
987 "")
988#define FUNC_NAME s_scm_vm_restore_continuation_hook
989{
990 VM_DEFINE_HOOK (SCM_VM_RESTORE_CONTINUATION_HOOK);
991}
992#undef FUNC_NAME
a98cef7e 993
7656f194 994SCM_DEFINE (scm_vm_trace_level, "vm-trace-level", 1, 0, 0,
17e90c5e
KN
995 (SCM vm),
996 "")
7656f194 997#define FUNC_NAME s_scm_vm_trace_level
a98cef7e 998{
a98cef7e 999 SCM_VALIDATE_VM (1, vm);
7656f194
AW
1000 return scm_from_int (SCM_VM_DATA (vm)->trace_level);
1001}
1002#undef FUNC_NAME
1003
1004SCM_DEFINE (scm_set_vm_trace_level_x, "set-vm-trace-level!", 2, 0, 0,
1005 (SCM vm, SCM level),
1006 "")
1007#define FUNC_NAME s_scm_set_vm_trace_level_x
1008{
1009 SCM_VALIDATE_VM (1, vm);
1010 SCM_VM_DATA (vm)->trace_level = scm_to_int (level);
1011 return SCM_UNSPECIFIED;
a98cef7e
KN
1012}
1013#undef FUNC_NAME
1014
1015\f
ea9f4f4b
AW
1016/*
1017 * VM engines
1018 */
1019
1020static int
1021symbol_to_vm_engine (SCM engine, const char *FUNC_NAME)
1022{
1023 if (scm_is_eq (engine, sym_regular))
1024 return SCM_VM_REGULAR_ENGINE;
1025 else if (scm_is_eq (engine, sym_debug))
1026 return SCM_VM_DEBUG_ENGINE;
1027 else
1028 SCM_MISC_ERROR ("Unknown VM engine: ~a", scm_list_1 (engine));
1029}
1030
1031static SCM
1032vm_engine_to_symbol (int engine, const char *FUNC_NAME)
1033{
1034 switch (engine)
1035 {
1036 case SCM_VM_REGULAR_ENGINE:
1037 return sym_regular;
1038 case SCM_VM_DEBUG_ENGINE:
1039 return sym_debug;
1040 default:
1041 /* ? */
1042 SCM_MISC_ERROR ("Unknown VM engine: ~a",
1043 scm_list_1 (scm_from_int (engine)));
1044 }
1045}
1046
ea9f4f4b
AW
1047SCM_DEFINE (scm_vm_engine, "vm-engine", 1, 0, 0,
1048 (SCM vm),
1049 "")
1050#define FUNC_NAME s_scm_vm_engine
1051{
1052 SCM_VALIDATE_VM (1, vm);
1053 return vm_engine_to_symbol (SCM_VM_DATA (vm)->engine, FUNC_NAME);
1054}
1055#undef FUNC_NAME
1056
1057void
1058scm_c_set_vm_engine_x (SCM vm, int engine)
1059#define FUNC_NAME "set-vm-engine!"
1060{
1061 SCM_VALIDATE_VM (1, vm);
1062
ea9f4f4b
AW
1063 if (engine < 0 || engine >= SCM_VM_NUM_ENGINES)
1064 SCM_MISC_ERROR ("Unknown VM engine: ~a",
1065 scm_list_1 (scm_from_int (engine)));
1066
1067 SCM_VM_DATA (vm)->engine = engine;
1068}
1069#undef FUNC_NAME
1070
1071SCM_DEFINE (scm_set_vm_engine_x, "set-vm-engine!", 2, 0, 0,
1072 (SCM vm, SCM engine),
1073 "")
1074#define FUNC_NAME s_scm_set_vm_engine_x
1075{
1076 scm_c_set_vm_engine_x (vm, symbol_to_vm_engine (engine, FUNC_NAME));
1077 return SCM_UNSPECIFIED;
1078}
1079#undef FUNC_NAME
1080
1081void
1082scm_c_set_default_vm_engine_x (int engine)
1083#define FUNC_NAME "set-default-vm-engine!"
1084{
1085 if (engine < 0 || engine >= SCM_VM_NUM_ENGINES)
1086 SCM_MISC_ERROR ("Unknown VM engine: ~a",
1087 scm_list_1 (scm_from_int (engine)));
1088
1089 vm_default_engine = engine;
1090}
1091#undef FUNC_NAME
1092
1093SCM_DEFINE (scm_set_default_vm_engine_x, "set-default-vm-engine!", 1, 0, 0,
1094 (SCM engine),
1095 "")
1096#define FUNC_NAME s_scm_set_default_vm_engine_x
1097{
1098 scm_c_set_default_vm_engine_x (symbol_to_vm_engine (engine, FUNC_NAME));
1099 return SCM_UNSPECIFIED;
1100}
1101#undef FUNC_NAME
1102
1103static void reinstate_vm (SCM vm)
1104{
1105 scm_i_thread *t = SCM_I_CURRENT_THREAD;
1106 t->vm = vm;
1107}
1108
1109SCM_DEFINE (scm_call_with_vm, "call-with-vm", 2, 0, 1,
1110 (SCM vm, SCM proc, SCM args),
1111 "Apply @var{proc} to @var{args} in a dynamic extent in which\n"
1112 "@var{vm} is the current VM.\n\n"
1113 "As an implementation restriction, if @var{vm} is not the same\n"
1114 "as the current thread's VM, continuations captured within the\n"
1115 "call to @var{proc} may not be reinstated once control leaves\n"
1116 "@var{proc}.")
1117#define FUNC_NAME s_scm_call_with_vm
1118{
1119 SCM prev_vm, ret;
1120 SCM *argv;
1121 int i, nargs;
1122 scm_t_wind_flags flags;
1123 scm_i_thread *t = SCM_I_CURRENT_THREAD;
1124
1125 SCM_VALIDATE_VM (1, vm);
1126 SCM_VALIDATE_PROC (2, proc);
1127
1128 nargs = scm_ilength (args);
1129 if (SCM_UNLIKELY (nargs < 0))
1130 scm_wrong_type_arg_msg (FUNC_NAME, 3, args, "list");
1131
1132 argv = alloca (nargs * sizeof(SCM));
1133 for (i = 0; i < nargs; i++)
1134 {
1135 argv[i] = SCM_CAR (args);
1136 args = SCM_CDR (args);
1137 }
1138
1139 prev_vm = t->vm;
1140
1141 /* Reentry can happen via invokation of a saved continuation, but
1142 continuations only save the state of the VM that they are in at
1143 capture-time, which might be different from this one. So, in the
1144 case that the VMs are different, set up a non-rewindable frame to
1145 prevent reinstating an incomplete continuation. */
1146 flags = scm_is_eq (prev_vm, vm) ? 0 : SCM_F_WIND_EXPLICITLY;
1147 if (flags)
1148 {
1149 scm_dynwind_begin (0);
1150 scm_dynwind_unwind_handler_with_scm (reinstate_vm, prev_vm, flags);
1151 t->vm = vm;
1152 }
1153
1154 ret = scm_c_vm_run (vm, proc, argv, nargs);
1155
1156 if (flags)
1157 scm_dynwind_end ();
1158
1159 return ret;
1160}
1161#undef FUNC_NAME
1162
1163\f
a98cef7e 1164/*
17e90c5e 1165 * Initialize
a98cef7e
KN
1166 */
1167
07e56b27
AW
1168SCM scm_load_compiled_with_vm (SCM file)
1169{
b8bc86bc
AW
1170 SCM program = scm_load_thunk_from_file (file);
1171
4abef68f 1172 return scm_c_vm_run (scm_the_vm (), program, NULL, 0);
07e56b27
AW
1173}
1174
67b699cc 1175
9f309e2c
AW
1176void
1177scm_init_vm_builtin_properties (void)
1178{
1179 /* FIXME: Seems hacky to do this here, but oh well :/ */
1180 scm_sym_apply = scm_from_utf8_symbol ("apply");
1181 scm_sym_values = scm_from_utf8_symbol ("values");
1182 scm_sym_abort_to_prompt = scm_from_utf8_symbol ("abort-to-prompt");
1183 scm_sym_call_with_values = scm_from_utf8_symbol ("call-with-values");
1184 scm_sym_call_with_current_continuation =
1185 scm_from_utf8_symbol ("call-with-current-continuation");
1186
1187#define INIT_BUILTIN(builtin, BUILTIN, req, opt, rest) \
1188 scm_set_procedure_property_x (vm_builtin_##builtin, scm_sym_name, \
1189 scm_sym_##builtin); \
1190 scm_set_procedure_minimum_arity_x (vm_builtin_##builtin, \
1191 SCM_I_MAKINUM (req), \
1192 SCM_I_MAKINUM (opt), \
1193 scm_from_bool (rest));
1194 FOR_EACH_VM_BUILTIN (INIT_BUILTIN);
1195#undef INIT_BUILTIN
1196}
1197
17e90c5e 1198void
07e56b27 1199scm_bootstrap_vm (void)
17e90c5e 1200{
44602b08
AW
1201 scm_c_register_extension ("libguile-" SCM_EFFECTIVE_VERSION,
1202 "scm_init_vm",
60ae5ca2 1203 (scm_t_extension_init_func)scm_init_vm, NULL);
486013d6
AW
1204 scm_c_register_extension ("libguile-" SCM_EFFECTIVE_VERSION,
1205 "scm_init_vm_builtins",
1206 (scm_t_extension_init_func)scm_init_vm_builtins,
1207 NULL);
60ae5ca2 1208
aab9d46c
SIT
1209 initialize_default_stack_size ();
1210
4a655e50
AW
1211 sym_vm_run = scm_from_latin1_symbol ("vm-run");
1212 sym_vm_error = scm_from_latin1_symbol ("vm-error");
1213 sym_keyword_argument_error = scm_from_latin1_symbol ("keyword-argument-error");
1214 sym_regular = scm_from_latin1_symbol ("regular");
1215 sym_debug = scm_from_latin1_symbol ("debug");
0404c97d 1216
73c3db66
AW
1217 rtl_boot_continuation = scm_i_make_rtl_program (rtl_boot_continuation_code);
1218 SCM_SET_CELL_WORD_0 (rtl_boot_continuation,
1219 (SCM_CELL_WORD_0 (rtl_boot_continuation)
1220 | SCM_F_PROGRAM_IS_BOOT));
9f309e2c
AW
1221
1222#define DEFINE_BUILTIN(builtin, BUILTIN, req, opt, rest) \
1223 vm_builtin_##builtin = scm_i_make_rtl_program (vm_builtin_##builtin##_code);
1224 FOR_EACH_VM_BUILTIN (DEFINE_BUILTIN);
1225#undef DEFINE_BUILTIN
73c3db66 1226
e3eb628d
LC
1227#ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
1228 vm_stack_gc_kind =
1229 GC_new_kind (GC_new_free_list (),
1230 GC_MAKE_PROC (GC_new_proc (vm_stack_mark), 0),
1231 0, 1);
1232
1233#endif
07e56b27
AW
1234}
1235
1236void
1237scm_init_vm (void)
1238{
17e90c5e 1239#ifndef SCM_MAGIC_SNARFER
aeeff258 1240#include "libguile/vm.x"
17e90c5e 1241#endif
a98cef7e 1242}
17e90c5e
KN
1243
1244/*
1245 Local Variables:
1246 c-file-style: "gnu"
1247 End:
1248*/