1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-04-30 20:00:19 +02:00
Commit graph

94 commits

Author SHA1 Message Date
Andy Wingo
7c0bfcb097 Minor 32-bit untag-fixnum optimization
* libguile/jit.c (compile_untag_fixnum): Minor optimization in 32-bit
  case.
2018-09-01 10:29:05 +02:00
Andy Wingo
dafa648915 Fix compilation of compile_eq
* libguile/jit.c (compile_eq): Compare to register, not immediate.
2018-09-01 10:11:17 +02:00
Andy Wingo
79be7028e4 More JIT debugging
* libguile/jit.c (compile1): Add debug for when instructions are first
  compiled.  Will be removed when all is working.
  (compute_mcode): Add debugging about what code is compiled.
  (scm_sys_jit_compile): Remove per-instruction output.
  (scm_jit_compute_mcode): Actually compile JIT code.  Use
  GUILE_JIT_COUNTER_THRESHOLD to control when JIT happens.
2018-08-31 15:50:46 +02:00
Andy Wingo
cc997293e2 JIT threshold controlled by environment variable
* libguile/jit.c (scm_jit_counter_threshold): Make a static variable
  instead of a compile-time constant.
  (scm_init_jit): Init scm_jit_counter_threshold from
  GUILE_JIT_COUNTER_THRESHOLD environment variable.  Default is -1
  indicating "never JIT".
* libguile/vm-engine.c (instrument-entry, instrument-loop): Adapt to new
  variable.
2018-08-31 11:28:38 +02:00
Andy Wingo
def671974c Minor optimization in compile_alloc_frame
* libguile/jit.c (compile_alloc_frame): Remove useless FP reload.
2018-08-31 10:54:34 +02:00
Andy Wingo
dac43443a3 Fix bind-kwargs JIT compilation
* libguile/jit.c (COMPILE_X8_C24__C8_C24__X8_C24__N32): Fix unpacking of
  N32 arg.
2018-08-29 22:29:39 +02:00
Andy Wingo
6da132cb95 Fix JIT compilation of composable continuations
* libguile/control.c (compose_continuation_code): Fix offset of code
  end.
* libguile/jit.c (compile_compose_continuation): Fix test for mcode not
  null.
2018-08-29 22:15:20 +02:00
Andy Wingo
15314fdc07 Fix JIT compilation of shuffle-down
* libguile/jit.c (compile_shuffle_down): Fix compilation.
2018-08-29 20:29:57 +02:00
Andy Wingo
c02c89d533 Fix JIT compilation of call-with-prompt
* libguile/jit.c (compile_prompt): Actually push the MRA arg.
  (analyze): Mark call continuations as entries, as both FP and SP are
  set then, and also mark prompt handlers as entries (and blocks).
2018-08-29 20:00:03 +02:00
Andy Wingo
66fb76db2b Fix miscompilation for "abort" opcode
* libguile/jit.c (compile_abort): Fix miscompilation.
2018-08-29 19:41:47 +02:00
Andy Wingo
24d09b16b6 Maybe enter JIT when returning from interpreted functions
* libguile/jit.c (scm_jit_compute_mcode): Minor optimization.
* libguile/vm-engine.c (return-values): Maybe return to JIT code.
2018-08-29 17:54:19 +02:00
Andy Wingo
c03e2bbbb4 JIT tracks register clobbers
* libguile/jit.c (struct scm_jit_state): Add beginnings of a little
  local register allocator.
  (reset_register_state): New helper.
  (clear_scratch_register_state): Use new helper.
  (record_gpr_clobber, record_fpr_clobber): New helpers, used when there
  may be cached variables in registers, called when registers are
  written.
  (set_sp_cache_gpr, set_sp_cache_fpr): New helpers, called when results
  are written to the stack.
  (emit_retval, emit_movi, emit_ldxi, DEFINE_CLOBBER_RECORDING_EMITTER_R)
  (DEFINE_CLOBBER_RECORDING_EMITTER_P, DEFINE_CLOBBER_RECORDING_EMITTER_R_I)
  (DEFINE_CLOBBER_RECORDING_EMITTER_R_R): New wrappers for Lightning API
  that also records register clobbers.  Update callers.
  (save_reloadable_register_state): New helper.
  (restore_reloadable_register_state): Rename from
  ensure_register_state.
