Hello all, Attached is the first version of Jitgen, a system for writing virtual machines and matching JIT compilers without so much duplicated code. It's pretty rough, but I wanted to see what you thought of this version and ask for comments.
The problem it's trying to solve is that if I made a JIT compiler the normal way, I would have to basically write the virtual machine over again. This is because each VM opcode would have a compiler method which would implement exactly the same algorithm as the already-existing C implementation, but with slightly different function calls. For example, here's the C implementation of scm_op_assert_nargs_ee_locals (with a few macros expanded): { scm_t_ptrdiff n; SCM *old_sp; /* nargs = n & 0x7, nlocs = nargs + (n >> 3) */ n = (*ip++); if (sp - (fp - 1) != (n & 0x7)) goto vm_error_wrong_num_args; old_sp = sp; sp += (n >> 3); while (old_sp < sp) *++old_sp = SCM_UNDEFINED; NEXT; } And here's the JIT implementation: { jit_value_t tmp1, tmp2, tmp3, val_scm_undefined; jit_label_t good_path = jit_label_undefined; int n_val, count; objcodep++; ip = jit_insn_add (function, ip, ipup); n_val = *objcodep; tmp1 = jit_insn_sub (function, fp, spup); tmp2 = jit_insn_sub (function, sp, tmp1); tmp3 = jit_insn_eq (function, tmp2, jit_value_create_nint_constant (function, jit_type_void_ptr, n_val&0x7)); jit_insn_branch_if (function, tmp3, &good_path); /** goto vm_error_wrong_num_args **/ /* restore the ip, sp and fp pointers, and return. */ jit_insn_store_relative (function, ipp, 0, ip); jit_insn_store_relative (function, spp, 0, sp); jit_insn_store_relative (function, fpp, 0, fp); jit_insn_return (function, jit_value_create_nint_constant (function, jit_type_int, jit_return_wrong_num_args)); jit_insn_label (function, &good_path); val_scm_undefined = jit_value_create_nint_constant (function, jit_type_void_ptr, (jit_nint)SCM_UNDEFINED); for (count = 0; count < (n_val >> 3); count++) { sp = jit_insn_add (function, sp, spup); jit_insn_store_relative (function, sp, 0, val_scm_undefined); } break; } The goal of Jitgen is to generate both of these from the following instructions: '((ip <- ip + ipup) (tmp1 <- fp - spup) (tmp2 <- sp - tmp1) (tmp3 <- tmp2 == (n_val & 0x7)) (branch-if tmp3 good_path) (store-relative ipp 0 ip) (store-relative spp 0 sp) (store-relative fpp 0 fp) (return jit_return_wrong_num_args) (label good_path) (sp <- sp + spup) (store-relative sp 0 SCM_UNDEFINED) ) (Actually these instructions will only generate part of that, but I did say it was rough. :-) ) The attached file jitgen.scm has two functions, instructions->c and instructions->libjit, which implement this. The rest of that file is supporting functions for those two. The file test.scm has a few tests for these, but they're pretty primitive. There's also a file called expand.scm, which is my idea for eventually using these. It's a Guile script that takes a file and copies it to an output file, except that in between occurrences of `%%` it expects to find Scheme code, and it evaluates the code and pastes the output into its output file. I'm thinking that we could use this to generate vm-i-system.c and vm-jit.c from templates, using a common set of definitions for the VM operations. (As a side note, something similar is already done for foreign.c and gsubr.c, but with Elisp to generate the code.) My biggest question is, is this something that you would be interested in having in Guile? If so, then also what do you think of the code style and interfaces, and do you have any other feedback? Thanks, Noah
jitgen.scm
Description: Binary data
expand.scm
Description: Binary data
test.scm
Description: Binary data