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