2018-08-29 14:01:20 +02:00
Andy Wingo
10bfd55ec3 JIT: Store FP in register during procedure prolog/epilog
* libguile/jit.c (scm_jit_state): Add op_attrs array, for a pre-pass,
  and store state of what's in registers.
  (SP, FP): Reassign to scratch registers, as in general these need to
  be reloaded anyway after callouts.
  (die, DIE, ASSERT, UNREACHABLE): Add better invariant-testing.
  (clear_register_state, clear_scratch_register_state)
  (set_register_state, has_register_state, ASSERT_HAS_REGISTER_STATE):
  Add machinery to track state of SP and FP.  Can eventually track
  scratch register assignments as well.  Adapt code to use these.
  (compile_atomic_ref_scm_immediate): Compile to a vanilla load on x86.
  (compile_handle_interrupts): Analogous atomic-ref changes here.
  (analyze): New helper, a simple once-through pre-pass to identify
  branch targets.
  (compile): Only generate labels for branch targets.  Reset register
  state at branch targets.
  (compute_mcode): Initialize j->op_attrs appropriately.
2018-08-28 16:03:21 +02:00
Andy Wingo
4fb99e9454 Bug-fix for alloc-frame and stack moving
* libguile/jit.c (emit_push_frame): Simplification; we never need to
  store old_fp and new_fp at once.
  (compile_alloc_frame): Fix to not keep a pointer into the stack across
  a stack expansion.
2018-08-26 15:13:01 +02:00
Andy Wingo
98b4c46a36 Minor JIT refactor
* libguile/jit.c (emit_alloc_frame_for_sp): Remove unused "fp" arg.
  Adapt callers.
2018-08-26 10:25:52 +02:00
Andy Wingo
18dfe48fc4 Fuse comparisons and branches in JIT
* libguile/jit.c (emit_load_compare_result)
  (emit_store_compare_result): Remove these.
  (emit_branch_if_frame_locals_count_not_eq): New helper.
  (fuse_conditional_branch): New helper.
* libguile/jit.c (compile_u64_numerically_equal)
  (compile_u64_less, compile_s64_less, compile_f64_numerically_equal)
  (compile_f64_less, compile_numerically_equal, compile_less)
  (compile_check_arguments, compile_check_positional_arguments):
  (compile_immediate_tag_equals, compile_heap_tag_equals)
  (compile_eq, compile_heap_numbers_equal)
  (compile_s64_imm_numerically_equal, compile_u64_imm_less)
  (compile_imm_u64_less, compile_s64_imm_less, compile_imm_s64_less):
  Fuse conditional branches, to avoid going through compare-result.
  (compile_jl, compile_je, compile_jnl, compile_jne, compile_jge)
  (compile_jnge): Abort, since they shouldn't be reachable.
2018-08-25 16:20:49 +02:00
Andy Wingo
dfc0b902dc JIT refactor
* libguile/jit.c (struct scm_jit_state): Store next ip, so that
  compilers can fuse opcodes.
  (op_lengths): New static variable.
  (emit_direct_tail_call): Add a fast case for self-recursion.
  (compile1): Move IP advancement out of the specific arity compilers;
  instead precompute a "next_ip", that can be incremented.
2018-08-25 14:36:58 +02:00
Andy Wingo
9574245676 Fix again the unknown-filling of alloc-frame
* libguile/jit.c (compile_alloc_frame): Yet another fix, because I am an
  idiot.
2018-08-24 16:19:51 +02:00
Andy Wingo
d0c9d20626 Fix JIT compilation of bind-rest
* libguile/jit.c (compile_bind_rest): Fix.
2018-08-24 14:59:47 +02:00
Andy Wingo
3920b99125 Fix fp-ref, fp-set! helpers in jit for signedness
* libguile/jit.c (emit_fp_ref_scm, emit_fp_set_scm): Fix signedless of
  offsets.
