* libguile/Makefile.am: add new header file setjump-win.h
* libguile/continuations.h, libguile/dynstack.c, libguile/dynstack.h,
libguile/intrinsics.h, libguile/vm.h:
supply custom `setjmp` macro on Windows
Mingw implements `setjmp (env)` as a macro that expands to
_setjmp (env, faddr)
where `faddr` is set to the current frame address.
This address is then stored as first element in the jump buffer `env`.
When `longjmp` is called, it tries to unwind the stack up
to the saved address by calling `RtlUnwindEx` from MSVCRT,
which will fail, if the stack frames are interwoven with
JIT-generated code, that violate the Windows x64 calling conventions.
Thus implement the macro ourselves as
_setjmp (env, NULL)
which will toggle a code path in `longjmp` that does no unwinding.
Signed-off-by: Ludovic Courtès <ludo@gnu.org>
* module/language/tree-il/primitives.scm (*interesting-primitive-names*):
(*primitive-accessors*): Add string->utf8, utf8->string, and
string-utf8-length.
(primitive-module): New public function, moved here from (language
tree-il compile-bytecode).
* module/language/tree-il/compile-bytecode.scm: Use primitive-module
from (language tree-il primitives).
* module/language/tree-il/peval.scm (peval): A bugfix: load primitives
from their proper module. Allows bytevector primitives to fold.
* module/language/cps/guile-vm/reify-primitives.scm:
* module/language/cps/effects-analysis.scm:
* module/language/cps/types.scm
* module/language/tree-il/primitives.scm:
* module/language/tree-il/cps-primitives.scm:
* module/language/tree-il/effects.scm (make-effects-analyzer):
Add string->utf8, utf8->string, and string-utf8-length.
* module/language/tree-il/compile-cps.scm (string->utf8)
(string-utf8-length, utf8->string): New custom lowerers, including type
checks and an unboxed result for string-utf8-length.
* module/system/vm/assembler.scm:
* libguile/intrinsics.h:
* libguile/intrinsics.c: Because string-utf8-length returns an unboxed
value, we need an intrinsic for it; go ahead and add an intrinsic for
string->utf8 and utf8->string too, as we will likely be able to use
these in the future.
* libguile/intrinsics.h:
* libguile/intrinsics.c (lookup_bound_public, lookup_bound_private): Two
new intrinsics.
(scm_bootstrap_intrinsics): Wire them up.
* libguile/jit.c (compile_call_scm_from_scmn_scmn):
(compile_call_scm_from_scmn_scmn_slow):
(COMPILE_X8_S24__N32__N32__C32): Add JIT support for new instruction
kind.
* libguile/vm-engine.c (call-scm<-scmn-scmn): New instruction, takes
arguments as non-immediate offsets, to avoid needless loads and register
pressure.
* module/language/cps/effects-analysis.scm: Add cases for new
primcalls.
* module/language/cps/compile-bytecode.scm (compile-function): Add new
primcalls.
* module/language/cps/reify-primitives.scm (cached-module-box): If the
variable is bound, call lookup-bound-public / lookup-bound-private as
appropriate instead of separately resolving the module, name, and doing
the bound check.
* module/language/tree-il/compile-bytecode.scm (emit-cached-module-box):
Use new instructions.
* module/system/vm/assembler.scm (define-scm<-scmn-scmn-intrinsic):
(lookup-bound-public, lookup-bound-private): Add assembler support.
This fixes a bug whereby the compiler would sometimes allocate floats in
marked space.
* libguile/gc-inline.h (scm_inline_gc_malloc_pointerless_words): New
internal helper.
* libguile/intrinsics.h (SCM_FOR_ALL_VM_INTRINSICS):
* libguile/intrinsics.c (allocate_pointerless_words):
(allocate_pointerless_words_with_freelist): New intrinsics.
* libguile/jit.c (compile_allocate_pointerless_words):
(compile_allocate_pointerless_words_immediate): New compilers.
* libguile/vm-engine.c (allocate_pointerless_words)
(allocate_pointerless_words_immediate): New opcodes.
* module/language/cps/compile-bytecode.scm (compile-function):
* module/language/cps/effects-analysis.scm (param):
* module/language/cps/reify-primitives.scm (reify-primitives):
* module/language/cps/specialize-primcalls.scm (specialize-primcalls):
* module/language/cps/types.scm (allocate-words):
(allocate-words/immediate):
* module/system/vm/assembler.scm (system): Add support for the new
opcodes.
* libguile/intrinsics.c (scm_atan1): New intrinsic, wrapping scm_atan.
(scm_bootstrap_intrinsics): Add new intrinsics.
* libguile/intrinsics.h (scm_t_f64_from_f64_f64_intrinsic): New
intrinsic type.
(SCM_FOR_ALL_VM_INTRINSICS): Add intrinsics for floor, ceiling, sin,
cos, tan, asin, acos, atan, and their unboxed counterparts.
* libguile/jit.c (sp_f64_operand): New helper.
(compile_call_f64_from_f64, compile_call_f64_from_f64_f64): Call out
to intrinsics.
* libguile/vm-engine.c (call-f64<-f64-f64): New opcode.
* module/language/cps/effects-analysis.scm: Add new intrinsics.
* module/language/cps/reify-primitives.scm (compute-known-primitives):
Add new intrinsics.
* module/language/cps/slot-allocation.scm (compute-var-representations):
Add 'f64 slot types for the new unboxed intrinsics.
* module/language/cps/specialize-numbers.scm (specialize-operations):
Support unboxing the new intrinsics.
* module/language/cps/types.scm: Define type inferrers for the new
intrinsics.
* module/language/tree-il/cps-primitives.scm: Define CPS translations
for the new intrinsics.
* module/language/tree-il/primitives.scm (*interesting-primitive-names*):
(*effect-free-primitives*, atan): Define primitive resolvers.
* module/system/vm/assembler.scm: Export assemblers for the new
intrinsics.
(define-f64<-f64-f64-intrinsic): New helper.
Some components of this have been wired up for a while; this commit
finishes the compiler, runtime, and JIT support.
* libguile/intrinsics.h (SCM_FOR_ALL_VM_INTRINSICS):
* libguile/intrinsics.c (scm_bootstrap_intrinsics): Declare the new
intrinsics.
* libguile/jit.c (compile_call_f64_from_f64): Define code generators for
the new intrinsics.
* libguile/vm-engine.c (call-f64<-f64): New instruction.
* module/language/cps/effects-analysis.scm:
* module/language/cps/reify-primitives.scm (compute-known-primitives):
* module/language/cps/slot-allocation.scm (compute-var-representations):
* module/language/cps/specialize-numbers.scm (specialize-operations):
* module/language/tree-il/cps-primitives.scm (abs):
* module/system/vm/assembler.scm (system, define-f64<-f64-intrinsic):
(sqrt, abs, fsqrt, fabs):
* module/language/cps/types.scm (fsqrt, fabs): Add new f64<-f64
primitives.
* libguile/intrinsics.h (SCM_FOR_ALL_VM_INTRINSICS):
* libguile/intrinsics.c (scm_bootstrap_intrinsics): Remove the atomic
intrinsics, as the JIT no longer needs them.
* libguile/vm-engine.c (VM_NAME): Inline the intrinsics.
* libguile/intrinsics.h (SCM_FOR_ALL_VM_INTRINSICS): Remove VM hook
intrinsics, now that we're going to rely on the interpreter for
stepping and breakpoints.
* libguile/jit.c (struct scm_jit_state): Remove "hooks_enabled" member,
now that we won't JIT. Remove all code related to calling hooks.
* libguile/vm-engine.c (RUN_HOOK): Call hooks directly instead of
through intrinsics. Use precise per-hook enable flags.
* libguile/vm.c (DEFINE_INVOKE_HOOK): New helper. Use to define the
hook invokers.
* libguile/intrinsics.h: Add "intrinsic" for handle-interrupts code.
Unlike the other intrinsics, this one isn't a function.
* libguile/programs.c (try_parse_arity): Add cases for instructions used
in VM builtins.
(scm_primitive_call_ip): Return #f if call-ip not found.
* libguile/vm-engine.c (handle-interrupts): Get code from intrinsics.
* libguile/vm.c
* libguile/vm.c (instrumented_code, define_vm_builtins): Add
instrumentation to the builtins, so that they can be JIT-compiled.
(INIT_BUILTIN): Remove min-arity setting; the fallback min-arity
interpreter should figure it out.
(scm_bootstrap_vm): Call the new define_vm_builtins function.
* libguile/gsubr.c (primitive_call_ip): Return 0 if call IP not found.
(primitive_subr_idx): Interpret call ip == 0 as not-a-subr.
* module/system/vm/program.scm (program-arguments-alist): Allow a #f
call-ip.
* libguile/intrinsics.h:
* libguile/intrinsics.c (atomic_ref_scm, atomic_set_scm):
(atomic_swap_scm, atomic_compare_and_swap_scm): New intrinsics, given
that lightning doesn't know atomics.
(scm_bootstrap_intrinsics): Init new intrinsics.
* libguile/vm-engine.c (atomic-scm-ref/immediate)
(atomic-scm-set!/immediate, atomic-scm-swap!/immediate)
(atomic-scm-compare-and-swap!/immediate): Use intrinsics, to be like
the JIT.
* libguile/intrinsics.h (INDIRECT_INT64_INTRINSICS): New definition. If
true, int64 args and return values are passed by reference. Here to
make JIT easier.
* libguile/intrinsics.c (indirect_scm_to_int64, indirect_scm_to_uint64):
(indirect_scm_to_uint64_truncate, indirect_scm_from_int64):
(indirect_scm_from_uint64, indirect_lsh, indirect_rsh): New indirect
variants.
(scm_bootstrap_intrinsics): Use indirect variants as appropriate.
* libguile/vm-engine.c: Update to call indirect intrinsics if
appropriate.
* libguile/intrinsics.h:
* libguile/intrinsics.c (string_set_x): Change to take size_t and u32 as
args.
(allocate_words): Change to take size_t as arg.
* libguile/vm.c (expand_apply_argument): Rename from rest_arg_length,
and also handle the stack manipulation.
* libguile/vm-engine.c (expand-apply-argument): Update for intrinsic
change.
(call-scm-sz-u32): Rename from call-scm-u64-u64, as it matches its
uses and will compile better on 32-bit systems.
* module/system/vm/assembler.scm (define-scm-sz-u32-intrinsic):
(string-set!): Update for new instrinsic call inst.
* libguile/jit.c (compile_call_scm_sz_u32): Adapt.
* libguile/intrinsics.h (SCM_FOR_ALL_VM_INTRINSICS):
* libguile/intrinsics.c (error_wrong_num_args): Take the thread as an
arg, instead of the ostensible callee.
* libguile/vm-engine.c: Update callers of wrong-num-args intrinsic to
pass a thread instead.
* libguile/intrinsics.h (SCM_FOR_ALL_VM_INTRINSICS): Update prototype of
capture-continuation.
* libguile/jit.h:
* libguile/jit.c (scm_jit_enter_mcode): Return void, not the vra.
Instead, we expect the code to set vp->ip for the vra.
* libguile/vm-engine.c (instrument-entry, instrument-loop)
(return-values, abort): Adapt scm_jit_enter_mcode calling convention.
(capture-continuation): No need to pass an mra; the intrinsic will
read it from the stack.
* libguile/vm.c (capture_continuation): Remove mra arg, as we take mra
from the continuation.
(scm_call_n): Adapt to scm_jit_enter_mcode change.
* libguile/continuations.c (scm_i_continuation_to_frame): Adapt to vra
field renaming.
(scm_i_reinstate_continuation, grow_stack, copy_stack_and_call)
(scm_dynthrow): Take mra of continuation. Set on the vp before the
longjmp.
* libguile/continuations.h: Update scm_i_reinstate_continuation
prototype.
* libguile/dynstack.h:
* libguile/control.c (scm_suspendable_continuation_p):
* libguile/dynstack.c (PROMPT_WORDS, PROMPT_VRA, PROMPT_MRA):
(PROMPT_JMPBUF, scm_dynstack_push_prompt, scm_dynstack_find_prompt)
(scm_dynstack_wind_prompt): Store both virtual and machine return
addresses on the dynstack, for prompts.
* libguile/eval.c (eval): Pass NULL for mra.
* libguile/intrinsics.c (push_prompt): Add mra arg, and pass it to the
dynstack.
* libguile/intrinsics.h: Update prototypes so that continuation-related
intrinsics can save and restore the MRA.
* libguile/jit.h:
* libguile/jit.c: Return VRA when JIT code needs to tier down.
* libguile/stacks.c (find_prompt, scm_make_stack)
* libguile/throw.c (catch): Adapt find-prompt calls.
* libguile/vm-engine.c (instrument-entry, instrument-loop): Add logic to
continue with vcode after the mcode finishes.
(compose-continuation, capture-continuation, abort, prompt): Add logic
to pass NULL as captured MRA, but continue with mcode from new
continuations, if appropriate.
* libguile/vm.c (scm_i_vm_cont_to_frame, capture_stack)
(scm_i_capture_current_stack, reinstate_continuation_x)
(capture_continuation, compose_continuation_inner, compose_continuation)
(capture_delimited_continuation, abort_to_prompt): Adapt to plumb
around machine code continuations.
(scm_call_n): Check "mra_after_abort" field for machine code
continuation, if any.
* libguile/vm.h (struct scm_vm): Add "mra_after_abort" field.
(struct scm_vm_cont): Rename "ra" field to "vra" and add "mra" field.
* libguile/foreign.c (scm_i_foreign_call): Rename back from
foreign_call. Need a new trampoline that's easier to call from JIT,
until we actually rewrite the FFI in terms of the JIT.
(scm_register_foreign): Remove foreign_call intrinsic init.
* libguile/intrinsics.h (SCM_FOR_ALL_VM_INTRINSICS): Foreign-call
intrinsic sets return directly on stack.
* libguile/vm-engine.c (foreign-call): Adapt to new intrinsic behavior.
* libguile/vm.c (foreign_call, scm_bootstrap_vm): Add new intrinsic
wrapper.
* libguile/intrinsics.h (SCM_FOR_ALL_VM_INTRINSICS): Make intrinsics for
the VM hooks.
* libguile/vm-engine.c (RUN_HOOK): Run hooks through the intrinsics
table.
* libguile/vm.c (invoke_apply_hook, invoke_return_hook):
(invoke_next_hook, invoke_abort_hook): Rename, remove NOINLINE
attribute (as we call them through the intrinsics table).
(scm_bootstrap_vm): Init new intrinsics.
* libguile/intrinsics.h (SCM_FOR_ALL_VM_INTRINSICS): Add
unpack-values-object.
* libguile/vm-engine.c (subr-call): If the object is a values object,
call out to unpack-values-object. This is to avoid reifying
allocate-frame code in each jitted subr.
* libguile/vm.c (unpack_values_object, scm_bootstrap_vm): Define new
intrinsic.
* libguile/intrinsics.h:
* libguile/vm.c (get_callee_vcode): Rename from apply_non_program, and
instead return the IP for the callee of a frame.
(scm_call_n, scm_bootstrap_vm): Adapt to get_callee_vcode change.
* libguile/vm-engine.c (call, tail-call, call/cc): Use
get_callee_vcode unconditionally. JIT will do this to avoid so much
code generation for calls.
* libguile/frames.c (scm_frame_return_address): Use
SCM_FRAME_VIRTUAL_RETURN_ADDRESS.
(scm_c_frame_previous): Likewise.
* libguile/frames.h: Update diagram for new names.
(union scm_vm_stack_element): Rename "as_ip" to "as_vcode", and
add "as_mcode" for machine code pointers.
(SCM_FRAME_VIRTUAL_RETURN_ADDRESS)
(SCM_FRAME_SET_VIRTUAL_RETURN_ADDRESS): Rename to these, from
SCM_FRAME_RETURN_ADDRESS and SCM_FRAME_SET_RETURN_ADDRESS.
* libguile/vm-engine.c (halt, call, call-label, return-values)
(return-from-interrupt): Adapt to renamings. Make "halt" have frame
size as a parameter.
* libguile/vm.c (scm_i_vm_mark_stack): Adapt to renaming.
(push_interrupt_frame): Take mRA as additional argument. In future we
will set it as frame mRA.
(capture_continuation): Adapt to renaming.
(scm_call_n): Adapt to renaming and make frame size adjustable.
(push_interrupt_frame, reinstate_continuation_x): Make frame size
adjustable.
* module/language/cps/slot-allocation.scm (allocate-slots): Make frame
size adjustable.
* libguile/intrinsics.h (scm_t_thread_mra_intrinsic): New type; use for
push_interrupt_frame.
(scm_t_thread_u8_scm_sp_vra_intrinsic): Rename from the same but was
"ra" instead of "vra", and change type to uint32_t*.
* module/system/vm/disassembler.scm (define-clobber-parser):
Parameterize clobber set for calls by frame size.
* libguile/continuations.c (scm_i_make_continuation): Remove registers
argument; instead get from thread.
* libguile/vm-engine.c (vm_engine): Adapt VM engine to not receive a
registers argument, and thus to not pass it to intrinsics either.
* libguile/intrinsics.h:
* libguile/intrinsics.c (push_prompt):
* libguile/vm.c (capture_continuation, compose_continuation)
(abort_to_prompt): Refactor these intrinsics to not take a registers
argument; it's not necessary.
(scm_call_n): Don't pass registers argument.
* libguile/fluids.c (scm_i_fluid_ref): New internal function.
(scm_fluid_ref): Use scm_i_fluid_ref.
* libguile/intrinsics.h:
* libguile/intrinsics.c (current_module): New intrinsic.
* libguile/modules.c (scm_i_current_module): New internal function.
(scm_current_module): Use new internal function.
* module/language/cps/reify-primitives.scm (compute-known-primitives):
Add current-module as an intrinsic primitive.
* module/system/vm/assembler.scm (define-scm<-thread-intrinsic):
(current-module): Arrange to compile to intrinsic call.
* libguile/intrinsics.c (error_wrong_num_args, error_no_values)
(error_not_enough_values, error_wrong_number_of_values): New
intrinsics.
* libguile/intrinsics.h: Add new intrinsics.
* libguile/vm-engine.c: Signal errors using the new intrinsics.
* libguile/vm.c (vm_error): Remove, now that it's unused.
(vm_error_bad_instruction): Abort instead of throwing an exception.
If we get a bad instruction, nothing good will ever happen!
(compose_continuation): Use wrong-type-arg for unrewindable
continuations.
(scm_bootstrap_vm): No need to make "vm-run" or "vm-error" symbols.
* libguile/intrinsics.h (SCM_FOR_ALL_VM_INTRINSICS): Add intrinsics for
throw, throw/value, and throw/value+data.
* libguile/intrinsics.c (throw_, throw_with_value):
(throw_with_value_and_data): And here they are.
* libguile/vm-engine.c (throw, throw/value, throw/value+data): Use
intrinsics.
* libguile/vm.c: Remove vm_throw et al.
* libguile/control.h:
* libguile/control.c (scm_i_make_composable_continuation): Rename from
make_partial_continuation and expose internally.
(scm_abort_to_prompt_star): Adapt to scm_i_vm_abort name change.
* libguile/intrinsics.h (SCM_FOR_ALL_VM_INTRINSICS): Define
abort_to_prompt intrinsic.
* libguile/throw.c (abort_to_prompt): Adapt to scm_i_vm_abort name
change.
* libguile/vm-engine.c (abort): Use abort_to_prompt intrinsic.
* libguile/vm.c (capture_delimited_continuation): Move here from
control.c where it was named reify_partial_continuation.
(scm_i_vm_abort): Move from control.c where it was named
scm_c_abort (and only exposed internally).
(abort_to_prompt): New intrinsic, replacing vm_abort.
* libguile/vm.h: Add setjmp include and scm_i_vm_abort decl.
* libguile/intrinsics.h:
* libguile/vm.c (rest_arg_length): New intrinsic.
(vm_error_apply_to_non_list): Remove now-unused error proc.
* libguile/vm-engine.c (tail-apply): Use new intrinsic.
* libguile/intrinsics.h (SCM_FOR_ALL_VM_INTRINSICS): Add
compose-continuation intrinsic.
* libguile/vm-engine.c (compose-continuation): Call compose-continuation
intrinsic.
* libguile/vm.c (compose_continuation_inner, compose_continuation): Move
down and rename from vm_reinstate_partial_continuation, and make into
a form that works as an intrinsic.
* libguile/continuations.h (scm_t_contregs): Remove "struct vm*" member;
unneeded.
* libguile/continuations.c (scm_i_make_continuation): No need to store
continuation->vp.
(scm_i_contregs): New internal function, replaces scm_i_contregs_vp
and scm_i_contregs_vm_cont.
(scm_i_check_continuation): Remove; moved to vm.c.
(scm_i_reinstate_continuation): Add an abort(), to satisfy
SCM_NORETURN.
* libguile/intrinsics.h: Add new "reinstate-continuation!" intrinsic.
* libguile/vm-engine.c (continuation-call): Use new
reinstate-continuation! intrinsic.
* libguile/vm.c (vm_return_to_continuation_inner): Move later in the
file.
(reinstate_continuation_x): New intrinsic.
(scm_bootstrap_vm): Init new intrinsic.
* libguile/Makefile.am (noinst_HEADERS, modinclude_HEADERS): Change to
not install intrinsics.h.
* libguile/intrinsics.h: Add an error if BUILDING_LIBGUILE isn't set, to
catch any stray bad inclusions. Add intrinsic for foreign-call.
* libguile/foreign.c (foreign_call): Rename from scm_i_foreign_call, and
set as the foreign-call intrinsic.
* libguile/vm-engine.c (foreign-call): Use the intrinsic. In the future
we'll want to totally revamp the FFI, if we know that a JIT is
available!
* libguile/intrinsics.h (SCM_FOR_ALL_VM_INTRINSICS): Add
push-interrupt-frame.
* libguile/vm.c (push_interrupt_frame): New intrinsic. Goal is to
reduce the amount of inline code the JIT will generate for handling
interrupts.
* libguile/vm-engine.c (handle-interrupts): Call out to the
push_interrupt_frame intrinsic in the slow case.
* libguile/intrinsics.h (scm_t_thread_sp_intrinsic): Change to take
thread instead of vp.
(SCM_FOR_ALL_VM_INTRINSICS): Change expand_stack to expect thread, not
vp.
* libguile/vm-engine.c (ALLOC_FRAME): Call expand_stack with thread.
* libguile/vm.c (thread_expand_stack, scm_bootstrap_vm): Adapt.