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