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