* libguile/goops.c (SCM_GOOPS_UNBOUND, SCM_GOOPS_UNBOUNDP): Remove
internal macros.
(scm_make_unbound, scm_unbound_p): Remove internal functions.
(scm_sys_clear_fields_x): Add "unbound" parameter, for the init
value.
* module/oop/goops.scm (*unbound*): Define in Scheme as a simple
heap-allocated value.
(unbound?): New definition.
(%allocate-instance): Pass *unbound* to %clear-fields!.
(make-class, slot-definition-init-value)
(slot-definition-init-form, make-closure-variable): Use *unbound*
instead of (make-unbound), which is now gone.
* module/oop/goops/active-slot.scm (compute-get-n-set): Use *unbound*
instead of make-unbound. This module uses the GOOPS internals module;
perhaps we should export make-unbound or something...
* module/oop/goops/save.scm (make-unbound): Export our own make-unbound
definition, for use by residualized save code.
* module/language/ecmascript/base.scm (<undefined>, *undefined*): Use a
unique object kind and instance for the undefined value.
* libguile/vm.c (scm_i_vm_mark_stack): Fill the stack with
SCM_UNSPECIFIED instead of SCM_UNBOUND.
* libguile/vm.c (vm_error_unbound, vm_error_unbound_fluid): Remove proc
argument. The value in slot 0 is not necessarily the procedure being
applied, after the prelude is done.
* libguile/vm-engine.c (vm_engine): Use LOCAL_REF (0) instead of
SCM_FRAME_PROGRAM, and adapt to above changes.
* libguile/stacks.c (scm_make_stack, scm_stack_id):
* libguile/vm.c (scm_i_vm_cont_to_frame): Allow delimited continuations
as the argument to make-stack.
* libguile/gc.c (scm_oom_fn, scm_init_gc): Install an out-of-memory
handler that raises an unwind-only out-of-memory exception.
(scm_gc_warn_proc, scm_init_gc): Install a warning proc that tries to
print to the current warning port, if the current warning port is a
file port.
(scm_gc_after_nonlocal_exit): New interface. Should be called after a
nonlocal return to potentially collect memory; otherwise allocations
could try to expand again when they should collect.
* libguile/continuations.c (scm_i_make_continuation):
* libguile/eval.c (eval):
* libguile/throw.c (catch):
* libguile/vm.c (scm_call_n): Call scm_gc_after_nonlocal_exit after
nonlocal returns.
* libguile/throw.c (abort_to_prompt, throw_without_pre_unwind): Rework
to avoid allocating memory.
(scm_report_out_of_memory): New interface.
(scm_init_throw): Pre-allocate the arguments for stack-overflow and
out-of-memory errors.
* module/ice-9/boot-9.scm: Add an out-of-memory exception printer.
* module/system/repl/error-handling.scm (call-with-error-handling): Add
out-of-memory to the report-keys set.
* libguile/gc-malloc.c (scm_realloc): Call scm_report_out_of_memory if
realloc fails.
* libguile/error.h:
* libguile/error.c:
* libguile/deprecated.h:
* libguile/deprecated.c (scm_memory_error): Deprecate.
* test-suite/standalone/Makefile.am:
* test-suite/standalone/test-out-of-memory: New test case.
* libguile/vm.h:
* libguile/vm.c (default_max_stack_size, initialize_default_stack_size):
Remove the default stack limit. In this way, programs run from the
command line or outside of the REPL will have no soft stack limit.
(make_vm): Change `max_stack_size' field to be a stack of limits and
handlers.
(current_overflow_size, should_handle_stack_overflow)
(reset_stack_limit, wind_overflow_handler, unwind_overflow_handler)
(vm_expand_stack): If the stack surpasses a user-set limit, call the
user-specified handler within its outer stack limit.
(call-with-stack-overflow-handler): New interface.
* module/system/vm/vm.scm: Export call-with-stack-overflow-handler.
* libguile/vm.c:
* libguile/vm-engine.c: Change the one use of
VM_ENABLE_PARANOID_ASSERTIONS to ASSERT. That becomes the one use of
VM_ENABLE_ASSERTIONS, so disable that too.
* libguile/vm-engine.c (ALLOC_FRAME): Fold CHECK_OVERFLOW into this
routine, and rework to not extend vp->sp until the stack has been
expanded.
* libguile/vm.c (vm_increase_sp): Likewise, don't extend vp->sp until
the stack has expanded.
(vm_expand_stack): Rework to take the new stack pointer as an
argument, and also to update vp->sp_max_since_gc and vp->sp.
* module/ice-9/boot-9.scm (catch): Signal an early error if the handler
or pre-unwind handler types aren't right. This is more important than
it was, given that we dispatch on type now when finding matching catch
clauses.
* libguile/vm.c (vm_expand_stack): Use the standard
scm_report_stack_overflow to signal stack overflow. This will avoid
running pre-unwind handlers.
* libguile/throw.h: Move scm_report_stack_overflow here.
* libguile/throw.c (catch): Define a version of catch in C.
(throw_without_pre_unwind): New helper. Besides serving as the
pre-boot "throw" binding, it allows stack overflow to throw without
running pre-unwind handlers.
(scm_catch, scm_catch_with_pre_unwind_handler)
(scm_with_throw_handler): Use the new catch in C.
(scm_report_stack_overflow): Moved from stackchk.c; throws an
unwind-only exception.
* libguile/stackchk.h:
* libguile/stackchk.c: Remove the scm_report_stack_overflow bits.
* libguile/vm.c (allocate_stack, expand_stack): Return NULL on
allocation failure instead of throwing an exception. Throwing an
exception is tricky to get right, and we need more context to do it
correctly.
(return_unused_stack_to_os): Try again if madvise returns -EAGAIN. If
madvise fails, print an error message.
(vm_expand_stack): Abort if stack expansion fails. We'll fix this in
a future patch.
(make_vm): Abort if we can't mmap a single page.
* libguile/tags.h (SCM_TYP7S, SCM_HAS_TYP7S): Remove these, as we no
longer do the differs-by-one-bit thing for vectors and weak vectors.
* libguile/vectors.h (SCM_I_IS_VECTOR): Use SCM_HAS_TYP7.
(SCM_I_IS_NONWEAK_VECTOR): Remove.
* libguile/vm-engine.c (vector-length, vector-ref, vector-set!)
(vector-ref/immediate, vector-set!/immediate): We can inline these
instructions completely now.
* libguile/vm.c (vm_error_not_a_vector, vm_error_out_of_range): New
error conditions.
* libguile/vm.c (vm_increase_sp): New interface, to increase the SP to
some new level, possibly expanding the stack.
(vm_push_sp, vm_restore_sp): Intefaces to vm_increase_sp.
(vm_return_to_continuation): Don't throw an error if there's not
enough space; instead, expand.
(vm_reinstate_partial_continuation): Use the new helper.
(return_unused_stack_to_os): Avoid off-by-one error (sp points to
valid memory.)
(scm_call_n): Never write beyond the sp.
* libguile/bdw-gc.h: Remove a needless compatibility hack.
* libguile/gc-inline.h: New file, implementing thread-local freelists
providing faster allocation if we already have a scm_i_thread*
pointer. Based on gc_inline.h from libgc.
* libguile/threads.h (scm_i_thread): Add freelists here.
* libguile/threads.c (guilify_self_1, guilify_self_2): Initialize
freelists.
* libguile/vm.c: Include gc-inline.h.
* libguile/vm-engine.c: Rename current_thread to thread. Use
scm_inline_cons instead of scm_cons, scm_inline_cell instead of
scm_cell, and scm_inline_words instead of words.
* libguile/vm.h (struct scm_vm): Reorder fields. Add "sp_max_since_gc"
field.
* libguile/vm-engine.c (ALLOC_FRAME, RESET_FRAME):
* libguile/vm.c (vm_return_to_continuation)
(vm_reinstate_partial_continuation, scm_call_n): In places where we
could increase the stack height, update sp_max_since_gc.
(vm_expand_stack): Relocate sp_max_since_gc on expansion.
(scm_bootstrap_vm): Record the page size using gnulib's getpagesize.
(return_unused_stack_to_os): New routine, run when marking stacks.
* module/language/cps/slot-allocation.scm (lookup-dead-slot-map)
(allocate-slots): For each non-tail call in a function, compute the
set of slots that are dead after the function has begun the call.
* module/language/cps/compile-bytecode.scm (compile-fun): Emit the
`dead-slot-map' macro instruction for non-tail calls.
* module/system/vm/assembler.scm (<asm>): Add `dead-slot-maps' member.
(dead-slot-map): New macro-instruction.
(link-frame-maps, link-dynamic-section, link-objects): Write dead
slots information into .guile.frame-maps sections of ELF files.
* module/system/vm/elf.scm (DT_GUILE_FRAME_MAPS): New definition.
* libguile/loader.h:
* libguile/loader.c (DT_GUILE_FRAME_MAPS, process_dynamic_segment):
(load_thunk_from_memory, register_elf): Arrange to parse
DT_GUILE_FRAME_MAPS out of the dynamic section.
(find_mapped_elf_image_unlocked, find_mapped_elf_image): New helpers.
(scm_find_mapped_elf_image): Refactor.
(scm_find_dead_slot_map_unlocked): New interface.
* libguile/vm.c (scm_i_vm_mark_stack): Mark the hottest frame
conservatively, as before. Otherwise use the dead slots map, if
available, to avoid marking data that isn't live.
* libguile/vm-engine.c (CHECK_OVERFLOW): Call vm_expand_stack, not
vm_error_stack_overflow.
* libguile/vm.c (hard_max_stack_size, default_max_stack_size): Recast
#defines as locals. Have both hard and soft stack limits.
(initialize_default_stack_size): Set soft stack limit from
GUILE_STACK_SIZE.
(expand_stack, vm_expand_stack): Support for expanding stacks as
needed. Whee!
(make_vm): Adapt limits.
(scm_call_n): Expand stack if needed.
* libguile/vm.h (struct scm_vm): Add max_stack_size member.
* libguile/threads.c (thread_mark): Mark the VM stack, if we have one.
(on_thread_exit): Free the VM stack here.
* libguile/vm.c (make_vm): Allocate the VM stack using mmap, and arrange
for it to be marked by the thread marker.
(scm_i_vm_mark_stack, scm_i_vm_free_stack): New internal interfaces.
(allocate_stack, free_stack): New helpers.
* libguile/vm-engine.c (CACHE_REGISTER): Remove an unneeded cast.
(VM_NAME):
* libguile/vm.c (scm_call_n): Setjmp out here. This leaves the VM
without any initialization work to do. It also makes it possible to
restart the VM in another mode (with hooks, for example).
* libguile/vm-engine.c:
* libguile/vm.c (scm_call_n): Move boot continuation setup to
scm_call_n, so that vm-engine takes all of its state from the vp.
* libguile/vm-engine.c (VM_NAME): Take the current thread as an
argument.
* libguile/vm.c (scm_i_capture_current_stack): Call thread_vm.
(thread_vm): New helper.
(scm_the_vm): Call thread_vm.
(scm_call_n): Call thread_vm. Avoids a double TLS lookup.
* libguile/vm.c (scm_i_capture_current_stack): Cosmetic tweak.
(scm_call_n): Define here instead of in eval.c. All callers of
scm_c_vm_run were passing scm_the_vm() as the VM. Eventually
scm_call_n will replace scm_c_vm_run.
* libguile/eval.c: Adapt all callers.
* libguile/control.h:
* libguile/control.c (reify_partial_continuation, scm_c_abort): Take
struct scm_vm *vp as an arg.
* libguile/dynstack.h: Remove control.h include.
* libguile/vm.c (vm_abort): Take struct scm_vm *vp as an arg.
* libguile/vm-engine.c (abort): Adapt to vm_abort change.
* libguile/frames.h (struct scm_frame): stack_holder is a void*.
* libguile/frames.c (scm_i_frame_stack_base, scm_i_frame_offset): Expect
stack_holder to be the raw struct scm_vm or scm_vm_cont.
* libguile/continuations.c (scm_i_continuation_to_frame):
* libguile/stacks.c (scm_make_stack)
* libguile/vm.c (vm_dispatch_hook): Adapt creators.
* libguile/frames.h (enum scm_vm_frame_kind, SCM_VM_FRAME_KIND)
(scm_c_make_frame): Add a "frame kind" bit to the first word. This
will allow the "stack holder" to be a non-SCM object.
* libguile/continuations.c (scm_i_continuation_to_frame):
* libguile/frames.c (scm_c_make_frame, scm_frame_previous)
* libguile/stacks.c (scm_make_stack):
* libguile/vm.c (vm_dispatch_hook): Adapt frame creators to set the
frame kind bit.
* libguile/vm.h:
* libguile/vm.c:
(scm_vm_apply_hook, scm_vm_push_continuation_hook,
scm_vm_pop_continuation_hook, scm_vm_abort_continuation_hook,
scm_vm_restore_continuation_hook, scm_vm_next_hook,
scm_vm_trace_level, scm_set_vm_trace_level_x, scm_vm_engine,
scm_set_vm_engine_x, scm_c_set_vm_engine_x): The VM argument is now
implicit: the VM for the current thread.
* doc/ref/api-debug.texi (VM Hooks): Try to adapt.
* module/ice-9/command-line.scm:
* module/statprof.scm:
* module/system/vm/coverage.scm:
* module/system/vm/trace.scm:
* module/system/vm/trap-state.scm:
* module/system/vm/traps.scm:
* test-suite/tests/control.test:
* test-suite/tests/eval.test: Adapt users that set hooks or ensure that
we have a debug engine.
* libguile/frames.h: Wrap the C interface to VM frames in
BUILDING_LIBGUILE. Change VM frames to record relative offsets into a
stack held by some other object, so that if the stack moves they will
remain valid.
* libguile/frames.c (scm_c_make_frame): Remove offset argument.
(scm_i_frame_offset): Instead, compute the offset from the stack
holder.
(scm_i_frame_stack_base): New helper.
(scm_frame_previous): Adapt.
* libguile/stacks.c (scm_make_stack)
* libguile/vm.c (vm_dispatch_hook):
* libguile/continuations.c (scm_i_continuation_to_frame): Adapt.
* libguile/vm-engine.c (RUN_HOOK, RUN_HOOK0, RUN_HOOK1): Rework to
dispatch through specific per-hook procedures. Might reduce register
pressure in the VM.
* libguile/vm.c (vm_dispatch_apply_hook):
(vm_dispatch_push_continuation_hook):
(vm_dispatch_pop_continuation_hook):
(vm_dispatch_next_hook):
(vm_dispatch_abort_hook):
(vm_dispatch_restore_continuation_hook): New internal helpers.