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