summaryrefslogtreecommitdiff
path: root/src/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime')
-rw-r--r--src/runtime/c/gu/mem.c3
-rw-r--r--src/runtime/c/gu/seq.c6
-rw-r--r--src/runtime/c/gu/seq.h3
-rw-r--r--src/runtime/c/pgf/data.h34
-rw-r--r--src/runtime/c/pgf/evaluator.c427
-rw-r--r--src/runtime/c/pgf/evaluator.h87
-rw-r--r--src/runtime/c/pgf/jit.c765
-rw-r--r--src/runtime/c/pgf/lightning/core-common.h8
-rw-r--r--src/runtime/c/pgf/lightning/i386/core-32.h12
-rw-r--r--src/runtime/c/pgf/lightning/i386/core-64.h9
-rw-r--r--src/runtime/c/pgf/reader.c4
-rw-r--r--src/runtime/c/pgf/reader.h3
12 files changed, 799 insertions, 562 deletions
diff --git a/src/runtime/c/gu/mem.c b/src/runtime/c/gu/mem.c
index 62ffef85d..cc168637e 100644
--- a/src/runtime/c/gu/mem.c
+++ b/src/runtime/c/gu/mem.c
@@ -311,9 +311,8 @@ gu_pool_free(GuPool* pool)
{
GuFinalizerNode* node = pool->finalizers;
while (node) {
- GuFinalizerNode* next = node->next;
node->fin->fn(node->fin);
- node = next;
+ node = node->next;
}
GuMemChunk* chunk = pool->chunks;
while (chunk) {
diff --git a/src/runtime/c/gu/seq.c b/src/runtime/c/gu/seq.c
index 2b99df318..2c3d6c3e3 100644
--- a/src/runtime/c/gu/seq.c
+++ b/src/runtime/c/gu/seq.c
@@ -136,12 +136,6 @@ gu_buf_data(GuBuf* buf)
return &buf->seq->data;
}
-void*
-gu_buf_last(GuBuf* buf)
-{
- return buf->seq->data + buf->elem_size*(buf->seq->len-1);
-}
-
GuSeq*
gu_buf_data_seq(GuBuf* buf)
{
diff --git a/src/runtime/c/gu/seq.h b/src/runtime/c/gu/seq.h
index 034620140..5accb0b24 100644
--- a/src/runtime/c/gu/seq.h
+++ b/src/runtime/c/gu/seq.h
@@ -65,9 +65,6 @@ gu_buf_avail(GuBuf* buf);
void*
gu_buf_data(GuBuf* buf);
-void*
-gu_buf_last(GuBuf* buf);
-
GuSeq*
gu_buf_data_seq(GuBuf* buf);
diff --git a/src/runtime/c/pgf/data.h b/src/runtime/c/pgf/data.h
index dc6965174..8c9b577d9 100644
--- a/src/runtime/c/pgf/data.h
+++ b/src/runtime/c/pgf/data.h
@@ -76,7 +76,7 @@ typedef struct {
PgfEquations* defns; // maybe null
PgfExprProb ep;
void* predicate;
- void* function;
+ size_t closure_id;
} PgfAbsFun;
extern GU_DECLARE_TYPE(PgfAbsFun, abstract);
@@ -95,31 +95,31 @@ typedef struct {
extern GU_DECLARE_TYPE(PgfAbsCat, abstract);
+typedef struct PgfEvalGates PgfEvalGates;
+
typedef struct {
PgfCId name;
PgfFlags* aflags;
PgfCIdMap* funs; // |-> PgfAbsFun*
PgfCIdMap* cats; // |-> PgfAbsCat*
PgfAbsFun* abs_lin_fun;
+ PgfEvalGates* eval_gates;
} PgfAbstr;
typedef enum {
- PGF_INSTR_ENTER,
- PGF_INSTR_CASE,
- PGF_INSTR_CASE_LIT,
- PGF_INSTR_ALLOC,
- PGF_INSTR_PUT_CONSTR,
- PGF_INSTR_PUT_FUN,
- PGF_INSTR_PUT_CLOSURE,
- PGF_INSTR_PUT_LIT,
- PGF_INSTR_SET,
- PGF_INSTR_SET_PAD,
- PGF_INSTR_PUSH,
- PGF_INSTR_EVAL,
- PGF_INSTR_CALL,
- PGF_INSTR_FAIL,
- PGF_INSTR_UPDATE,
- PGF_INSTR_RET
+ PGF_INSTR_CHECK_ARGS = 0,
+ PGF_INSTR_CASE = 1,
+ PGF_INSTR_CASE_LIT = 2,
+ PGF_INSTR_ALLOC = 3,
+ PGF_INSTR_PUT_CONSTR = 4,
+ PGF_INSTR_PUT_CLOSURE = 5,
+ PGF_INSTR_PUT_LIT = 6,
+ PGF_INSTR_SET = 7,
+ PGF_INSTR_SET_PAD = 8,
+ PGF_INSTR_PUSH = 9,
+ PGF_INSTR_EVAL = 10,
+ PGF_INSTR_RET = 13,
+ PGF_INSTR_FAIL = 15
} PgfInstruction;
struct PgfPGF {
diff --git a/src/runtime/c/pgf/evaluator.c b/src/runtime/c/pgf/evaluator.c
index a3f22e274..25a9158dc 100644
--- a/src/runtime/c/pgf/evaluator.c
+++ b/src/runtime/c/pgf/evaluator.c
@@ -1,288 +1,187 @@
#include "pgf/pgf.h"
#include "pgf/data.h"
#include "pgf/evaluator.h"
+#include <stdlib.h>
-typedef struct PgfEnv PgfEnv;
-
-struct PgfEnv {
- PgfEnv* next;
- PgfClosure* closure;
-};
-
-typedef struct {
- PgfClosure header;
- PgfEnv* env;
- PgfExpr expr;
-} PgfExprThunk;
-
-typedef struct {
- PgfClosure header;
- PgfClosure* val;
-} PgfIndirection;
-
-typedef struct {
- PgfClosure header;
- int level;
- size_t n_args;
- PgfClosure* args[];
-} PgfValueGen;
-
-typedef struct {
- PgfClosure header;
- PgfEnv* env;
- PgfMetaId id;
- size_t n_args;
- PgfClosure* args[];
-} PgfValueMeta;
-
-typedef struct {
- PgfClosure header;
- PgfLiteral lit;
-} PgfValueLit;
+#define PGF_ARGS_DELTA 5
PgfClosure*
-pgf_evaluate_indirection(PgfEvalState* state, PgfClosure* closure)
-{
- PgfIndirection* indir = (PgfIndirection*) closure;
- return indir->val;
-}
-
-PgfClosure*
-pgf_evaluate_value(PgfEvalState* state, PgfClosure* closure)
-{
- return closure;
-}
-
-static PgfClosure*
-pgf_evaluate_value_gen(PgfEvalState* state, PgfClosure* closure)
-{
- PgfValueGen* val = (PgfValueGen*) closure;
-
- size_t n_args = val->n_args + gu_buf_length(state->stack);
- PgfValueGen* new_val =
- gu_new_flex(state->pool, PgfValueGen, args, n_args);
- new_val->header.code = pgf_evaluate_value_gen;
- new_val->level = val->level;
- new_val->n_args = n_args;
-
- size_t i = 0;
- while (i < val->n_args) {
- new_val->args[i] = val->args[i];
- i++;
- }
- while (i < n_args) {
- new_val->args[i] = gu_buf_pop(state->stack, PgfClosure*);
- i++;
- }
-
- return &new_val->header;
-}
-
-static PgfClosure*
-pgf_evaluate_value_meta(PgfEvalState* state, PgfClosure* closure)
-{
- PgfValueMeta* val = (PgfValueMeta*) closure;
-
- size_t n_args = val->n_args + gu_buf_length(state->stack);
- PgfValueMeta* new_val =
- gu_new_flex(state->pool, PgfValueMeta, args, n_args);
- new_val->header.code = pgf_evaluate_value_meta;
- new_val->id = val->id;
- new_val->n_args = n_args;
-
- size_t i = 0;
- while (i < val->n_args) {
- new_val->args[i] = val->args[i];
- i++;
- }
- while (i < n_args) {
- val->args[i] = gu_buf_pop(state->stack, PgfClosure*);
- i++;
- }
-
- return &new_val->header;
-}
-
-static PgfClosure*
-pgf_evaluate_value_lit(PgfEvalState* state, PgfClosure* closure)
-{
- return closure;
-}
-
-static PgfClosure*
pgf_evaluate_expr_thunk(PgfEvalState* state, PgfClosure* closure)
{
PgfExprThunk* thunk = (PgfExprThunk*) closure;
PgfEnv* env = thunk->env;
PgfExpr expr = thunk->expr;
- for (;;) {
- GuVariantInfo ei = gu_variant_open(expr);
- switch (ei.tag) {
- case PGF_EXPR_ABS: {
- PgfExprAbs* eabs = ei.data;
-
- if (gu_buf_length(state->stack) > 0) {
- PgfEnv* new_env = gu_new(PgfEnv, state->pool);
- new_env->next = env;
- new_env->closure = gu_buf_pop(state->stack, PgfClosure*);
-
- env = new_env;
- expr = eabs->body;
- } else {
- thunk->expr = expr;
- return closure;
- }
- break;
+ size_t n_args = 0;
+ PgfClosure** args = NULL;
+ PgfClosure* res = NULL;
+
+repeat:;
+ GuVariantInfo ei = gu_variant_open(expr);
+ switch (ei.tag) {
+ case PGF_EXPR_ABS: {
+ PgfExprAbs* eabs = ei.data;
+
+ if (n_args > 0) {
+ PgfEnv* new_env = gu_new(PgfEnv, state->pool);
+ new_env->next = env;
+ new_env->closure = args[--n_args];
+
+ env = new_env;
+ expr = eabs->body;
+ goto repeat;
+ } else {
+ thunk->header.code = state->eval_gates->evaluate_value_lambda;
+ thunk->expr = eabs->body;
+ res = closure;
}
- case PGF_EXPR_APP: {
- PgfExprApp* eapp = ei.data;
- PgfExprThunk* thunk =
- gu_new(PgfExprThunk, state->pool);
- thunk->header.code = pgf_evaluate_expr_thunk;
- thunk->env = env;
- thunk->expr = eapp->arg;
- gu_buf_push(state->stack, PgfClosure*, &thunk->header);
- expr = eapp->fun;
- break;
+ break;
+ }
+ case PGF_EXPR_APP: {
+ PgfExprApp* eapp = ei.data;
+ PgfExprThunk* thunk =
+ gu_new(PgfExprThunk, state->pool);
+ thunk->header.code = state->eval_gates->evaluate_expr_thunk;
+ thunk->env = env;
+ thunk->expr = eapp->arg;
+
+ if (n_args % PGF_ARGS_DELTA == 0) {
+ args = realloc(args, n_args + PGF_ARGS_DELTA);
}
- case PGF_EXPR_LIT: {
- PgfExprLit* elit = ei.data;
+ args[n_args++] = &thunk->header;
- if (gu_buf_length(state->stack) > 0) {
- GuExnData* err_data = gu_raise(state->err, PgfExn);
- if (err_data) {
- err_data->data = "found literal of function type";
- }
- return NULL;
- }
-
- PgfValueLit* val = (PgfValueLit*) closure;
- val->header.code = pgf_evaluate_value_lit;
- val->lit = elit->lit;
- return &val->header;
+ expr = eapp->fun;
+ goto repeat;
+ }
+ case PGF_EXPR_LIT: {
+ PgfExprLit* elit = ei.data;
+ PgfValueLit* val = (PgfValueLit*) closure;
+ val->header.code = state->eval_gates->evaluate_value_lit;
+ val->lit = elit->lit;
+ res = &val->header;
+ break;
+ }
+ case PGF_EXPR_META: {
+ PgfExprMeta* emeta = ei.data;
+
+ PgfValueMeta* val =
+ gu_new_flex(state->pool, PgfValueMeta, args, n_args);
+ val->header.code = state->eval_gates->evaluate_value_meta;
+ val->id = emeta->id;
+ val->n_args = n_args*sizeof(PgfClosure*);
+ for (size_t i = 0; i < n_args; i++) {
+ val->args[i] = args[n_args-i-1];
}
- case PGF_EXPR_META: {
- PgfExprMeta* emeta = ei.data;
- size_t n_args = gu_buf_length(state->stack);
+ PgfIndirection* indir = (PgfIndirection*) closure;
+ indir->header.code = state->eval_gates->evaluate_indirection;
+ indir->val = &val->header;
- PgfValueMeta* val =
- gu_new_flex(state->pool, PgfValueMeta, args, n_args);
- val->header.code = pgf_evaluate_value_meta;
- val->id = emeta->id;
- val->n_args = n_args;
- for (size_t i = 0; i < n_args; i++) {
- val->args[i] = gu_buf_pop(state->stack, PgfClosure*);
+ res = &val->header;
+ break;
+ }
+ case PGF_EXPR_FUN: {
+ PgfExprFun* efun = ei.data;
+
+ PgfAbsFun* absfun =
+ gu_map_get(state->pgf->abstract.funs, efun->fun, PgfAbsFun*);
+ if (absfun == NULL) {
+ GuExnData* err_data = gu_raise(state->err, PgfExn);
+ if (err_data) {
+ err_data->data = (char* const)
+ gu_format_string(err_data->pool,
+ "Unknown function: %s",
+ efun->fun);
}
-
- PgfIndirection* indir = (PgfIndirection*) closure;
- indir->header.code = pgf_evaluate_indirection;
- indir->val = &val->header;
-
- return &val->header;
- }
- case PGF_EXPR_FUN: {
- PgfExprFun* efun = ei.data;
-
- PgfAbsFun* absfun =
- gu_map_get(state->pgf->abstract.funs, efun->fun, PgfAbsFun*);
- if (absfun == NULL) {
- GuExnData* err_data = gu_raise(state->err, PgfExn);
- if (err_data) {
- err_data->data = (char* const)
- gu_format_string(err_data->pool,
- "Unknown function: %s",
- efun->fun);
+ } else {
+ if (absfun->closure_id > 0) {
+ res = &state->globals[absfun->closure_id-1].header;
+
+ if (n_args > 0) {
+ PgfValuePAP* val = gu_new_flex(state->pool, PgfValuePAP, args, n_args);
+ val->header.code = state->eval_gates->evaluate_value_pap;
+ val->fun = res;
+ val->n_args = n_args*sizeof(PgfClosure*);
+ for (size_t i = 0; i < n_args; i++) {
+ val->args[i] = args[i];
+ }
+ res = &val->header;
}
- return NULL;
- }
-
- PgfValue* val;
- if (absfun->function != NULL) {
- val = (PgfValue*) ((PgfFunction) absfun->function)(state, closure);
} else {
- size_t n_args = absfun->arity;
+ size_t arity = absfun->arity;
- val = gu_new_flex(state->pool, PgfValue, args, n_args);
- val->header.code = pgf_evaluate_value;
+ PgfValue* val = gu_new_flex(state->pool, PgfValue, args, arity);
+ val->header.code = state->eval_gates->evaluate_value;
val->absfun = absfun;
- for (size_t i = 0; i < n_args; i++) {
- val->args[i] = gu_buf_pop(state->stack, PgfClosure*);
+ for (size_t i = 0; i < arity; i++) {
+ val->args[i] = args[--n_args];
}
+
+ res = &val->header;
}
PgfIndirection* indir = (PgfIndirection*) closure;
- indir->header.code = pgf_evaluate_indirection;
- indir->val = &val->header;
-
- return &val->header;
+ indir->header.code = state->eval_gates->evaluate_indirection;
+ indir->val = res;
}
- case PGF_EXPR_VAR: {
- PgfExprVar* evar = ei.data;
- PgfEnv* tmp_env = env;
- size_t i = evar->var;
- while (i > 0) {
- tmp_env = tmp_env->next;
- if (tmp_env == NULL) {
- GuExnData* err_data = gu_raise(state->err, PgfExn);
- if (err_data) {
- err_data->data = "invalid de Bruijn index";
- }
- return NULL;
+ break;
+ }
+ case PGF_EXPR_VAR: {
+ PgfExprVar* evar = ei.data;
+ PgfEnv* tmp_env = env;
+ size_t i = evar->var;
+ while (i > 0) {
+ tmp_env = tmp_env->next;
+ if (tmp_env == NULL) {
+ GuExnData* err_data = gu_raise(state->err, PgfExn);
+ if (err_data) {
+ err_data->data = "invalid de Bruijn index";
}
- i--;
+ return NULL;
}
+ i--;
+ }
- PgfClosure* val =
- tmp_env->closure->code(state, tmp_env->closure);
+ res = tmp_env->closure;
- PgfIndirection* indir = (PgfIndirection*) closure;
- indir->header.code = pgf_evaluate_indirection;
- indir->val = val;
+ PgfIndirection* indir = (PgfIndirection*) closure;
+ indir->header.code = state->eval_gates->evaluate_indirection;
+ indir->val = res;
- return val;
- }
- case PGF_EXPR_TYPED: {
- PgfExprTyped* etyped = ei.data;
- expr = etyped->expr;
- break;
- }
- case PGF_EXPR_IMPL_ARG: {
- PgfExprImplArg* eimpl = ei.data;
- expr = eimpl->expr;
- break;
- }
- default:
- gu_impossible();
+ if (n_args > 0) {
+ PgfValuePAP* val = gu_new_flex(state->pool, PgfValuePAP, args, n_args);
+ val->header.code = state->eval_gates->evaluate_value_pap;
+ val->fun = res;
+ val->n_args = n_args*sizeof(PgfClosure*);
+ for (size_t i = 0; i < n_args; i++) {
+ val->args[i] = args[i];
+ }
+ res = &val->header;
}
+ break;
}
-}
-
-void
-pgf_evaluate_save_variables(PgfEvalState* state, PgfValue* val)
-{
- size_t n_args = val->absfun->arity;
- for (size_t i = 0; i < n_args; i++) {
- gu_buf_push(state->stack, PgfClosure*, val->args[i]);
+ case PGF_EXPR_TYPED: {
+ PgfExprTyped* etyped = ei.data;
+ expr = etyped->expr;
+ goto repeat;
}
-}
-
-void
-pgf_evaluate_slide(PgfEvalState* state, size_t a, size_t b)
-{
- size_t len = gu_buf_length(state->stack);
- for (size_t i = 0; i < b-a; i++) {
- PgfClosure* c = gu_buf_get(state->stack, PgfClosure*, len-(b-a)+i);
- gu_buf_set(state->stack, PgfClosure*, len-b+i, c);
+ case PGF_EXPR_IMPL_ARG: {
+ PgfExprImplArg* eimpl = ei.data;
+ expr = eimpl->expr;
+ goto repeat;
+ }
+ default:
+ gu_impossible();
}
- gu_buf_trim_n(state->stack, a);
+
+ free(args);
+ return res;
}
static PgfExpr
pgf_value2expr(PgfEvalState* state, int level, PgfClosure* clos, GuPool* pool)
{
- clos = clos->code(state, clos);
+ clos = state->eval_gates->enter(state, clos);
if (clos == NULL)
return gu_null_variant;
@@ -290,13 +189,13 @@ pgf_value2expr(PgfEvalState* state, int level, PgfClosure* clos, GuPool* pool)
size_t n_args = 0;
PgfClosure** args;
- if (clos->code == pgf_evaluate_value) {
+ if (clos->code == state->eval_gates->evaluate_value) {
PgfValue* val = (PgfValue*) clos;
expr = val->absfun->ep.expr;
n_args = gu_seq_length(val->absfun->type->hypos);
args = val->args;
- } else if (clos->code == pgf_evaluate_value_gen) {
+ } else if (clos->code == state->eval_gates->evaluate_value_gen) {
PgfValueGen* val = (PgfValueGen*) clos;
PgfExprVar *evar =
@@ -305,9 +204,9 @@ pgf_value2expr(PgfEvalState* state, int level, PgfClosure* clos, GuPool* pool)
&expr, pool);
evar->var = level - val->level - 1;
- n_args = val->n_args;
+ n_args = val->n_args/sizeof(PgfClosure*);
args = val->args;
- } else if (clos->code == pgf_evaluate_value_meta) {
+ } else if (clos->code == state->eval_gates->evaluate_value_meta) {
PgfValueMeta* val = (PgfValueMeta*) clos;
PgfExprMeta *emeta =
@@ -316,16 +215,16 @@ pgf_value2expr(PgfEvalState* state, int level, PgfClosure* clos, GuPool* pool)
&expr, pool);
emeta->id = val->id;
- n_args = val->n_args;
+ n_args = val->n_args / sizeof(PgfClosure*);
args = val->args;
- } else if (clos->code == pgf_evaluate_value_lit) {
+ } else if (clos->code == state->eval_gates->evaluate_value_lit) {
PgfValueLit* val = (PgfValueLit*) clos;
PgfExprLit *elit =
gu_new_variant(PGF_EXPR_LIT,
PgfExprLit,
&expr, pool);
-
+
GuVariantInfo i = gu_variant_open(val->lit);
switch (i.tag) {
case PGF_LITERAL_STR: {
@@ -362,13 +261,18 @@ pgf_value2expr(PgfEvalState* state, int level, PgfClosure* clos, GuPool* pool)
default:
gu_impossible();
}
- } else {
+ } else if (clos->code == state->eval_gates->evaluate_value_pap) {
+ PgfValuePAP *pap = (PgfValuePAP*) clos;
+
+ n_args = pap->n_args / sizeof(PgfClosure*);
+ args = pap->args;
+ } else if (clos->code == state->eval_gates->evaluate_value_lambda) {
PgfExprThunk *old_thunk = (PgfExprThunk*) clos;
PgfExprAbs *old_eabs = gu_variant_open(old_thunk->expr).data;
PgfValueGen* gen =
gu_new(PgfValueGen, state->pool);
- gen->header.code = pgf_evaluate_value_gen;
+ gen->header.code = state->eval_gates->evaluate_value_gen;
gen->level = level;
gen->n_args = 0;
@@ -378,7 +282,7 @@ pgf_value2expr(PgfEvalState* state, int level, PgfClosure* clos, GuPool* pool)
PgfExprThunk* new_thunk =
gu_new(PgfExprThunk, state->pool);
- new_thunk->header.code = pgf_evaluate_expr_thunk;
+ new_thunk->header.code = state->eval_gates->evaluate_expr_thunk;
new_thunk->env = new_env;
new_thunk->expr = old_eabs->body;
@@ -389,6 +293,8 @@ pgf_value2expr(PgfEvalState* state, int level, PgfClosure* clos, GuPool* pool)
eabs->bind_type = old_eabs->bind_type;
eabs->id = gu_format_string(pool, "v%d", level);
eabs->body = pgf_value2expr(state, level+1, &new_thunk->header, pool);
+ } else {
+ gu_impossible();
}
for (size_t i = 0; i < n_args; i++) {
@@ -412,15 +318,24 @@ pgf_value2expr(PgfEvalState* state, int level, PgfClosure* clos, GuPool* pool)
PgfExpr
pgf_compute(PgfPGF* pgf, PgfExpr expr, GuExn* err, GuPool* pool, GuPool* out_pool)
{
- PgfEvalState* state = gu_new(PgfEvalState, pool);
+ size_t n_closures = gu_seq_length(pgf->abstract.eval_gates->defrules);
+
+ PgfEvalState* state =
+ gu_new_flex(pool, PgfEvalState, globals, n_closures);
state->pgf = pgf;
+ state->eval_gates = pgf->abstract.eval_gates;
state->pool = pool;
state->err = err;
- state->stack = gu_new_buf(PgfClosure*, pool);
+
+ PgfFunction* defrules = gu_seq_data(state->eval_gates->defrules);
+ for (size_t i = 0; i < n_closures; i++) {
+ state->globals[i].header.code = defrules[i];
+ state->globals[i].val = NULL;
+ }
PgfExprThunk* thunk =
gu_new(PgfExprThunk, pool);
- thunk->header.code = pgf_evaluate_expr_thunk;
+ thunk->header.code = state->eval_gates->evaluate_expr_thunk;
thunk->env = NULL;
thunk->expr = expr;
diff --git a/src/runtime/c/pgf/evaluator.h b/src/runtime/c/pgf/evaluator.h
index 3962e772f..a6a98cdf1 100644
--- a/src/runtime/c/pgf/evaluator.h
+++ b/src/runtime/c/pgf/evaluator.h
@@ -1,38 +1,91 @@
#ifndef PGF_EVALUATOR_H_
#define PGF_EVALUATOR_H_
-struct PgfEvalState {
+typedef void *PgfFunction;
+
+typedef struct {
+ PgfFunction code;
+} PgfClosure;
+
+typedef struct {
+ PgfClosure header;
+ PgfClosure* val;
+} PgfIndirection;
+
+typedef struct {
PgfPGF* pgf;
+ PgfEvalGates* eval_gates; // cached from pgf->abstr->eval_gates
GuPool* pool;
GuExn* err;
- GuBuf* stack;
-};
+ PgfIndirection globals[]; // derived from gu_seq_data(pgf->abstr->eval_gates->defrules)
+} PgfEvalState;
-typedef struct PgfClosure PgfClosure;
-typedef struct PgfEvalState PgfEvalState;
+typedef struct PgfEnv PgfEnv;
-typedef PgfClosure* (*PgfFunction)(PgfEvalState* state, PgfClosure* val);
-
-struct PgfClosure {
- PgfFunction code;
+struct PgfEnv {
+ PgfEnv* next;
+ PgfClosure* closure;
};
typedef struct {
PgfClosure header;
+ PgfEnv* env;
+ PgfExpr expr;
+} PgfExprThunk;
+
+typedef struct {
+ PgfClosure header;
PgfAbsFun* absfun;
PgfClosure* args[];
} PgfValue;
-PgfClosure*
-pgf_evaluate_indirection(PgfEvalState* state, PgfClosure* closure);
+typedef struct {
+ PgfClosure header;
+ int level;
+ size_t n_args;
+ PgfClosure* args[];
+} PgfValueGen;
-PgfClosure*
-pgf_evaluate_value(PgfEvalState* state, PgfClosure* closure);
+typedef struct {
+ PgfClosure header;
+ PgfEnv* env;
+ PgfMetaId id;
+ size_t n_args;
+ PgfClosure* args[];
+} PgfValueMeta;
-void
-pgf_evaluate_save_variables(PgfEvalState* state, PgfValue* val);
+typedef struct {
+ PgfClosure header;
+ PgfLiteral lit;
+} PgfValueLit;
-void
-pgf_evaluate_slide(PgfEvalState* state, size_t a, size_t b);
+typedef struct {
+ PgfClosure header;
+ PgfClosure* fun;
+ size_t n_args;
+ PgfClosure* args[];
+} PgfValuePAP;
+
+struct PgfEvalGates {
+ PgfFunction evaluate_expr_thunk;
+ PgfFunction evaluate_indirection;
+ PgfFunction evaluate_value;
+ PgfFunction evaluate_value_gen;
+ PgfFunction evaluate_value_meta;
+ PgfFunction evaluate_value_lit;
+ PgfFunction evaluate_value_pap;
+ PgfFunction evaluate_value_lambda;
+
+ PgfFunction update_closure;
+ PgfFunction update_pap;
+
+ PgfClosure* (*enter)(PgfEvalState* state, PgfClosure* closure);
+
+ GuFinalizer fin;
+ GuSeq* defrules;
+};
+
+PgfClosure*
+pgf_evaluate_expr_thunk(PgfEvalState* state, PgfClosure* closure);
#endif
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);
}
}
}
diff --git a/src/runtime/c/pgf/lightning/core-common.h b/src/runtime/c/pgf/lightning/core-common.h
index 04dbb2c7b..3cda23322 100644
--- a/src/runtime/c/pgf/lightning/core-common.h
+++ b/src/runtime/c/pgf/lightning/core-common.h
@@ -52,6 +52,12 @@ typedef struct {
#define JIT_V0 JIT_V(0)
#define JIT_V1 JIT_V(1)
#define JIT_V2 JIT_V(2)
+#define JIT_FPR0 JIT_FPR(0)
+#define JIT_FPR1 JIT_FPR(1)
+#define JIT_FPR2 JIT_FPR(2)
+#define JIT_FPR3 JIT_FPR(3)
+#define JIT_FPR4 JIT_FPR(4)
+#define JIT_FPR5 JIT_FPR(5)
#define _jitl _jit.jitl
@@ -149,7 +155,7 @@ typedef union jit_code {
#define jit_xorr_ul(d, s1, s2) jit_xorr_l((d), (s1), (s2))
#define jit_addr_p(d, s1, s2) jit_addr_ul((d), (s1), (s2))
-#define jit_addi_p(d, rs, is) jit_addi_ul((d), (rs), (long) (is))
+#define jit_addi_p(d, rs, is) (jit_addi_ul((d), (rs), (long) (is)), _jit.x.pc)
#define jit_movr_p(d, rs) jit_movr_ul((d), (rs))
#define jit_subr_p(d, s1, s2) jit_subr_ul((d), (s1), (s2))
#define jit_subi_p(d, rs, is) jit_subi_ul((d), (rs), (long) (is))
diff --git a/src/runtime/c/pgf/lightning/i386/core-32.h b/src/runtime/c/pgf/lightning/i386/core-32.h
index 561fab5fb..9de85b86e 100644
--- a/src/runtime/c/pgf/lightning/i386/core-32.h
+++ b/src/runtime/c/pgf/lightning/i386/core-32.h
@@ -101,6 +101,8 @@ struct jit_local_state {
#define jit_ret() jit_base_ret (_jitl.alloca_offset)
#endif
+#define jit_bare_ret(IM) ((IM == 0) ? RET_() : RETi(IM))
+
#define jit_calli(label) (CALLm( ((unsigned long) (label))), _jit.x.pc)
#define jit_callr(reg) CALLsr(reg)
@@ -108,16 +110,6 @@ struct jit_local_state {
#define jit_finish(sub) (_jitl.finish_ref = jit_calli((sub)), ADDLir(sizeof(long) * _jitl.argssize, JIT_SP), _jitl.argssize = 0, _jitl.finish_ref)
#define jit_finishr(reg) (jit_callr((reg)), ADDLir(sizeof(long) * _jitl.argssize, JIT_SP), _jitl.argssize = 0)
-#ifdef __APPLE__
-#define jit_tail_finishr(reg) jit_base_tail_finishr(-12, reg)
-#else
-#define jit_tail_finishr(reg) jit_base_tail_finishr(_jitl.alloca_offset, reg)
-#endif
-
-#define jit_base_tail_finishr(ofs, reg) \
- (((ofs) < 0 ? LEAVE_() : POPLr(_EBP)), \
- POPLr(_EDI), POPLr(_ESI), POPLr(_EBX), jit_jmpr(reg))
-
#define jit_arg_c() ((_jitl.framesize += sizeof(int)) - sizeof(int))
#define jit_arg_uc() ((_jitl.framesize += sizeof(int)) - sizeof(int))
#define jit_arg_s() ((_jitl.framesize += sizeof(int)) - sizeof(int))
diff --git a/src/runtime/c/pgf/lightning/i386/core-64.h b/src/runtime/c/pgf/lightning/i386/core-64.h
index 70b4d6069..bd53d9744 100644
--- a/src/runtime/c/pgf/lightning/i386/core-64.h
+++ b/src/runtime/c/pgf/lightning/i386/core-64.h
@@ -190,14 +190,6 @@ struct jit_local_state {
? (ADDQir(sizeof(long) * _jitl.argssize, JIT_SP), _jitl.argssize = 0) \
: 0))
-#ifdef __APPLE__
-#define jit_tail_finishr(reg) jit_base_tail_finishr(-12, reg)
-#else
-#define jit_tail_finishr(reg) jit_base_tail_finishr(_jitl.alloca_offset, reg)
-#endif
-
-#define jit_base_tail_finishr(ofs, reg)
-
#define jit_retval_l(rd) ((void)jit_movr_l ((rd), _EAX))
#define jit_arg_i() (_jitl.nextarg_geti < JIT_ARG_MAX \
? _jitl.nextarg_geti++ \
@@ -273,6 +265,7 @@ static int jit_arg_reg_order[] = { _EDI, _ESI, _EDX, _ECX, _R8D, _R9D };
#define jit_patch_at(jump_pc,v) (_jitl.long_jumps ? jit_patch_long_at((jump_pc)-3, v) : jit_patch_short_at(jump_pc, v))
#define jit_patch_calli(pa,pv) (*_PSL((pa) - sizeof(long)) = _jit_SL((pv)))
#define jit_ret() (LEAVE_(), POPQr(_R14), POPQr(_R13), POPQr(_R12), POPQr(_EBX), RET_())
+#define jit_bare_ret(IM) ((IM == 0) ? RET_() : RETi(IM))
/* Memory */
diff --git a/src/runtime/c/pgf/reader.c b/src/runtime/c/pgf/reader.c
index 20dfd6e6c..3594f80ed 100644
--- a/src/runtime/c/pgf/reader.c
+++ b/src/runtime/c/pgf/reader.c
@@ -441,7 +441,7 @@ pgf_read_absfun(PgfReader* rdr, PgfAbstr* abstr)
switch (tag) {
case 0:
absfun->defns = NULL;
- absfun->function = NULL;
+ absfun->closure_id = 0;
break;
case 1: {
GuLength length = pgf_read_len(rdr);
@@ -557,6 +557,8 @@ pgf_read_abstract(PgfReader* rdr, PgfAbstr* abstract)
abstract->aflags = pgf_read_flags(rdr);
gu_return_on_exn(rdr->err, );
+ abstract->eval_gates = pgf_jit_gates(rdr);
+
abstract->funs = pgf_read_absfuns(rdr, abstract);
gu_return_on_exn(rdr->err, );
diff --git a/src/runtime/c/pgf/reader.h b/src/runtime/c/pgf/reader.h
index 98042c330..6fa24e6d2 100644
--- a/src/runtime/c/pgf/reader.h
+++ b/src/runtime/c/pgf/reader.h
@@ -53,6 +53,9 @@ typedef struct PgfJitState PgfJitState;
PgfJitState*
pgf_new_jit(PgfReader* rdr);
+PgfEvalGates*
+pgf_jit_gates(PgfReader* rdr);
+
void
pgf_jit_predicate(PgfReader* rdr, PgfAbstr* abstr,
PgfAbsCat* abscat);