* libguile/vm.c (prepare_smob_call): New helper. Now, instead of making
a per-smob trampoline, we will shuffle the smob into the args and use
a gsubr. This prevents a memory leak in which the trampolines, which
were values in a weak-key table, were preventing the smobs from being
collected.
* libguile/vm-i-system.c (call, tail-call, mv-call): Adapt to new smob
application mechanism.
(smob-call): Remove this instruction.
* libguile/smob.h (scm_smob_descriptor): Rename apply_trampoline_objcode
to apply_trampoline.
* libguile/smob.c: Remove our own objcode trampolines in favor of using
scm_c_make_gsubr.
(scm_smob_prehistory): No more trampoline weak map.
* libguile/procprop.c (scm_i_procedure_arity): Adapt to applicable smob
representation change.
* 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.
* libguile/control.h:
* libguile/control.c (scm_c_make_prompt, SCM_PROMPT_PRE_UNWIND_HANDLER):
* libguile/vm-i-system.c (prompt)
* module/language/tree-il.scm (<prompt> prompt-pre-unwind-handler):
* module/language/tree-il/analyze.scm:
* module/language/tree-il/compile-glil.scm:
* module/language/tree-il/inline.scm:
* module/language/tree-il/primitives.scm: Remove the "pre-unwind"
handler from prompt; it turns out not to be necessary. Adapt all
references.
* libguile/vm.h (struct scm_vm_cont): Instead of saving the "IP", save
"RA" and "MVRA". That is, save singly-valued and multiply-valued
return addresses, so that we can return multiple values on the stack.
(scm_i_vm_reinstate_continuation): Remove.
* libguile/vm.c (vm_capture_continuation): Rename from capture_vm_cont,
and change the prototype so we can capture the RA and MVRA, and so
that tail calls to call/cc can capture a continuation without the
call/cc application frame.
(vm_return_to_continuation): Rename from reinstate_vm_cont, and take
arguments to return to the continuation. Handles returning to single
or multiple-value RA.
(scm_i_vm_capture_continuation): Change to invoke
vm_capture_continuation. Kept around for the benefit of make-stack.
* libguile/vm-i-system.c (continuation-call): Handle reinstatement of
the VM stack, with arguments.
(call/cc, tail-call/cc): Adapt to new vm_capture_continuation
prototype. tail-call/cc captures tail continuations.
* libguile/stacks.c (scm_make_stack): Update for scm_vm_cont structure
change.
* libguile/continuations.h (struct scm_contregs): Remove throw_value
member, which was used to return a value to a continuation.
(scm_i_check_continuation): New internal function, checks that a
continuation may be reinstated.
(scm_i_reinstate_continuation): Replaces scm_i_continuation_call; just
reinstates the C stack.
(scm_i_contregs_vm, scm_i_contregs_vm_cont): New internal accessors.
* libguile/continuations.c (scm_i_make_continuation): Return
SCM_UNDEFINED if we are returning again.
(grow_stack, copy_stack_and_call, scm_dynthrow): Remove extra arg, as
vm opcodes handle value returns.
(copy_stack): No need to instate VM continuation.
(scm_i_reinstate_continuation): Adapt.
* libguile/continuations.h:
* libguile/continuations.c (scm_i_make_continuation): Take VM and VM
continuation arguments as well; I'm not convinced that saving all VM
continuations was the right thing, and in any case we only ever saved
the latest. Running a new VM should create a continuation barrier.
* libguile/stacks.c (scm_make_stack):
* libguile/vm-i-system.c (call/cc, tail-call/cc): Adapt callers.
* libguile/vm.h (scm_i_vm_capture_continuation)
(scm_i_vm_reinstate_continuation): Change to be internal, and to only
capture and reinstate continuations for a particular VM.
* libguile/vm-i-system.c (continuation-call): New op, like subr-call or
foreign-call, but for continuations.
* libguile/continuations.h: Add scm_i_continuation_call internal
declaration.
(SCM_CONTINUATIONP): Reimplement in terms of
SCM_PROGRAM_IS_CONTINUATION.
(scm_tc16_continuation, SCM_CONTREGS, SCM_CONTINUATION_LENGTH)
(SCM_SET_CONTINUATION_LENGTH, SCM_JMPBUF, SCM_DYNENV, SCM_THROW_VALUE)
(SCM_CONTINUATION_ROOT, SCM_DFRAME): Remove these from the exposed
API.
(scm_i_continuation_to_frame): New internal declaration.
* libguile/continuations.c
* libguile/continuations.c: Add trickery like in foreign.c, smob.c, and
gsubr.c, so that we can make procedural trampolines for continuations.
(scm_i_continuation_to_frame): New internal function, from stacks.c.
* libguile/programs.h (SCM_F_PROGRAM_IS_CONTINUATION)
(SCM_PROGRAM_IS_CONTINUATION): Add a flag for programs that are
continuations. Probably should add flags for the other trampoline
types too.
* libguile/programs.c (scm_i_program_print): Print continuations as
before.
* libguile/stacks.c (scm_stack_id, scm_make_stack): Use
scm_i_continuation_to_frame in the continuation case.