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