2018-08-24 12:58:54 +02:00
Andy Wingo
02a9e76b57 Fix bug in compile-alloc-frame
* libguile/jit.c (compile_alloc_frame): Fix alloc-frame filling in of
  undefined values for when previous frame size was unknown.
2018-08-24 12:14:29 +02:00
Andy Wingo
5603079995 Clear frame size after subr-call, return-values
* libguile/jit.c (compile_return_values, compile_subr_call): Clear frame
  size.
2018-08-24 11:43:50 +02:00
Andy Wingo
25e9b0f79d 32-bit fix for emit_run_hook
* libguile/jit.c (emit_run_hook): Use sign-extending load, as unsigned
  load doesn't exist on 32-bit targets.
2018-08-23 19:53:17 +02:00
Andy Wingo
7854460fac Minor refactors to jit.c
* libguile/jit.c (emit_direct_tail_call): Add FIXME.
  (emit_mov): Simplify implementation.
  (emit_branch_if_frame_locals_count_less_than):
  (emit_branch_if_frame_locals_count_eq):
  (emit_branch_if_frame_locals_count_greater_than):
  (emit_load_fp_slot):
  (emit_branch_if_immediate):
  (emit_load_heap_object_word):
  (emit_load_heap_object_tc):
  (emit_branch_if_heap_object_has_tc):
  (emit_branch_if_heap_object_not_tc):
  (emit_branch_if_heap_object_not_tc7):
  (emit_entry_trampoline):
  (emit_handle_interrupts_trampoline):
  (initialize_handle_interrupts_trampoline):
  (emit_free_variable_ref): Move later in the file.
2018-08-23 19:45:36 +02:00
Andy Wingo
bf035d9385 Fix load width of get-ip-relative-addr
* libguile/jit.c (emit_get_ip_relative_addr): Fix load width.
2018-08-23 17:19:15 +02:00
Andy Wingo
fd1deab3c3 Optimizations to subr-call
* libguile/jit.c (compile_subr_call): Optimizations.
2018-08-23 10:27:27 +02:00
Andy Wingo
01a79bed89 Comments in the JIT
* libguile/jit.c: Add some overview comments.
2018-08-23 10:24:30 +02:00
Andy Wingo
77695612f4 Add support for labels, and fix a bug in uadd/imm and usub/imm.
* libguile/jit.c (add_inter_instruction_patch, compile, compute_mcode):
  Add support for labels.
  (compile_uadd_immediate, compile_usub_immediate): Fix cases where we
  were adding the wrong operand as an immediate.
2018-08-20 15:35:47 +02:00
Andy Wingo
d7fcdd9a2e Add out-of-line handle-interrupts trampoline stub
* libguile/jit.c (emit_handle_interrupts_trampoline)
  (initialize_handle_interrupts_trampoline)
  (compile_handle_interrupts): Handle most of the slow case of
  handle-interrupts out-of-line, to avoid code bloat.
2018-08-20 14:57:00 +02:00
Andy Wingo
9c76a1ad42 Fix frame popping in JIT
* libguile/jit.c (emit_entry_trampoline): Don't bother hackily trying to
  save registers; the "jit_frame" call handles that.
  (compile_return_values, compile_return_from_interrupt): Fix bug when
  computing previous FP: no need to add frame_overhead_slots.
  (emit_load_prev_fp_offset, emit_store_prev_fp_offset): Rename from
  emit_load_prev_frame_size, emit_store_prev_frame_size.
  (emit_push_frame): Adapt to emit_store_prev_frame_size.  Don't
  subtract off the frame_overhead_slots.
  (scm_jit_enter_mcode): Comment out a printf for the time being.
2018-08-20 12:45:00 +02:00
Andy Wingo
d00150303d JIT compilation tweaks
* libguile/jit.c (emit_alloc_frame_for_sp, compile_current_thread): Fix
  some ldxr/ldxi stxr/stxi confusions.
  (compile_alloc_frame): Omit if the frame size is already correct.
  (compile, compute_mcode, scm_sys_jit_compile, scm_jit_enter_mcode):
  Add a bit more debugging.
