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