diff options
Diffstat (limited to 'src/runtime/c/pgf/jit.c')
| -rw-r--r-- | src/runtime/c/pgf/jit.c | 765 |
1 files changed, 524 insertions, 241 deletions
diff --git a/src/runtime/c/pgf/jit.c b/src/runtime/c/pgf/jit.c index 1a9e25e6f..4f6b8e8dc 100644 --- a/src/runtime/c/pgf/jit.c +++ b/src/runtime/c/pgf/jit.c @@ -1,12 +1,13 @@ #include <gu/seq.h> #include <gu/file.h> +#include <gu/utf8.h> #include <pgf/data.h> #include <pgf/reasoner.h> #include <pgf/evaluator.h> #include <pgf/reader.h> #include "lightning.h" -//#define PGF_JIT_DEBUG +#define PGF_JIT_DEBUG struct PgfJitState { @@ -15,6 +16,7 @@ struct PgfJitState { char *save_ip_ptr; GuBuf* call_patches; GuBuf* segment_patches; + size_t n_closures; }; #define _jit (rdr->jit_state->jit) @@ -33,18 +35,16 @@ typedef struct { // Between two calls to pgf_jit_make_space we are not allowed // to emit more that JIT_CODE_WINDOW bytes. This is not quite // safe but this is how GNU lightning is designed. -#define JIT_CODE_WINDOW 1280 +#define JIT_CODE_WINDOW 128 -typedef struct { - GuFinalizer fin; - void *page; -} PgfPageFinalizer; +#define JIT_VHEAP JIT_V0 +#define JIT_VSTATE JIT_V1 +#define JIT_VCLOS JIT_V2 static void pgf_jit_finalize_page(GuFinalizer* self) { - PgfPageFinalizer* fin = gu_container(self, PgfPageFinalizer, fin); - free(fin->page); + free(self); } static void @@ -64,43 +64,43 @@ pgf_jit_alloc_page(PgfReader* rdr) gu_fatal("Memory allocation failed"); } - PgfPageFinalizer* fin = - gu_new(PgfPageFinalizer, rdr->opool); - fin->fin.fn = pgf_jit_finalize_page; - fin->page = page; - gu_pool_finally(rdr->opool, &fin->fin); - + GuFinalizer* fin = page; + fin->fn = pgf_jit_finalize_page; + gu_pool_finally(rdr->opool, fin); + rdr->jit_state->buf = page; - jit_set_ip(rdr->jit_state->buf); + jit_set_ip(rdr->jit_state->buf+sizeof(GuFinalizer)); } PgfJitState* pgf_new_jit(PgfReader* rdr) { PgfJitState* state = gu_new(PgfJitState, rdr->tmp_pool); + memset(&state->jit, 0, sizeof(state->jit)); state->call_patches = gu_new_buf(PgfCallPatch, rdr->tmp_pool); state->segment_patches = gu_new_buf(PgfSegmentPatch, rdr->tmp_pool); state->buf = NULL; state->save_ip_ptr = NULL; + state->n_closures = 0; return state; } static void -pgf_jit_make_space(PgfReader* rdr) +pgf_jit_make_space(PgfReader* rdr, size_t space) { size_t page_size = getpagesize(); if (rdr->jit_state->buf == NULL) { pgf_jit_alloc_page(rdr); } else { - assert (rdr->jit_state->save_ip_ptr + JIT_CODE_WINDOW > jit_get_ip().ptr); + assert (jit_get_ip().ptr < rdr->jit_state->save_ip_ptr); - if (jit_get_ip().ptr + JIT_CODE_WINDOW > ((char*) rdr->jit_state->buf) + page_size) { + if (jit_get_ip().ptr + space > ((char*) rdr->jit_state->buf) + page_size) { jit_flush_code(rdr->jit_state->buf, jit_get_ip().ptr); pgf_jit_alloc_page(rdr); } } - rdr->jit_state->save_ip_ptr = jit_get_ip().ptr; + rdr->jit_state->save_ip_ptr = jit_get_ip().ptr + space; } static PgfAbsFun* @@ -137,7 +137,7 @@ pgf_jit_predicate(PgfReader* rdr, PgfAbstr* abstr, size_t n_funs = pgf_read_len(rdr); gu_return_on_exn(rdr->err, ); - pgf_jit_make_space(rdr); + pgf_jit_make_space(rdr, JIT_CODE_WINDOW); abscat->predicate = (PgfPredicate) jit_get_ip().ptr; @@ -183,7 +183,7 @@ pgf_jit_predicate(PgfReader* rdr, PgfAbstr* abstr, #endif for (size_t i = 0; i < n_funs; i++) { - pgf_jit_make_space(rdr); + pgf_jit_make_space(rdr, JIT_CODE_WINDOW); absfun = next_absfun; absfun->predicate = (PgfPredicate) jit_get_ip().ptr; @@ -254,7 +254,7 @@ pgf_jit_predicate(PgfReader* rdr, PgfAbstr* abstr, jit_ret(); if (i+1 < n_hypos) { - pgf_jit_make_space(rdr); + pgf_jit_make_space(rdr, JIT_CODE_WINDOW); jit_patch_movi(ref,jit_get_label()); @@ -318,28 +318,287 @@ pgf_jit_predicate(PgfReader* rdr, PgfAbstr* abstr, } static void -pgf_jit_compile_slide(PgfReader* rdr, int es_arg, size_t a, size_t b) +pgf_jit_finalize_defrules(GuFinalizer* self) { - if (a == b) { - jit_prepare(2); - jit_movi_i(JIT_V1, a); - jit_pusharg_p(JIT_V1); - jit_getarg_p(JIT_V1, es_arg); - jit_ldxi_p(JIT_V1, JIT_V1, offsetof(PgfEvalState,stack)); - jit_pusharg_p(JIT_V1); - jit_finish(gu_buf_trim_n); - } else { - jit_prepare(3); - jit_movi_i(JIT_V1, b); - jit_pusharg_p(JIT_V1); - jit_movi_i(JIT_V1, a); - jit_pusharg_p(JIT_V1); - jit_getarg_p(JIT_V1, es_arg); - jit_pusharg_p(JIT_V1); - jit_finish(pgf_evaluate_slide); - } + PgfEvalGates* gates = gu_container(self, PgfEvalGates, fin); + if (gates->defrules != NULL) + gu_seq_free(gates->defrules); } +PgfEvalGates* +pgf_jit_gates(PgfReader* rdr) +{ + PgfEvalGates* gates = gu_new(PgfEvalGates, rdr->opool); + jit_insn* next; + jit_insn* ref, *ref2; + + pgf_jit_make_space(rdr, JIT_CODE_WINDOW); + + gates->evaluate_indirection = jit_get_ip().ptr; + jit_ldxi_p(JIT_VCLOS, JIT_VCLOS, offsetof(PgfIndirection,val)); + jit_ldr_p(JIT_R0, JIT_VCLOS); + jit_jmpr(JIT_R0); + + pgf_jit_make_space(rdr, JIT_CODE_WINDOW); + + gates->evaluate_value = jit_get_ip().ptr; + jit_movr_p(JIT_VHEAP, JIT_VCLOS); + jit_ldxi_p(JIT_RET, JIT_VHEAP, offsetof(PgfValue, absfun)); + jit_bare_ret(0); + + pgf_jit_make_space(rdr, JIT_CODE_WINDOW); + + gates->evaluate_value_gen = jit_get_ip().ptr; + jit_subr_p(JIT_R0, JIT_FP, JIT_SP); + jit_subi_p(JIT_R0, JIT_R0, sizeof(void*)); + ref = jit_bnei_i(jit_forward(), JIT_R0, 0); + jit_movr_p(JIT_VHEAP, JIT_VCLOS); + jit_bare_ret(0); + jit_patch(ref); + jit_pushr_i(JIT_R0); + jit_prepare(2); + jit_addi_i(JIT_R0, JIT_R0, sizeof(PgfValueGen)); + jit_pusharg_ui(JIT_R0); + jit_ldxi_p(JIT_R0, JIT_VSTATE, offsetof(PgfEvalState,pool)); + jit_pusharg_p(JIT_R0); + jit_finish(gu_malloc); + jit_retval(JIT_VHEAP); + jit_popr_i(JIT_R0); + jit_movi_p(JIT_R1, gates->evaluate_value_gen); + jit_str_p(JIT_VHEAP, JIT_R1); + jit_ldxi_p(JIT_R1, JIT_VCLOS, offsetof(PgfValueGen,level)); + jit_stxi_p(offsetof(PgfValueGen,level), JIT_VHEAP, JIT_R1); + jit_ldxi_p(JIT_R1, JIT_VCLOS, offsetof(PgfValueGen,n_args)); + jit_addr_i(JIT_R1, JIT_R1, JIT_R0); + jit_stxi_p(offsetof(PgfValueGen,n_args), JIT_VHEAP, JIT_R1); + jit_movi_i(JIT_R1, offsetof(PgfValueGen,args)); + jit_ldxi_i(JIT_R2, JIT_VCLOS, offsetof(PgfValueGen,n_args)); + jit_addr_i(JIT_R2, JIT_R2, JIT_R1); + jit_pushr_i(JIT_R0); + next = jit_get_label(); + ref = jit_bger_i(jit_forward(), JIT_R1, JIT_R2); + jit_ldxr_i(JIT_R0, JIT_VCLOS, JIT_R1); + jit_stxr_p(JIT_R1, JIT_VHEAP, JIT_R0); + jit_addi_i(JIT_R1, JIT_R1, sizeof(void*)); + jit_jmpi(next); + jit_patch(ref); + jit_popr_i(JIT_R0); + jit_addr_i(JIT_R2, JIT_R2, JIT_R0); + jit_popr_p(JIT_VCLOS); + next = jit_get_label(); + ref = jit_bger_i(jit_forward(), JIT_R1, JIT_R2); + jit_popr_p(JIT_R0); + jit_stxr_p(JIT_R1, JIT_VHEAP, JIT_R0); + jit_addi_i(JIT_R1, JIT_R1, sizeof(void*)); + jit_jmpi(next); + jit_patch(ref); + jit_jmpr(JIT_VCLOS); + + pgf_jit_make_space(rdr, JIT_CODE_WINDOW); + + gates->evaluate_value_meta = jit_get_ip().ptr; + jit_subr_p(JIT_R0, JIT_FP, JIT_SP); + jit_subi_p(JIT_R0, JIT_R0, sizeof(void*)); + ref = jit_bnei_i(jit_forward(), JIT_R0, 0); + jit_movr_p(JIT_VHEAP, JIT_VCLOS); + jit_bare_ret(0); + jit_patch(ref); + jit_pushr_i(JIT_R0); + jit_prepare(2); + jit_addi_i(JIT_R0, JIT_R0, sizeof(PgfValueMeta)); + jit_pusharg_ui(JIT_R0); + jit_ldxi_p(JIT_R0, JIT_VSTATE, offsetof(PgfEvalState,pool)); + jit_pusharg_p(JIT_R0); + jit_finish(gu_malloc); + jit_retval(JIT_VHEAP); + jit_popr_i(JIT_R0); + jit_movi_p(JIT_R1, gates->evaluate_value_meta); + jit_str_p(JIT_VHEAP, JIT_R1); + jit_ldxi_p(JIT_R1, JIT_VCLOS, offsetof(PgfValueMeta,id)); + jit_stxi_p(offsetof(PgfValueMeta,id), JIT_VHEAP, JIT_R1); + jit_ldxi_p(JIT_R1, JIT_VCLOS, offsetof(PgfValueMeta,n_args)); + jit_addr_i(JIT_R1, JIT_R1, JIT_R0); + jit_stxi_p(offsetof(PgfValueMeta,n_args), JIT_VHEAP, JIT_R1); + jit_movi_i(JIT_R1, offsetof(PgfValueMeta,args)); + jit_ldxi_i(JIT_R2, JIT_VCLOS, offsetof(PgfValueMeta,n_args)); + jit_addr_i(JIT_R2, JIT_R2, JIT_R1); + jit_pushr_i(JIT_R0); + next = jit_get_label(); + ref = jit_bger_i(jit_forward(), JIT_R1, JIT_R2); + jit_ldxr_i(JIT_R0, JIT_VCLOS, JIT_R1); + jit_stxr_p(JIT_R1, JIT_VHEAP, JIT_R0); + jit_addi_i(JIT_R1, JIT_R1, sizeof(PgfClosure*)); + jit_jmpi(next); + jit_patch(ref); + jit_popr_i(JIT_R0); + jit_addr_i(JIT_R2, JIT_R2, JIT_R0); + jit_popr_p(JIT_VCLOS); + next = jit_get_label(); + ref = jit_bger_i(jit_forward(), JIT_R1, JIT_R2); + jit_popr_p(JIT_R0); + jit_stxr_p(JIT_R1, JIT_VHEAP, JIT_R0); + jit_addi_i(JIT_R1, JIT_R1, sizeof(PgfClosure*)); + jit_jmpi(next); + jit_patch(ref); + jit_jmpr(JIT_VCLOS); + + pgf_jit_make_space(rdr, JIT_CODE_WINDOW); + + gates->evaluate_expr_thunk = jit_get_ip().ptr; + jit_prepare(2); + jit_pusharg_p(JIT_VCLOS); + jit_pusharg_p(JIT_VSTATE); + jit_finish(pgf_evaluate_expr_thunk); + jit_retval(JIT_VCLOS); + jit_ldr_p(JIT_R0, JIT_VCLOS); + jit_jmpr(JIT_R0); + + pgf_jit_make_space(rdr, JIT_CODE_WINDOW); + + gates->evaluate_value_lit = jit_get_ip().ptr; + jit_movr_p(JIT_VHEAP, JIT_VCLOS); + jit_prepare(1); + jit_ldxi_p(JIT_R0, JIT_VHEAP, offsetof(PgfValueLit, lit)); + jit_pusharg_p(JIT_R0); + jit_finish(gu_variant_data); + jit_bare_ret(0); + + pgf_jit_make_space(rdr, JIT_CODE_WINDOW); + + gates->enter = (void*) jit_get_ip().ptr; + jit_prolog(2); + int es_arg = jit_arg_p(); + int closure_arg = jit_arg_p(); + jit_getarg_p(JIT_VSTATE, es_arg); + jit_getarg_p(JIT_VCLOS, closure_arg); + jit_ldr_p(JIT_R0, JIT_VCLOS); + jit_callr(JIT_R0); + jit_movr_p(JIT_RET, JIT_VHEAP); + jit_ret(); + + pgf_jit_make_space(rdr, JIT_CODE_WINDOW); + + gates->evaluate_value_pap = jit_get_ip().ptr; + jit_popr_p(JIT_VHEAP); + jit_addi_p(JIT_R1, JIT_VCLOS, offsetof(PgfValuePAP,args)); + jit_ldxi_p(JIT_R2, JIT_VCLOS, offsetof(PgfValuePAP,n_args)); + jit_addr_p(JIT_R2, JIT_R2, JIT_R1); + next = jit_get_label(); + ref = jit_bger_i(jit_forward(), JIT_R1, JIT_R2); + jit_ldr_p(JIT_R0, JIT_R1); + jit_pushr_p(JIT_R0); + jit_addi_p(JIT_R1, JIT_R1, sizeof(PgfClosure*)); + jit_jmpi(next); + jit_patch(ref); + jit_pushr_p(JIT_VHEAP); + jit_ldxi_p(JIT_VCLOS, JIT_VCLOS, offsetof(PgfValuePAP,fun)); + jit_ldr_p(JIT_R0, JIT_VCLOS); + jit_jmpr(JIT_R0); + + pgf_jit_make_space(rdr, JIT_CODE_WINDOW); + + gates->update_closure = jit_get_ip().ptr; + jit_popr_p(JIT_FP); + jit_popr_p(JIT_VCLOS); + jit_movi_p(JIT_R1, gates->evaluate_indirection); + jit_str_p(JIT_VCLOS, JIT_R1); + jit_stxi_p(offsetof(PgfIndirection, val), JIT_VCLOS, JIT_VHEAP); + jit_bare_ret(0); + + pgf_jit_make_space(rdr, JIT_CODE_WINDOW*2); + + gates->update_pap = jit_get_ip().ptr; + jit_subi_p(JIT_R0, JIT_R0, sizeof(void*)); + jit_pushr_i(JIT_R0); + jit_prepare(2); + jit_addi_i(JIT_R0, JIT_R0, sizeof(PgfValuePAP)); + jit_pusharg_ui(JIT_R0); + jit_ldxi_p(JIT_R0, JIT_VSTATE, offsetof(PgfEvalState,pool)); + jit_pusharg_p(JIT_R0); + jit_finish(gu_malloc); + jit_popr_i(JIT_R1); + jit_movi_p(JIT_R2, gates->evaluate_value_pap); + jit_str_p(JIT_RET, JIT_R2); + jit_stxi_p(offsetof(PgfValuePAP,fun), JIT_RET, JIT_VCLOS); + jit_stxi_p(offsetof(PgfValuePAP,n_args), JIT_RET, JIT_R1); + jit_ldr_p(JIT_R2, JIT_SP); + ref2 = jit_bnei_i(jit_forward(), JIT_R2, (int)gates->update_closure); + jit_ldxi_p(JIT_VHEAP, JIT_FP, sizeof(void*)); + jit_movi_p(JIT_R2, gates->evaluate_indirection); + jit_str_p(JIT_VHEAP, JIT_R2); + jit_stxi_p(offsetof(PgfIndirection, val), JIT_VHEAP, JIT_RET); + jit_ldr_p(JIT_R2, JIT_FP); + jit_pushr_p(JIT_R2); + jit_ldxi_p(JIT_R2, JIT_FP, 2*sizeof(void*)); + jit_pushr_p(JIT_R2); + next = jit_get_label(); + ref = jit_blei_i(jit_forward(), JIT_R1, 0); + jit_ldxi_p(JIT_R2, JIT_FP, -sizeof(void*)); + jit_stxi_p(2*sizeof(void*), JIT_FP, JIT_R2); + jit_stxi_p(offsetof(PgfValuePAP,args), JIT_RET, JIT_R2); + jit_addi_i(JIT_RET, JIT_RET, sizeof(void*)); + jit_subi_i(JIT_FP, JIT_FP, sizeof(void*)); + jit_subi_i(JIT_R1, JIT_R1, sizeof(void*)); + jit_jmpi(next); + jit_patch(ref); + jit_popr_p(JIT_R0); + jit_popr_p(JIT_FP); + jit_addi_p(JIT_SP, JIT_SP, 4*sizeof(void*)); + jit_pushr_p(JIT_R0); + jit_ldr_p(JIT_R0, JIT_VCLOS); + jit_jmpr(JIT_R0); + jit_patch(ref2); + jit_movr_p(JIT_VHEAP, JIT_RET); + jit_pushr_p(JIT_R1); + next = jit_get_label(); + ref = jit_blei_i(jit_forward(), JIT_R1, 0); + jit_ldxi_p(JIT_R2, JIT_FP, -sizeof(void*)); + jit_stxi_p(offsetof(PgfValuePAP,args), JIT_RET, JIT_R2); + jit_addi_i(JIT_RET, JIT_RET, sizeof(void*)); + jit_subi_i(JIT_FP, JIT_FP, sizeof(void*)); + jit_subi_i(JIT_R1, JIT_R1, sizeof(void*)); + jit_jmpi(next); + jit_patch(ref); + jit_popr_p(JIT_R1); + jit_popr_p(JIT_R0); + jit_addr_p(JIT_SP, JIT_SP, JIT_R1); + jit_jmpr(JIT_R0); + + pgf_jit_make_space(rdr, JIT_CODE_WINDOW); + + gates->evaluate_value_lambda = jit_get_ip().ptr; + jit_subr_p(JIT_R0, JIT_FP, JIT_SP); + jit_blti_i(gates->update_pap, JIT_R0, 2*sizeof(PgfClosure*)); + jit_prepare(2); + jit_movi_i(JIT_R0, sizeof(PgfEnv)); + jit_pusharg_ui(JIT_R0); + jit_ldxi_p(JIT_R0, JIT_VSTATE, offsetof(PgfEvalState,pool)); + jit_pusharg_p(JIT_R0); + jit_finish(gu_malloc); + jit_popr_p(JIT_R2); + jit_ldxi_p(JIT_R1, JIT_VCLOS, offsetof(PgfExprThunk,env)); + jit_stxi_p(offsetof(PgfEnv,next), JIT_RET, JIT_R1); + jit_popr_p(JIT_R1); + jit_stxi_p(offsetof(PgfEnv,closure), JIT_RET, JIT_R1); + jit_stxi_p(offsetof(PgfExprThunk,env), JIT_VCLOS, JIT_RET); + jit_pushr_p(JIT_R2); + jit_prepare(2); + jit_pusharg_p(JIT_VCLOS); + jit_pusharg_p(JIT_VSTATE); + jit_finish(pgf_evaluate_expr_thunk); + jit_retval(JIT_VCLOS); + jit_ldr_p(JIT_R0, JIT_VCLOS); + jit_jmpr(JIT_R0); + + gates->fin.fn = pgf_jit_finalize_defrules; + gates->defrules = NULL; + gu_pool_finally(rdr->opool, &gates->fin); + + return gates; +} + +#define PGF_DEFRULES_DELTA 20 + void pgf_jit_function(PgfReader* rdr, PgfAbstr* abstr, PgfAbsFun* absfun) @@ -353,34 +612,43 @@ pgf_jit_function(PgfReader* rdr, PgfAbstr* abstr, gu_puts(":\n", out, err); #endif - pgf_jit_make_space(rdr); - - absfun->function = jit_get_ip().ptr; + if (rdr->jit_state->n_closures % PGF_DEFRULES_DELTA == 0) { + abstr->eval_gates->defrules = + gu_realloc_seq(abstr->eval_gates->defrules, + PgfFunction, + rdr->jit_state->n_closures + PGF_DEFRULES_DELTA); + } + absfun->closure_id = ++rdr->jit_state->n_closures; size_t n_segments = pgf_read_len(rdr); gu_return_on_exn(rdr->err, ); gu_buf_flush(rdr->jit_state->segment_patches); - int es_arg = 0; - int closure_arg = 0; - for (size_t segment = 0; segment < n_segments; segment++) { size_t n_instrs = pgf_read_len(rdr); gu_return_on_exn(rdr->err, ); - + + pgf_jit_make_space(rdr, (JIT_CODE_WINDOW/4)*n_instrs); + + if (segment == 0) { + gu_seq_set(abstr->eval_gates->defrules, + PgfFunction, + absfun->closure_id-1, + jit_get_ip().ptr); + } + size_t curr_offset = 0; size_t n_patches = gu_buf_length(rdr->jit_state->segment_patches); - if (n_patches > 0) { + for (size_t i = 0; i < n_patches; i++) { PgfSegmentPatch* patch = - gu_buf_index(rdr->jit_state->segment_patches, PgfSegmentPatch, n_patches-1); + gu_buf_index(rdr->jit_state->segment_patches, PgfSegmentPatch, i); if (patch->segment == segment) { if (patch->is_abs) jit_patch_movi(patch->ref,jit_get_ip().ptr); else jit_patch(patch->ref); - gu_buf_trim_n(rdr->jit_state->segment_patches, 1); } } @@ -395,27 +663,27 @@ pgf_jit_function(PgfReader* rdr, PgfAbstr* abstr, #endif uint8_t tag = pgf_read_tag(rdr); - uint8_t opcode = tag >> 3; - uint8_t mod = tag & 0x07; + uint8_t opcode = tag >> 2; + uint8_t mod = tag & 0x03; switch (opcode) { - case PGF_INSTR_ENTER: { + case PGF_INSTR_CHECK_ARGS: { + int n = pgf_read_int(rdr); #ifdef PGF_JIT_DEBUG - gu_printf(out, err, "ENTER\n"); + gu_printf(out, err, "CHECK_ARGS %d\n", n); #endif - - jit_prolog(2); - es_arg = jit_arg_p(); - closure_arg = jit_arg_p(); + jit_subr_p(JIT_R0, JIT_FP, JIT_SP); + jit_blti_i(abstr->eval_gates->update_pap, JIT_R0, (n+1)*sizeof(PgfClosure*)); break; } case PGF_INSTR_CASE: { - PgfCId id = pgf_read_cid(rdr, rdr->opool); + PgfCId id = pgf_read_cid(rdr, rdr->tmp_pool); + int n = pgf_read_int(rdr); int target = pgf_read_int(rdr); #ifdef PGF_JIT_DEBUG - gu_printf(out, err, "CASE %s %03d\n", id, target); + gu_printf(out, err, "CASE %s %d %03d\n", id, n, target); #endif - jit_insn *jump= - jit_bnei_i(jit_forward(), JIT_V0, (int) jit_forward()); + jit_insn *jump = + jit_bnei_i(jit_forward(), JIT_RET, (int) jit_forward()); PgfSegmentPatch label_patch; label_patch.segment = target; @@ -428,42 +696,68 @@ pgf_jit_function(PgfReader* rdr, PgfAbstr* abstr, call_patch.ref = jump-6; gu_buf_push(rdr->jit_state->call_patches, PgfCallPatch, call_patch); - jit_prepare(2); - jit_pusharg_p(JIT_V1); - jit_getarg_p(JIT_V2, es_arg); - jit_pusharg_p(JIT_V2); - jit_finish(pgf_evaluate_save_variables); + for (int i = 0; i < n; i++) { + jit_ldxi_p(JIT_R0, JIT_VHEAP, sizeof(PgfValue)+sizeof(PgfClosure*)*i); + jit_pushr_p(JIT_R0); + } break; } case PGF_INSTR_CASE_LIT: { + int target; + jit_insn *jump; + switch (mod) { case 0: { - int n = pgf_read_int(rdr); - int target = pgf_read_int(rdr); + int n = pgf_read_int(rdr); + target = pgf_read_int(rdr); #ifdef PGF_JIT_DEBUG gu_printf(out, err, "CASE_LIT %d %03d\n", n, target); #endif + jit_ldxi_p(JIT_R1, JIT_RET, offsetof(PgfLiteralInt,val)); + jump = + jit_bnei_i(jit_forward(), JIT_R1, n); break; } case 1: { GuString s = pgf_read_string(rdr); - int target = pgf_read_int(rdr); + target = pgf_read_int(rdr); #ifdef PGF_JIT_DEBUG gu_printf(out, err, "CASE_LIT %s %03d\n", s, target); #endif + jit_pushr_p(JIT_RET); + jit_prepare(2); + jit_pusharg_p(JIT_RET); + jit_movi_p(JIT_R0, s); + jit_pusharg_p(JIT_R0); + jit_finish(strcmp); + jit_retval(JIT_R1); + jit_popr_p(JIT_RET); + jump = + jit_bnei_i(jit_forward(), JIT_R1, 0); break; } case 2: { double d = pgf_read_double(rdr); - int target = pgf_read_int(rdr); + target = pgf_read_int(rdr); #ifdef PGF_JIT_DEBUG gu_printf(out, err, "CASE_LIT %f %03d\n", d, target); #endif + jit_ldxi_d(JIT_FPR0, JIT_RET, offsetof(PgfLiteralFlt,val)); + jit_movi_d(JIT_FPR1, d); + jump = + jit_bner_d(jit_forward(), JIT_FPR0, JIT_FPR1); break; } default: gu_impossible(); } + + PgfSegmentPatch label_patch; + label_patch.segment = target; + label_patch.ref = jump; + label_patch.is_abs = false; + gu_buf_push(rdr->jit_state->segment_patches, PgfSegmentPatch, label_patch); + break; } case PGF_INSTR_ALLOC: { @@ -472,14 +766,13 @@ pgf_jit_function(PgfReader* rdr, PgfAbstr* abstr, gu_printf(out, err, "ALLOC %d\n", size); #endif jit_prepare(2); - jit_movi_ui(JIT_V0, size*sizeof(void*)); - jit_pusharg_ui(JIT_V0); - jit_getarg_p(JIT_V0, es_arg); - jit_ldxi_p(JIT_V0, JIT_V0, offsetof(PgfEvalState,pool)); - jit_pusharg_p(JIT_V0); + jit_movi_ui(JIT_R0, size*sizeof(void*)); + jit_pusharg_ui(JIT_R0); + jit_ldxi_p(JIT_R0, JIT_VSTATE, offsetof(PgfEvalState,pool)); + jit_pusharg_p(JIT_R0); jit_finish(gu_malloc); - jit_retval_p(JIT_V1); - + jit_retval_p(JIT_VHEAP); + curr_offset = 0; break; } @@ -489,30 +782,14 @@ pgf_jit_function(PgfReader* rdr, PgfAbstr* abstr, gu_printf(out, err, "PUT_CONSTR %s\n", id); #endif - jit_movi_p(JIT_V0, pgf_evaluate_value); - jit_stxi_p(curr_offset*sizeof(void*), JIT_V1, JIT_V0); - curr_offset++; - - PgfCallPatch patch; - patch.cid = id; - patch.ref = jit_movi_p(JIT_V0, jit_forward()); - jit_stxi_p(curr_offset*sizeof(void*), JIT_V1, JIT_V0); + jit_movi_p(JIT_R0, abstr->eval_gates->evaluate_value); + jit_stxi_p(curr_offset*sizeof(void*), JIT_VHEAP, JIT_R0); curr_offset++; - - gu_buf_push(rdr->jit_state->call_patches, PgfCallPatch, patch); - break; - } - case PGF_INSTR_PUT_FUN: { - PgfCId id = pgf_read_cid(rdr, rdr->tmp_pool); -#ifdef PGF_JIT_DEBUG - gu_printf(out, err, "PUT_FUN %s\n", id); -#endif PgfCallPatch patch; patch.cid = id; - patch.ref = jit_movi_p(JIT_V0, jit_forward()); - jit_ldxi_p(JIT_V0, JIT_V0, offsetof(PgfAbsFun,function)); - jit_stxi_p(curr_offset*sizeof(void*), JIT_V1, JIT_V0); + patch.ref = jit_movi_p(JIT_R0, jit_forward()); + jit_stxi_p(curr_offset*sizeof(void*), JIT_VHEAP, JIT_R0); curr_offset++; gu_buf_push(rdr->jit_state->call_patches, PgfCallPatch, patch); @@ -526,40 +803,72 @@ pgf_jit_function(PgfReader* rdr, PgfAbstr* abstr, PgfSegmentPatch patch; patch.segment = target; - patch.ref = jit_movi_p(JIT_V0, jit_forward()); + patch.ref = jit_movi_p(JIT_R0, jit_forward()); patch.is_abs = true; - jit_stxi_p(curr_offset*sizeof(void*), JIT_V1, JIT_V0); + jit_stxi_p(curr_offset*sizeof(void*), JIT_VHEAP, JIT_R0); curr_offset++; - + gu_buf_push(rdr->jit_state->segment_patches, PgfSegmentPatch, patch); break; } case PGF_INSTR_PUT_LIT: { + jit_movi_p(JIT_R0, abstr->eval_gates->evaluate_value_lit); + jit_stxi_p(curr_offset*sizeof(void*), JIT_VHEAP, JIT_R0); + curr_offset++; + + PgfLiteral lit; switch (mod) { case 0: { - size_t n = pgf_read_int(rdr); + PgfLiteralInt *lit_int = + gu_new_variant(PGF_LITERAL_INT, + PgfLiteralInt, + &lit, + rdr->opool); + lit_int->val = pgf_read_int(rdr); #ifdef PGF_JIT_DEBUG - gu_printf(out, err, "PUT_LIT %d\n", n); + gu_printf(out, err, "PUT_LIT %d\n", lit_int->val); #endif break; } case 1: { - GuString s = pgf_read_string(rdr); + GuLength len = pgf_read_len(rdr); + uint8_t* buf = alloca(len*6+1); + uint8_t* p = buf; + for (size_t i = 0; i < len; i++) { + gu_in_utf8_buf(&p, rdr->in, rdr->err); + } + *p++ = 0; + + PgfLiteralStr *lit_str = + gu_new_flex_variant(PGF_LITERAL_STR, + PgfLiteralStr, + val, p-buf, + &lit, rdr->opool); + strcpy((char*) lit_str->val, (char*) buf); #ifdef PGF_JIT_DEBUG - gu_printf(out, err, "PUT_LIT \"%s\"\n", s); + gu_printf(out, err, "PUT_LIT \"%s\"\n", lit_str->val); #endif break; } case 2: { - double d = pgf_read_double(rdr); + PgfLiteralFlt *lit_flt = + gu_new_variant(PGF_LITERAL_FLT, + PgfLiteralFlt, + &lit, + rdr->opool); + lit_flt->val = pgf_read_double(rdr); #ifdef PGF_JIT_DEBUG - gu_printf(out, err, "PUT_LIT %f\n", d); + gu_printf(out, err, "PUT_LIT %f\n", lit_flt->val); #endif break; } default: gu_impossible(); } + + jit_movi_p(JIT_R0, lit); + jit_stxi_p(curr_offset*sizeof(void*), JIT_VHEAP, JIT_R0); + curr_offset++; break; } case PGF_INSTR_SET: { @@ -569,7 +878,7 @@ pgf_jit_function(PgfReader* rdr, PgfAbstr* abstr, #ifdef PGF_JIT_DEBUG gu_printf(out, err, "SET hp(%d)\n", offset); #endif - jit_addi_p(JIT_V0, JIT_V1, offset*sizeof(void*)); + jit_addi_p(JIT_R0, JIT_VHEAP, offset*sizeof(void*)); break; } case 1: { @@ -577,13 +886,7 @@ pgf_jit_function(PgfReader* rdr, PgfAbstr* abstr, #ifdef PGF_JIT_DEBUG gu_printf(out, err, "SET stk(%d)\n", index); #endif - - jit_getarg_p(JIT_V0, es_arg); - jit_ldxi_p(JIT_V0, JIT_V0, offsetof(PgfEvalState,stack)); - jit_prepare(1); - jit_pusharg_p(JIT_V0); - jit_finish(gu_buf_last); - jit_ldxi_p(JIT_V0, JIT_RET, -index*sizeof(PgfClosure*)); + jit_ldxi_p(JIT_R0, JIT_SP, index*sizeof(PgfClosure*)); break; } case 2: { @@ -591,16 +894,14 @@ pgf_jit_function(PgfReader* rdr, PgfAbstr* abstr, #ifdef PGF_JIT_DEBUG gu_printf(out, err, "SET env(%d)\n", index); #endif - - jit_getarg_p(JIT_V0, closure_arg); - jit_ldxi_p(JIT_V0, JIT_V0, sizeof(PgfClosure)+index*sizeof(PgfClosure*)); + jit_ldxi_p(JIT_R0, JIT_VCLOS, sizeof(PgfClosure)+index*sizeof(PgfClosure*)); break; } default: gu_impossible(); } - jit_stxi_p(curr_offset*sizeof(void*), JIT_V1, JIT_V0); + jit_stxi_p(curr_offset*sizeof(void*), JIT_VHEAP, JIT_R0); curr_offset++; break; } @@ -608,18 +909,12 @@ pgf_jit_function(PgfReader* rdr, PgfAbstr* abstr, #ifdef PGF_JIT_DEBUG gu_printf(out, err, "SET_PAD\n"); #endif - jit_movi_p(JIT_V0, NULL); - jit_stxi_p(curr_offset*sizeof(void*), JIT_V1, JIT_V0); + jit_movi_p(JIT_R0, NULL); + jit_stxi_p(curr_offset*sizeof(void*), JIT_VHEAP, JIT_R0); curr_offset++; break; } case PGF_INSTR_PUSH: { - jit_getarg_p(JIT_V0, es_arg); - jit_ldxi_p(JIT_V0, JIT_V0, offsetof(PgfEvalState,stack)); - jit_prepare(1); - jit_pusharg_p(JIT_V0); - jit_finish(gu_buf_extend); - switch (mod) { case 0: { size_t offset = pgf_read_int(rdr); @@ -628,10 +923,10 @@ pgf_jit_function(PgfReader* rdr, PgfAbstr* abstr, #endif if (offset == 0) { - jit_str_p(JIT_RET, JIT_V1); + jit_pushr_p(JIT_VHEAP); } else { - jit_addi_p(JIT_V0, JIT_V1, offset*sizeof(void*)); - jit_str_p(JIT_RET, JIT_V0); + jit_addi_p(JIT_R0, JIT_VHEAP, offset*sizeof(void*)); + jit_pushr_p(JIT_R0); } break; } @@ -640,9 +935,8 @@ pgf_jit_function(PgfReader* rdr, PgfAbstr* abstr, #ifdef PGF_JIT_DEBUG gu_printf(out, err, "PUSH stk(%d)\n", index); #endif - - jit_ldxi_p(JIT_V0, JIT_RET, -(index+1)*sizeof(PgfClosure*)); - jit_str_p(JIT_RET, JIT_V0); + jit_ldxi_p(JIT_R0, JIT_SP, index*sizeof(PgfClosure*)); + jit_pushr_p(JIT_R0); break; } case 2: { @@ -650,10 +944,8 @@ pgf_jit_function(PgfReader* rdr, PgfAbstr* abstr, #ifdef PGF_JIT_DEBUG gu_printf(out, err, "PUSH env(%d)\n", index); #endif - - jit_getarg_p(JIT_V0, closure_arg); - jit_ldxi_p(JIT_V0, JIT_V0, sizeof(PgfClosure)+index*sizeof(PgfClosure*)); - jit_str_p(JIT_RET, JIT_V0); + jit_ldxi_p(JIT_R0, JIT_VCLOS, sizeof(PgfClosure)+index*sizeof(PgfClosure*)); + jit_pushr_p(JIT_R0); break; } default: @@ -661,15 +953,17 @@ pgf_jit_function(PgfReader* rdr, PgfAbstr* abstr, } break; } - case PGF_INSTR_EVAL: { - switch (mod & 0x3) { + case PGF_INSTR_EVAL+0: + case PGF_INSTR_EVAL+2: + jit_movr_p(JIT_R2, JIT_VCLOS); + case PGF_INSTR_EVAL+1: { + switch (mod) { case 0: { size_t offset = pgf_read_int(rdr); #ifdef PGF_JIT_DEBUG gu_printf(out, err, "EVAL hp(%d)", offset); #endif - - jit_addi_p(JIT_V0, JIT_V1, offset*sizeof(void*)); + jit_addi_p(JIT_VCLOS, JIT_VHEAP, offset*sizeof(void*)); break; } case 1: { @@ -677,13 +971,7 @@ pgf_jit_function(PgfReader* rdr, PgfAbstr* abstr, #ifdef PGF_JIT_DEBUG gu_printf(out, err, "EVAL stk(%d)", index); #endif - - jit_getarg_p(JIT_V0, es_arg); - jit_ldxi_p(JIT_V0, JIT_V0, offsetof(PgfEvalState,stack)); - jit_prepare(1); - jit_pusharg_p(JIT_V0); - jit_finish(gu_buf_last); - jit_ldxi_p(JIT_V0, JIT_RET, -index*sizeof(PgfClosure*)); + jit_ldxi_p(JIT_VCLOS, JIT_SP, index*sizeof(PgfClosure*)); break; } case 2: { @@ -691,91 +979,84 @@ pgf_jit_function(PgfReader* rdr, PgfAbstr* abstr, #ifdef PGF_JIT_DEBUG gu_printf(out, err, "EVAL env(%d)", index); #endif + jit_ldxi_p(JIT_VCLOS, JIT_VCLOS, sizeof(PgfClosure)+index*sizeof(PgfClosure*)); + break; + } + case 3: { + PgfCId id = pgf_read_cid(rdr, rdr->tmp_pool); +#ifdef PGF_JIT_DEBUG + gu_printf(out, err, "EVAL %s", id); +#endif + PgfCallPatch patch; + patch.cid = id; + patch.ref = jit_addi_p(JIT_VCLOS, JIT_VSTATE, jit_forward()); + gu_buf_push(rdr->jit_state->call_patches, PgfCallPatch, patch); break; } default: gu_impossible(); } - switch (mod >> 2) { + jit_ldr_p(JIT_R0, JIT_VCLOS); + + switch (opcode - PGF_INSTR_EVAL) { case 0: { #ifdef PGF_JIT_DEBUG - gu_printf(out, err, "\n"); + gu_printf(out, err, "\n"); #endif - - jit_prepare(2); - jit_pusharg_p(JIT_V0); - jit_getarg_p(JIT_V2, es_arg); - jit_pusharg_p(JIT_V2); - jit_ldr_p(JIT_V0, JIT_V0); - jit_finishr(JIT_V0); - jit_retval_p(JIT_V1); - jit_ldxi_p(JIT_V0, JIT_V1, offsetof(PgfValue, absfun)); + jit_pushr_p(JIT_R2); + jit_callr(JIT_R0); + jit_popr_p(JIT_VCLOS); break; } case 1: { size_t a = pgf_read_int(rdr); - size_t b = pgf_read_int(rdr); - + size_t b = pgf_read_int(rdr); + size_t c = pgf_read_int(rdr); #ifdef PGF_JIT_DEBUG - gu_printf(out, err, " tail(%d,%d)\n", a, b); + gu_printf(out, err, " tail(%d,%d,%d)\n", a, b, c); #endif - pgf_jit_compile_slide(rdr, es_arg, a, b); - jit_setarg_p(JIT_V0, closure_arg); - jit_ldr_p(JIT_RET, JIT_V0); - jit_tail_finishr(JIT_RET); + jit_ldxi_p(JIT_R2, JIT_SP, sizeof(PgfClosure*)*(c-a-1)); + for (size_t i = 0; i < c-b; i++) { + jit_ldxi_p(JIT_R1, JIT_SP, sizeof(PgfClosure*)*((c-b-1)-i)); + jit_stxi_p(sizeof(PgfClosure*)*((c-1)-i), JIT_SP, JIT_R1); + } + jit_addi_p(JIT_SP, JIT_SP, b*sizeof(PgfClosure*)); + jit_pushr_p(JIT_R2); + jit_jmpr(JIT_R0); break; } - default: - gu_impossible(); - } - break; - } - case PGF_INSTR_CALL: { - PgfCId id = pgf_read_cid(rdr, rdr->tmp_pool); -#ifdef PGF_JIT_DEBUG - gu_printf(out, err, "CALL %s", id); -#endif - - switch (mod >> 2) { - case 0: { + case 2: { + size_t b = pgf_read_int(rdr); + size_t c = pgf_read_int(rdr); #ifdef PGF_JIT_DEBUG - gu_printf(out, err, "\n"); + gu_printf(out, err, " update(%d,%d)\n", b, c); #endif - jit_getarg_p(JIT_V0, es_arg); - jit_getarg_p(JIT_V1, closure_arg); - jit_prepare(2); - jit_pusharg_p(JIT_V1); - jit_pusharg_p(JIT_V0); - - PgfCallPatch patch; - patch.cid = id; - patch.ref = jit_movi_p(JIT_V0, jit_forward()); - gu_buf_push(rdr->jit_state->call_patches, PgfCallPatch, patch); - jit_ldxi_p(JIT_V0, JIT_V0, offsetof(PgfAbsFun,function)); - - jit_finishr(JIT_V0); - jit_retval_p(JIT_V1); - break; - } - case 1: { - size_t a = pgf_read_int(rdr); - size_t b = pgf_read_int(rdr); - -#ifdef PGF_JIT_DEBUG - gu_printf(out, err, " tail(%d,%d)\n", a, b); -#endif + if (b >= 3) { + jit_stxi_p(sizeof(PgfClosure*)*(c-3), JIT_SP, JIT_FP); + jit_stxi_p(sizeof(PgfClosure*)*(c-2), JIT_SP, JIT_R2); + for (size_t i = 0; i < c-b; i++) { + jit_ldxi_p(JIT_R1, JIT_SP, sizeof(PgfClosure*)*((c-b-1)-i)); + jit_stxi_p(sizeof(PgfClosure*)*((c-4)-i), JIT_SP, JIT_R1); + } + jit_addi_p(JIT_SP, JIT_SP, (b-3)*sizeof(PgfClosure*)); + } else { + jit_subi_p(JIT_SP, JIT_SP, (3-b)*sizeof(PgfClosure*)); + for (size_t i = 0; i < c-b; i++) { + jit_ldxi_p(JIT_R1, JIT_SP, sizeof(PgfClosure*)*(i+(3-b))); + jit_stxi_p(sizeof(PgfClosure*)*i, JIT_SP, JIT_R1); + } + jit_stxi_p(sizeof(PgfClosure*)*(c-b), JIT_SP, JIT_FP); + jit_stxi_p(sizeof(PgfClosure*)*(c-b+1), JIT_SP, JIT_R2); + } - pgf_jit_compile_slide(rdr, es_arg, a, b); + jit_addi_p(JIT_FP, JIT_SP, sizeof(PgfClosure*)*(c-b)); + jit_movi_p(JIT_R1, abstr->eval_gates->update_closure); + jit_pushr_p(JIT_R1); - PgfCallPatch patch; - patch.cid = id; - patch.ref = jit_movi_p(JIT_V0, jit_forward()); - gu_buf_push(rdr->jit_state->call_patches, PgfCallPatch, patch); - jit_ldxi_p(JIT_RET, JIT_V0, offsetof(PgfAbsFun,function)); - jit_tail_finishr(JIT_RET); + jit_jmpr(JIT_R0); break; } default: @@ -783,43 +1064,40 @@ pgf_jit_function(PgfReader* rdr, PgfAbstr* abstr, } break; } - case PGF_INSTR_FAIL: + case PGF_INSTR_RET: { + size_t h = pgf_read_int(rdr); + + if (h > 0) + jit_addi_p(JIT_VHEAP, JIT_VHEAP, h*sizeof(PgfClosure*)); + + size_t a, b; + if (mod == 1) { + a = pgf_read_int(rdr); + b = pgf_read_int(rdr); #ifdef PGF_JIT_DEBUG - gu_printf(out, err, "FAIL\n"); + gu_printf(out, err, "RET hp(%d) tail(%d,%d)\n", h, a, b); #endif - break; - case PGF_INSTR_UPDATE: { + } else { + a = 0; + b = pgf_read_int(rdr); #ifdef PGF_JIT_DEBUG - gu_printf(out, err, "UPDATE\n"); + gu_printf(out, err, "RET hp(%d) update(%d)\n", h, b); #endif + jit_movi_p(JIT_R0, abstr->eval_gates->evaluate_indirection); + jit_str_p(JIT_VCLOS, JIT_R0); + jit_stxi_p(offsetof(PgfIndirection,val), JIT_VCLOS, JIT_VHEAP); + } - jit_getarg_p(JIT_V0, closure_arg); - jit_movi_p(JIT_V2, pgf_evaluate_indirection); - jit_stxi_p(0, JIT_V0, JIT_V2); - jit_stxi_p(sizeof(PgfClosure), JIT_V0, JIT_V1); + if (b-(a+1) > 0) + jit_subi_p(JIT_SP, JIT_SP, (b-(a+1))*sizeof(PgfClosure*)); + jit_bare_ret(a*sizeof(PgfClosure*)); break; } - case PGF_INSTR_RET: { - size_t count = pgf_read_int(rdr); - + case PGF_INSTR_FAIL: #ifdef PGF_JIT_DEBUG - gu_printf(out, err, "RET %d\n", count); + gu_printf(out, err, "FAIL\n"); #endif - - if (count > 0) { - jit_prepare(2); - jit_movi_ui(JIT_V0, count); - jit_pusharg_p(JIT_V0); - jit_getarg_p(JIT_V0, es_arg); - jit_ldxi_p(JIT_V0, JIT_V0, offsetof(PgfEvalState,stack)); - jit_pusharg_p(JIT_V0); - jit_finish(gu_buf_trim_n); - } - - jit_movr_p(JIT_RET, JIT_V1); - jit_ret(); break; - } default: gu_impossible(); } @@ -842,10 +1120,15 @@ pgf_jit_done(PgfReader* rdr, PgfAbstr* abstr) else { PgfAbsFun* con = gu_map_get(abstr->funs, patch->cid, PgfAbsFun*); - if (con != NULL) - jit_patch_movi(patch->ref,con); - else { + if (con == NULL) gu_impossible(); + else if (con->closure_id == 0) { + jit_patch_movi(patch->ref,con); + } else { + size_t offset = + offsetof(PgfEvalState,globals)+ + sizeof(PgfIndirection)*(con->closure_id-1); + jit_patch_movi(patch->ref,offset); } } } |