2018-08-20 11:43:46 +02:00
Andy Wingo
dca1e9d7bd Manual JIT interface via %jit-compile
* libguile/init.c (scm_i_init_guile): Call scm_init_jit ().
* libguile/jit.c (enter_mcode, exit_mcode): New static members; code
  pointers for the JIT trampoline.
  (emit_exit): New helper.  The Lightning tramp/frame mechanism that we
  use needs to exit via a jmp instead of a return.  Adapt callers of
  jit_ret.
  (emit_entry_trampoline): Use the "frame" mechanism to enter the JIT.
  (compile1): Add missing "break" after case statements.  Oops!
  (compile): Add prolog and "tramp" to compiled functions.
  (initialize_jit): New local routine to init the JIT on demand.
  (compute_mcode): New helper, to compile a function.
  (scm_sys_jit_compile): New function, exported to Scheme as
  %jit-compile.
  (scm_jit_compute_mcode): Return the existing mcode if the function is
  at the start.
  (scm_jit_enter_mcode): Call the enter_mcode trampoline.
* libguile/jit.h (struct scm_jit_state): Declare, so we can make
  pointers to it.
* libguile/threads.h (struct scm_thread): Add jit_state member.
* libguile/threads.c (on_thread_exit): Free the jit state.
2018-08-20 08:56:35 +02:00
Andy Wingo
698bff8748 First implementation of a template JIT
* libguile/jit.c: Implement most of a JIT.  Untested and still needs to
  be wired up.
2018-08-19 17:39:16 +02:00
Andy Wingo
d4abe8bbed Avoid needless 64-bit args on 32-bit machines for some intrinsics
* 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.
2018-08-13 14:30:01 +02:00
Andy Wingo
5df43b60a9 Adapt JIT calling convention; continuations take mra from stack
* 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.
2018-08-13 10:32:13 +02:00
Andy Wingo
a20feea43e Continuations capture machine code address
* 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.
2018-08-12 15:57:53 +02:00
Andy Wingo
c3ff72cb81 Change call/cc inst to capture-continuation
* libguile/jit.c (compile_capture_continuation): Rename from call_cc now
  that the call is elsewhere.
* libguile/vm-engine.c (call, tail-call): Remove needless SYNC_IP before
  get-callee-vcode; the intrinsic can sync the ip if needed from the
  frame.
  (capture-continuation): Rename from call/cc, and leave the call itself
  to tail-call.
* libguile/vm.c (vm_builtin_call_with_current_continuation_code): Update
  to put the continuation in a local and then tail call.
  (get_callee_vcode): Sync vp->ip if we error.
2018-08-08 16:32:18 +02:00
Andy Wingo
b8a9a666f1 Rewrite subr implementation
* libguile/gsubr.c: Reimplement to store subr names and procedures in a
  side table, and to allocate fresh vcode for each subr.  This allows
  JIT of subrs, moves to a uniform all-code-starts-with-instrument-entry
  regime, and also allows statprof to distinguish between subrs based on
  IP.
* libguile/gsubr.h (SCM_SUBRF, SCM_SUBR_NAME): Call out to functions,
  now that these are in a side table.
  (scm_subr_function, scm_subr_name): New exports.
  (scm_i_primitive_name): New internal function, for looking up a
  primitive name based on IP.
  (scm_apply_subr): Take the subr index.
* libguile/vm-engine.c (subr-call):
* libguile/jit.c (compile_subr_call): Adapt to take index as arg.
* module/statprof.scm (sample-stack-procs, count-call):
  (stack-samples->procedure-data): Update to always record IP in stack
  samples and call counts.
* module/system/vm/frame.scm (frame-procedure-name): Simplify.
  (frame-instruction-pointer-or-primitive-procedure-name): Removed.
* libguile/programs.h:
* libguile/programs.c (scm_primitive_code_name): New function.
* module/system/vm/program.scm (primitive-code-name): New export.
2018-07-29 15:47:07 +02:00
Andy Wingo
a6b5049aa8 Emit instrument-loop in loops.
* am/bootstrap.am (SOURCES):
* module/Makefile.am (SOURCES): Handle renamve of handle-interrupts.scm
  to loop-instrumentation.scm.
* libguile/jit.h (SCM_JIT_COUNTER_ENTRY_INCREMENT): Rename from
  SCM_JIT_COUNTER_CALL_INCREMENT.
