* libguile/control.h: Remove scm_t_prompt_registers and
scm_c_make_prompt_registers.
(scm_c_abort): Take a pointer to a jmpbuf instead of a cookie. It
will serve the same purpose.
* libguile/control.c (reify_partial_continuation, scm_at_abort): Adapt
to new prompt representation.
* libguile/dynstack.h:
* libguile/dynstack.c (scm_dynstack_push_prompt): Prompts now have 5
words instead of 2, as they now push the fp, sp, ip, and jmpbuf on the
stack separately. This avoids allocation.
(scm_dynstack_find_prompt): Likewise, add return values for fp, sp,
etc.
(scm_dynstack_wind_prompt): Replaces scm_dynstack_relocate_prompt.
* libguile/eval.c (eval):
* libguile/stacks.c (find_prompt):
* libguile/throw.c (pre_init_catch): Adapt to the new prompt mechanism.
* libguile/vm-engine.c (vm_engine): Setjmp an on-stack jmpbuf every time
the VM enters. We can then re-use that jmpbuf for all prompts in that
invocation.
* libguile/vm-i-system.c (partial_cont_call): Adapt to change in prompt
representation. We don't need to wind here any more, since we pass in
the prompt's jmpbuf.
(prompt): Adapt to scm_dynstack_push_prompt change.
(abort): Adapt to vm_abort change.
* libguile/vm.h (struct scm_vm): No more cookie.
* libguile/vm.c (vm_abort): Adapt to scm_c_abort change.
(vm_reinstate_partial_continuation): Rewind the dynamic stack here,
now that we do have a valid jmpbuf.
(make_vm): No need to initialize a cookie.
* libguile/vm-i-system.c (wind):
* module/language/tree-il/compile-glil.scm (flatten-lambda-case):
Instead of making `wind' call `scm_thunk_p' on the winder and unwinder
at runtime, make it the responsibility of the compiler to emit code to
call thunk? and error, but only if the compiler cannot prove them to
be thunks.
* libguile/vm-engine.c (vm_engine): Remove a now-unused error block.
* libguile/dynstack.h:
* libguile/dynstack.c: New files, implementing the dynamic stack as a
true stack instead of a linked list. This lowers the cost of
dynwinds: frames, winders, prompts, with-fluids, and dynamic-wind.
For the most part, we allocate these items directly on the stack.
* libguile/dynwinds.h:
* libguile/dynwinds.c: Adapt all manipulators of the wind stack to use
interfaces from dynstack.c. Remove heap-allocated winder and frame
object types.
(scm_dowinds, scm_i_dowinds): Remove these. The first was exported,
but it was not a public interface.
* libguile/continuations.c:
* libguile/continuations.h (scm_t_contregs): Continuation objects
reference scm_t_dynstack* values now. Adapt to the new interfaces.
* libguile/control.c:
* libguile/control.h: There is no longer a scm_tc7_prompt kind of object
that can be allocated on the heap. Instead, the prompt flags, key,
and registers are pushed on the dynwind stack. (The registers are
still on the heap.) Also, since the vm_cont will reference the
dynwinds, make the partial continuation stub take just one extra arg,
instead of storing the intwinds separately in the object table.
* libguile/fluids.c:
* libguile/fluids.h: No more with-fluids objects; instead, the fluids go
on the dynstack. The values still have to be on the heap, though.
(scm_prepare_fluids, scm_swap_fluids): New internal functions,
replacing scm_i_make_with_fluids and scm_i_swap_with_fluids.
* libguile/print.c: Remove prompt and with-fluids printers.
* libguile/tags.h: Revert prompt and with-fluids tc7 values to what they
were before they were allocated.
* libguile/vm-i-system.c (partial_cont_call): Just pop the vmcont, the
intwinds will not be passed as a second arg. Rewind the dynamic stack
from within the VM, so that any rewinder sees valid prompt entries.
(call_cc, tail_call_cc): Adapt to pass the dynstack to
scm_i_vm_capture_stack.
(prompt, wind, unwind, wind_fluids, unwind_fluids): Adapt to the new
interfaces.
* libguile/vm.h (scm_i_capture_current_stack): Rename from
scm_i_vm_capture_continuation.
(scm_i_vm_capture_stack): Take a dynstack as an argument.
* libguile/vm.c (vm_reinstate_partial_continuation): Don't wind here, as
that could result in winders seeing invalid prompts.
* libguile/eval.c:
* libguile/root.c:
* libguile/stacks.c:
* libguile/threads.c:
* libguile/threads.h:
* libguile/throw.c: Adapt other users of dynwinds to use the dynstack.
* libguile/boolean.c (scm_nil_p): New function.
* libguile/vm-i-scheme.c (nilp, not_nilp):
* libguile/vm-i-system.c (br_if_nil, br_if_not_nil): New instructions.
Renumber other ops.
* libguile/_scm.h (SCM_OBJCODE_MINOR_VERSION): Increment.
* module/language/assembly/compile-bytecode.scm (compile-bytecode): Add
support for writing `br-if-nil' and `br-if-not-nil' instructions.
* module/language/assembly/disassemble.scm (code-annotation): Add
`br-if-nil' and `br-if-not-nil' to the list of branch instructions.
* module/language/tree-il/compile-glil.scm: Add `nil?' to
`*primcall-ops*'.
(flatten): Use the new branch instructions for `nil?' conditionals.
* module/language/tree-il/primitives.scm: Add `nil?' to
`*interesting-primitive-names*', `*effect-free-primitives', and
`*effect+exception-free-primitives*'.
* libguile/vm-engine.h (DEAD): New macro, nulls out a value.
* libguile/vm-i-system.c:
* libguile/vm-i-loader.c:
* libguile/vm-i-scheme.c: Use DEAD when variables become dead.
Later we can #ifdef this out, but I want to give the buildbots a try
with this patch to make sure it's correct.
Fixes part of <http://bugs.gnu.org/10520>.
Reported by Bruno Haible <bruno@clisp.org>.
* libguile/vm-i-system.c (COMPILER_BARRIER): New macro.
(halt, return, return_values): Insert compiler barrier after each
assignment to `fp'.
* libguile/fluids.c (grow_dynamic_state, new_fluid): Arrange for the
default value in the dynamic-state vector to be SCM_UNDEFINED instead
of SCM_BOOL_F. If the value in the dynamic-state is #f, default to a
value attached to the fluid instead. This allows useful default
values.
(scm_make_fluid_with_default): New function, allows the user to
specify a default value for the fluid. Defaults to #f. Bound to
`make-fluid' on the Scheme side.
(scm_make_unbound_fluid): Use SCM_UNDEFINED as the default in all
threads.
(scm_fluid_unset_x): Also unset the default value. Not sure if this
is the right thing.
(fluid_ref): Update to the new default-value strategy.
* libguile/threads.c (scm_i_reset_fluid): Reset to SCM_UNDEFINED.
* libguile/threads.h: Remove extra arg to scm_i_reset_fluid.
* libguile/vm-i-system.c (fluid-ref): Update to new default-value
strategy.
* module/ice-9/vlist.scm (block-growth-factor): Default to 2 in all
threads. Fixes http://debbugs.gnu.org/10093.
* libguile/__scm.h (SCM_ASYNC_TICK_WITH_CODE): Redefine to take a
scm_i_thread* as well. OK to do because it's within a
BUILDING_LIBGUILE block.
* libguile/vm-engine.c (vm_engine): Cache the scm_i_thread* instead of
the dynstate, so we can use the thread for ticks.
* libguile/vm-engine.h (VM_HANDLE_INTERRUPTS): Tick with the
scm_i_thread* local var, to avoid excessive tls calls.
* libguile/vm-i-system.c: Fix dynstate users to use
current_thread->dynamic_state.
* libguile/vm-engine.c (VM_CHECK_OBJECT, VM_CHECK_FREE_VARIABLES): Set
to 0 for both engines. These are really internal debugging variables,
which don't affect user-visible features, provided that the compiler
is correct of course.
(VM_CHECK_UNDERFLOW): New var, also off by default: whether to check
for stack underflow when popping values.
(vm_engine): Don't declare object_count if we are not checking object
table accesses.
* libguile/vm-engine.h (CACHE_PROGRAM): Don't muck with object_count
if we are not checking object table accesses.
(CHECK_UNDERFLOW, PRE_CHECK_UNDERFLOW): Nop out if we are not checking
underflow.
(POP2, POP3): New macros which check for underflow before popping more
than one value.
* libguile/vm-i-loader.c (load_array):
* libguile/vm-i-scheme.c (set_car, set_cdr, vector_set, slot_set)
(BV_SET_WITH_ENDIANNESS, BV_FIXABLE_INT_SET, BV_INT_SET)
(BV_FLOAT_SET):
* libguile/vm-i-system.c (partial_cont_call, fix_closure, prompt)
(fluid_set): Use POP2 / POP3.
(local_set, long_local_set): Pop to locals instead of using values on
the stack then dropping; allows for underflow to be checked before the
value is accessed.
(BR): Don't NULLSTACK or DROP after the operation.
(br_if, br_if_not, br_if_eq, br_if_not_eq, br_if_null)
(br_if_not_null): Pop to locals before doing the compare and jump.
* libguile/vm-i-system.c (new-frame): Though it was appealing to set the
dynamic link here on the incomplete frame, we no longer do that, for
the reasons mentioned in the code.
(call, mv-call): Adapt to set the frame's dynamic link.
* libguile/vm-engine.c (vm_engine): Don't set dynamic link here, even
for boot program.
* libguile/frames.c (scm_frame_num_locals, scm_frame_local_ref)
(scm_frame_local_set_x): Fix up not-yet-active frame detection.
* libguile/vm-i-system.c (variable-ref, variable-set, variable-bound?):
Check that the argument is actually a variable. Thanks to Kevin
Holmes for the report.
* libguile/vm-engine.c (vm_engine): Error handling down here.
* THANKS: Update.
* libguile/fluids.c (scm_make_undefined_fluid, scm_fluid_unset_x)
(scm_fluid_bound_p): New functions.
(fluid_ref): New function; like scm_fluid_ref, but will not throw an
error for unbound fluids.
(scm_fluid_ref, swap_fluid): Use `fluid_ref'.
* libguile/fluids.h (scm_make_undefined_fluid, scm_fluid_unset_x)
(scm_fluid_bound_p): New prototypes.
* libguile/vm-i-system.c (fluid_ref): If fluid is unbound, jump to
`vm_error_unbound_fluid'.
* libguile/vm-engine.c (VM_NAME)[vm_error_unbound_fluid]: New error
message.
* test-suite/tests/fluids.test ("unbound fluids")["fluid-ref of unbound
fluid", "fluid-bound? of bound fluid", "fluid-bound? of unbound
fluid", "unbound fluids can be set", "bound fluids can be unset"]: New
tests.
* libguile/vm-i-system.c (variable-ref, toplevel-ref)
(long-toplevel-ref): Fixup callers.
* libguile/vm-engine.c (vm_error_unbound): Don't use vm-error for
unbound vars, use misc-error. Don't include VM: in the string. Take
the name directly in finish_args, not as a list.
* libguile/vm-i-system.c (VM_DEFINE_INSTRUCTION): Drop the stack items
corresponding the the with-fluids object. Thanks very much to Stefan
Israelsson Tampe for the fix.
* libguile/vm-i-scheme.c (symbol?, vector?): New
instructions. Renumbered the rest.
* libguile/vm-i-system.c: Renumber instructions.
* libguile/_scm.h (SCM_OBJCODE_MINOR_VERSION): Bump.
* module/ice-9/psyntax.scm (binding-type, binding-value): Define using
macros so that we inline to car and cdr opcodes. Oh, for an inliner :)
* module/language/tree-il/compile-glil.scm (*primcall-ops*)
* module/language/tree-il/primitives.scm
(*interesting-primitive-names*, *effect-free-primitives*)
(*effect+exception-free-primitives*): Add symbol? and vector?
inlines.
* libguile/vm-i-system.c (call_cc, tail_call_cc): Call the new
RESTORE_CONTINUATION_HOOK when a continuation is restored.
(prompt): Call the new ABORT_CONTINUATION_HOOK when entering the abort
handler's continuation.
* libguile/vm-engine.h (ABORT_CONTINUATION_HOOK)
(RESTORE_CONTINUATION_HOOK):
* libguile/vm.h (SCM_VM_ABORT_CONTINUATION_HOOK)
(SCM_VM_RESTORE_CONTINUATION_HOOK):
* libguile/vm.c: (scm_vm_abort_continuation_hook): New hook, called when
entering an abort handler.
(scm_vm_restore_continuation_hook): New hook, called after returning
to a continuation.
* module/system/vm/vm.scm: Add hooks to export list.
* libguile/vm.h (SCM_VM_PUSH_CONTINUATION_HOOK)
(SCM_VM_POP_CONTINUATION_HOOK): New hooks, to replace
enter/exit/return.
(SCM_VM_BOOT_HOOK, SCM_VM_HALT_HOOK, SCM_VM_BREAK_HOOK): Remove these
useless hooks.
* libguile/vm.c (scm_vm_push_continuation_hook)
(scm_vm_pop_continuation_hook): New accessors.
* libguile/vm-i-system.c: Remove boot, halt, break, enter, exit, and
return hooks. Also remove the break instruction. Instead now when we
push a new continuation onto the stack we call PUSH_CONTINUATION_HOOK,
and when we pop via a return we call POP_CONTINUATION_HOOK. APPLY_HOOK
is now decoupled from continuation pushes and pops.
* libguile/vm-engine.h:
* libguile/vm-engine.c: Adapt for hooks.
* module/system/vm/trace.scm (vm-trace): Adapt for hooks. Also revive
the #:instructions? #t mode.
* module/system/vm/vm.scm: Adapt exports for new set of hooks.
* libguile/vm-engine.c (VM_NAME)[vm_error_unbound]: Add comment.
* libguile/vm-i-system.c (variable_ref): Attempt provide the name of X
in FINISH_ARGS.
* libguile/vm-engine.c: Add func_name local, for error reporting.
(vm_error_apply_to_non_list): New error case.
(vm_error_wrong_type_arg): Remove this generic error case.
(vm_error_wrong_type_apply): Remove FUNC_NAME -- no sense in seeing
"vm-debug-engine" in the error report.
(vm_error_not_a_pair, vm_error_not_a_bytevector)
(vm_error_not_a_struct, vm_error_not_a_thunk): Use func_name instead
of FUNC_NAME, so we can indicate what caused the error.
* libguile/vm-i-scheme.c (VM_VALIDATE_CONS, car, cdr, set-car!)
(set-cdr!): Indicate provenance of errors.
(VM_VALIDATE_STRUCT, struct-vtable):
(VM_VALIDATE_BYTEVECTOR, BV_FIXABLE_INT_REF, BV_INT_REF)
(BV_FLOAT_REF, BV_FIXABLE_INT_SET, BV_INT_SET, BV_FLOAT_SET): Same.
* libguile/vm-i-system.c (apply, tail-apply): Use
vm_error_apply_to_non_list.
* libguile/vm-i-system.c (assert-nargs-ee/locals): New instruction, a
combination of assert-nargs-ee and reserve-locals in the case in which
nreq and nlocs can both be represented in 8 bits.
* module/language/glil/compile-assembly.scm (glil->assembly): Add
compiler case.
* doc/ref/vm.texi (Function Prologue Instructions): Update docs.
* libguile/pairs.h (scm_is_null): Nil is also null.
* libguile/vm-i-scheme.c (not, not-not, null?, not-null?):
* libguile/vm-i-system.c (br-if-null, br-if-not-null): Remove some more
nil special cases.
* libguile/boolean.h (scm_is_false): Recognize nil as false, by default.
(scm_is_bool): Recognize nil as a boolean.
* libguile/boolean.c (scm_not, scm_boolean, scm_to_bool, scm_is_bool):
Adapt to treat nil as false.
* libguile/vm-i-system.c (br-if, br-if-not): Just use scm_is_false
instead of specifically mentioning nil.
* libguile/vm-i-system.c (continuation_call): Sync before calling a
continuation. Shouldn't much matter, but it seems like a good idea.
(wind-fluids): More importantly, sync before allocating a with-fluids
object.
* libguile/control.h (SCM_PROMPT_HANDLER): Remove, it was unused.
(SCM_PROMPT_DYNWINDS): Rename from SCM_PROMPT_DYNENV.
* libguile/control.c: (scm_c_make_prompt): Take another arg, the winds
that are to be in place for the prompt. Fix allocation to be 4 words
instead of 5 (the handler was never used).
* libguile/eval.c (eval):
* libguile/throw.c (pre_init_catch): Adapt to scm_c_make_prompt change.
* libguile/vm-i-system.c (partial-cont-call): Grovel the new elements of
the wind list in order to call setjmp() on the new prompts. Pass
cookie to vm_reinstate_partial_continuation.
(prompt): Adapt to scm_c_make_prompt change.
* libguile/vm.c (vm_reinstate_partial_continuation): Take a cookie arg,
used when winding captured prompts onto the stack. Winding a prompt
implies making a new prompt, actually -- with new registers, a new
jump buffer, new winds, etc.
* test-suite/tests/control.test ("rewinding prompts"): Add a test for
rewinding prompts.
* libguile/control.h:
* libguile/control.c (scm_c_make_prompt): Instead of taking a VM arg,
take the registers directly.
(scm_c_abort): Declare as returning void. In fact it will never
return.
* libguile/eval.c (eval):
* libguile/throw.c (pre_init_catch): Adapt to prompt API change.
* libguile/vm-i-system.c (prompt): Pass the abort ip as the ip to
scm_c_make_prompt. This fixes a bug in which we used the "offset"
local var, but it wasn't guaranteed to be around after a longjmp.
* libguile/vm-engine.c (vm_error_continuation_not_rewindable):
* libguile/vm-i-system.c (partial-cont-call):
* libguile/vm.h (SCM_VM_CONT_PARTIAL_P):
(SCM_VM_CONT_REWINDABLE_P): Fix a bug in which we weren't checking if
a partial continuation was actually rewindable.
* libguile/control.c (cont_objcode):
* libguile/vm-i-system.c (partial-cont-call):
* libguile/vm.c (vm_reinstate_partial_continuation): Don't keep the
"external winds" in a partial continuation, as they aren't logically
part of the continuation. Reinstate the "internal winds" when entering
a partial continuation. Things seem to work!
* libguile/vm-i-system.c (partial-cont-call): Sync registers before
splatting a partial continuation, and cache them back afterwards.
* libguile/vm.c (vm_reinstate_partial_continuation): Actually implement,
except dynamic-wind.
* libguile/control.c (cont_objcode): Along with a bunch of boilerplate
that certainly needs to go in some central place, define this
continuation-calling trampoline.
(reify_partial_continuation): New function, returns a procedure that
when called will reinstate a partial continuation.
(scm_c_abort): Take an extra arg, the cookie. Actually reify a
continuation.
(scm_at_abort): Adapt to scm_c_abort change.
* libguile/control.h: Declare scm_c_abort change.
* libguile/vm-i-system.c (partial_cont_call): New instruction.
(call/cc, tail-call/cc): Adapt to scm_i_vm_capture_stack change.
(abort): Pass vm_cookie to abort.
* libguile/vm.h (SCM_F_VM_CONT_PARTIAL, SCM_F_VM_CONT_REWINDABLE): New
flags.
(struct scm_vm_cont): Add flags field.
(SCM_VM_CONT_PARTIAL_P, SCM_VM_CONT_REWINDABLE_P): New predicates.
* libguile/vm.c (scm_i_vm_capture_stack): Rename from
vm_capture_continuation, and make internal instead of static. Take a
flags argument.
(scm_i_vm_capture_continuation): Adapt to scm_i_vm_capture_stack
change.
(vm_abort): Plumb cookie to scm_c_abort.
(vm_reinstate_partial_continuation): New stub.
* libguile/control.h:
* libguile/control.c (scm_c_make_prompt): Take an extra arg, a cookie.
Continuations will be rewindable only if the abort has the same cookie
as the prompt.
(scm_at_abort): Redefine from scm_abort, and instead of taking rest
args, take the abort values as a list directly. Also, don't allow
rewinding, because we won't support rewinding the C stack with
delimited continuations.
* libguile/eval.c (eval): Adapt to scm_c_make_prompt change.
* libguile/vm-engine.c (vm_engine): Use vp->cookie to get a unique value
corresponding to this VM invocation.
* libguile/vm-i-system.c (prompt): Pass the cookie to scm_c_make_prompt.
(abort): Take an additional tail arg.
* libguile/vm.c (vm_abort): Parse out the abort tail arg. This is for
the @abort case, or the (apply abort ...) case.
(make_vm): Initialize the cookie to 0.
* libguile/vm.h (struct scm_vm): Add cookie.
* module/ice-9/boot-9.scm (abort): Define here as a trampoline to
@abort. Needed to make sure that a call to abort dispatches to a VM
opcode, so the cookie will be the same.
* module/language/tree-il.scm (<tree-il>): Add a "tail" field to
<abort>, for the (apply abort ...) case, or (@abort tag args). Should
be #<const ()> in the normal case. Add support throughout.
* module/language/tree-il/analyze.scm (analyze-lexicals): Add abort-tail
support here too.
* module/language/tree-il/compile-glil.scm (flatten): Compile the tail
argument appropriately.
* module/language/tree-il/primitives.scm (*primitive-expand-table*): Fix
@abort and abort cases to pass the tail arg to make-abort.
* libguile/control.h:
* libguile/control.c: Remove scm_atcontrol and scm_atprompt.
(scm_c_make_prompt): Remove handler arg, as the handler is inline.
(scm_abort): New primitive, exported to Scheme as `abort'. The
compiler will also recognize calls to `abort', but this is the base
case.
(scm_init_control): Remove scm_register_control, just have this
function, which adds `abort' to the `(guile)' module.
* libguile/eval.c (eval): Add SCM_M_PROMPT case.
* libguile/init.c (scm_i_init_guile): Change scm_register_control call
into a nice orderly scm_init_control call.
* libguile/memoize.h: (scm_sym_at_prompt, SCM_M_PROMPT):
* libguile/memoize.c (MAKMEMO_PROMPT, scm_m_at_prompt, unmemoize): Add
prompt support to the memoizer.
* libguile/vm-i-system.c (prompt): Fix to not expect a handler on the
stack.
* module/ice-9/boot-9.scm (prompt): Add definition in terms of @prompt.
* module/ice-9/control.scm: Simplify, and don't play with the compiler
here, now that prompt and abort are primitive.
* module/ice-9/eval.scm (primitive-eval): Add a prompt case.
* module/language/tree-il/primitives.scm
(*interesting-primitive-names*): Add @prompt and prompt.
* libguile/control.h:
* libguile/control.c (scm_c_abort): Add an implementation of `abort',
but it doesn't reify the continuation yet.
* libguile/vm-i-system.c (abort):
* libguile/vm.c (vm_abort): Wire up the call to `abort', avoiding
consing the args into a list.
* module/language/tree-il/compile-glil.scm (flatten): Add some compily
bits that can allow the abort to be resumed.
* libguile/vm-engine.c (vm_engine): Cache the dynamic state in a local
var when we enter the VM.
* libguile/vm-i-system.c (wind-fluids, unwind-fluids): Use the cached
dynamic state instead of going through SCM_I_CURRENT_THREAD.