* libguile/vm-engine.c (instrument-entry): Rename from instrument-call.
* module/language/cps/compile-bytecode.scm (compile-function): Add
  handle-interrupts code before calls and returns.  Compile the
  "instrument-loop" primcall to an "instrument-loop" instruction and a
  "handle-interrupts" instruction.
  (lower-cps): Adapt to add-loop-instrumentation name change.
* module/language/cps/loop-instrumentation.scm: Rename from
  handle-interrupts.scm and just add "instrument-loop" primcalls in
  loops.  The compiler will add handle-interrupts primcalls as
  appropriate.
* module/system/vm/assembler.scm (<jit-data>): New data type, for
  emitting embedded JIT data.
  (<meta>): Add field for current JIT data.
  (make-meta): Initialize current JIT data.
  (emit-instrument-entry*, emit-instrument-loop*): New instruction
  emitters that reference the current JIT data.
  (end-program): Now that all labels are known, arrange to serialize the
  JIT data.
  (link-data): Reserve space for JIT data, and add relocs to initialize
  the "start" / "end" fields.
2018-07-29 15:47:07 +02:00
Andy Wingo
87da1c8d20 Add instrument-call, instrument-loop VM instructions
* libguile/jit.h (struct scm_jit_function_data)
  (enum scm_jit_counter_value): New data types.
* libguile/jit.c (scm_jit_compute_mcode, scm_jit_enter_mcode): New
  function stubs.  Adapt label/offset compilers to take pointers.
* libguile/vm-engine.c (instrument-call, instrument-loop): New
  instructions.
* libguile/vm.c: Add jit.h include.
* module/system/vm/assembler.scm (emit-instrument-call)
  (emit-instrument-loop): New exports.
2018-07-29 15:47:03 +02:00
Andy Wingo
c2a8224a63 Rework VM approach to shuffling unknown numbers of args
* libguile/vm-engine.c (shuffle-down, expand-apply-argument): New
  instructions.
  (tail-call, tail-call-label, return-values): Don't reset the frame.
  The compiler should reset the frame appropriately.
  (tail-call/shuffle, tail-apply): Remove unused instructions.
* libguile/vm.c (vm_builtin_apply_code): Use new shuffle-down and
  expand-apply-argument opcodes.
  (vm_builtin_call_with_values_code): Replace tail-call/shuffle with
  shuffle-down then tail-call.
* libguile/jit.c (compile_shuffle_down, compile_expand_apply_argument):
  Add compiler stubs
  (COMPILE_X8_F12_F12): New definition.
  (compile_tail_call_shuffle, compile_tail_apply): Remove unused
  compilers.
* module/language/cps/compile-bytecode.scm (compile-function): Emit
  reset-frame before tail calls and returns.
* module/system/vm/assembler.scm (system): Remove unbound "emit-return"
  export.
* module/system/vm/disassembler.scm (code-annotation)
  (instruction-has-fallthrough?, define-stack-effect-parser): Adapt for
  opcode changes.
2018-07-20 11:42:30 +02:00
Andy Wingo
80ba0e2cb1 Make JIT compiler skeleton more terse
* libguile/jit.c (scm_jit_state): Add "ip" member so we don't have to be
  passing it around all the time.  Rename use variables to "j" from
  "state".
2018-07-20 11:42:13 +02:00
Andy Wingo
5577392738 Begin structure for template JIT compiler
* libguile/jit.c: Begin to wire up compilers for the VM opcodes.
  Currently all that's there is a parser for each opcode's operands.
2018-07-03 13:31:29 +02:00
Andy Wingo
9338ef15c2 Wire up lightning into libguile build
* libguile/Makefile.am (AM_CPPFLAGS):
  (libguile_@GUILE_EFFECTIVE_VERSION@_la_SOURCES): If ENABLE_JIT, build
  lightning.
  (EXTRA_DIST): Add lightning files.
* libguile/lightning/lightning.am (lightning_extra_files): Add COPYING
  and related files to the dist.
* libguile/jit.c:
* libguile/jit.h: New files.
2018-07-02 11:08:57 +02:00