Skip to content

Commit

Permalink
JIT compile sp_runnativecall_v and sp_runnativecall_i
Browse files Browse the repository at this point in the history
  • Loading branch information
niner committed Oct 25, 2021
1 parent 6e5de3e commit 9111a09
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/jit/compile.c
Expand Up @@ -103,6 +103,9 @@ MVMJitCode * MVM_jit_compile_graph(MVMThreadContext *tc, MVMJitGraph *jg) {
case MVM_JIT_NODE_RUNCCODE:
MVM_jit_emit_runccode(tc, &cl, jg, &node->u.runccode);
break;
case MVM_JIT_NODE_RUNNATIVECALL:
MVM_jit_emit_runnativecall(tc, &cl, jg, &node->u.runnativecall);
break;
case MVM_JIT_NODE_DISPATCH:
MVM_jit_emit_dispatch(tc, &cl, jg, &node->u.dispatch);
break;
Expand Down
66 changes: 66 additions & 0 deletions src/jit/graph.c
Expand Up @@ -3875,6 +3875,72 @@ static MVMint32 consume_ins(MVMThreadContext *tc, MVMJitGraph *jg,
jg_append_label(tc, jg, reentry_label);
break;
}
case MVM_OP_sp_runnativecall_v:
case MVM_OP_sp_runnativecall_i: {
int start = (op == MVM_OP_sp_runnativecall_v) ? 0 : 1;
MVMint16 dst = ins->operands[0].reg.orig;

MVMSpeshFacts *object_facts = MVM_spesh_get_facts(tc, iter->graph, ins->operands[start]);
if (!(object_facts->flags & MVM_SPESH_FACT_KNOWN_VALUE)) {
MVM_spesh_graph_add_comment(tc, iter->graph, iter->ins,
"BAIL: op <%s> (Can't find nc_site value on spesh ins)", ins->info->name);
return 0;
}

MVMNativeCallBody *body = MVM_nativecall_get_nc_body(tc, object_facts->value.o);
MVMCallsite *callsite = (MVMCallsite*)ins->operands[1 + start].lit_ui64;
MVMJitCallArg *args = callsite->flag_count > 1 /* first arg is return_type */
? MVM_spesh_alloc(tc, jg->sg, (callsite->flag_count - 1) * sizeof(MVMJitCallArg))
: NULL;

for (int i = 1; i < callsite->flag_count; i++) {
if (callsite->arg_flags[i] & MVM_CALLSITE_ARG_INT) {
args[i - 1].type = MVM_JIT_REG_VAL;
args[i - 1].v.reg = ins->operands[start + 2 + i].reg.orig;
}
else if (callsite->arg_flags[i] & MVM_CALLSITE_ARG_NUM && body->arg_types[i - 1] == MVM_NATIVECALL_ARG_DOUBLE) {
args[i - 1].type = MVM_JIT_REG_VAL_F;
args[i - 1].v.reg = ins->operands[start + 2 + i].reg.orig;
}
else {
MVM_spesh_graph_add_comment(tc, iter->graph, iter->ins,
"BAIL: op <%s> (arg type NYI)", ins->info->name);
return 0;
}
}

MVMint32 reentry_label = MVM_jit_label_after_ins(tc, jg, iter->bb, ins);
MVMJitNode *node = MVM_spesh_alloc(tc, jg->sg, sizeof(MVMJitNode));
node->type = MVM_JIT_NODE_RUNNATIVECALL;
node->u.runnativecall.args = args;
node->u.runnativecall.num_args = callsite->flag_count - 1;
node->u.runnativecall.return_type =
op == MVM_OP_sp_runnativecall_v
? MVM_RETURN_VOID
: op == MVM_OP_sp_runnativecall_i
? MVM_RETURN_INT
: op == MVM_OP_sp_runnativecall_s
? MVM_RETURN_STR
: op == MVM_OP_sp_runnativecall_n
? MVM_RETURN_NUM
: MVM_RETURN_OBJ;
node->u.runnativecall.return_register = dst;
node->u.runnativecall.entry_point = body->entry_point;
node->u.runnativecall.map = &ins->operands[2 + start];
node->u.runnativecall.reentry_label = reentry_label;
jg_append_node(jg, node);
/* append reentry label */
jg_append_label(tc, jg, reentry_label);
/* Check the entry_point after we've used it to generate the code to avoid a race
* condition where the check turned out fine, but entry_point got overwritten before we
* got to use it for generating the code. */
if (!body->entry_point) {
MVM_spesh_graph_add_comment(tc, iter->graph, iter->ins,
"BAIL: op <%s> (entry_point is NULL)", ins->info->name);
return 0;
}
break;
}
case MVM_OP_sp_dispatch_v:
case MVM_OP_sp_dispatch_i:
case MVM_OP_sp_dispatch_s:
Expand Down
12 changes: 12 additions & 0 deletions src/jit/graph.h
Expand Up @@ -210,6 +210,16 @@ struct MVMJitRunCCode {
MVMint32 reentry_label;
};

struct MVMJitRunNativeCall {
void *entry_point;
MVMJitCallArg *args;
MVMuint16 num_args;
MVMReturnType return_type;
MVMint16 return_register;
MVMSpeshOperand *map;
MVMint32 reentry_label;
};

struct MVMJitDispatch {
MVMint32 id;
MVMCallsite *callsite;
Expand Down Expand Up @@ -264,6 +274,7 @@ typedef enum {
MVM_JIT_NODE_DEOPT_CHECK,
MVM_JIT_NODE_RUNCCODE,
MVM_JIT_NODE_RUNBYTECODE,
MVM_JIT_NODE_RUNNATIVECALL,
MVM_JIT_NODE_DISPATCH,
MVM_JIT_NODE_ISTYPE,
} MVMJitNodeType;
Expand All @@ -285,6 +296,7 @@ struct MVMJitNode {
MVMJitStackSlot stack;
MVMJitRunCCode runccode;
MVMJitRunByteCode runbytecode;
MVMJitRunNativeCall runnativecall;
MVMJitDispatch dispatch;
MVMJitIsType istype;
} u;
Expand Down
1 change: 1 addition & 0 deletions src/jit/internal.h
Expand Up @@ -60,6 +60,7 @@ void MVM_jit_emit_marker(MVMThreadContext *tc, MVMJitCompiler *compiler, MVMint3
void MVM_jit_emit_deopt_check(MVMThreadContext *tc, MVMJitCompiler *compiler);
void MVM_jit_emit_runbytecode(MVMThreadContext *tc, MVMJitCompiler *compiler, MVMJitGraph *jg, MVMJitRunByteCode *runcode);
void MVM_jit_emit_runccode(MVMThreadContext *tc, MVMJitCompiler *compiler, MVMJitGraph *jg, MVMJitRunCCode *runcode);
void MVM_jit_emit_runnativecall(MVMThreadContext *tc, MVMJitCompiler *compiler, MVMJitGraph *jg, MVMJitRunNativeCall *runcode);
void MVM_jit_emit_dispatch(MVMThreadContext *tc, MVMJitCompiler *compiler, MVMJitGraph *jg, MVMJitDispatch *dispatch);
void MVM_jit_emit_istype(MVMThreadContext *tc, MVMJitCompiler *compiler, MVMJitGraph *jg, MVMJitIsType *istype);

Expand Down
37 changes: 37 additions & 0 deletions src/jit/x64/emit.dasc
Expand Up @@ -3298,6 +3298,43 @@ void MVM_jit_emit_runccode(MVMThreadContext *tc, MVMJitCompiler *compiler, MVMJi
| call FUNCTION
}

void MVM_jit_emit_runnativecall(MVMThreadContext *tc, MVMJitCompiler *compiler, MVMJitGraph *jg, MVMJitRunNativeCall *runcode) {
MVMint16 i;

/* The return address for the interpreter */
| get_cur_op TMP2;
| mov TMP5, TC->cur_frame;
| mov aword FRAME:TMP5->return_address, TMP2;

/* Setup the frame for returning to our current position */
if (sizeof(MVMReturnType) == 1) {
| mov byte FRAME:TMP5->return_type, runcode->return_type;
} else {
MVM_panic(1, "JIT: MVMReturnType has unexpected size");
}

/* The register for our return value */
if (runcode->return_type == MVM_RETURN_VOID) {
| mov aword FRAME:TMP5->return_value, NULL;
} else {
| lea TMP2, WORK[runcode->return_register];
| mov aword FRAME:TMP5->return_value, TMP2;
}

|.if WIN32;
|| emit_win64_callargs(tc, compiler, jg, runcode->args, runcode->num_args);
|.else;
|| emit_posix_callargs(tc, compiler, jg, runcode->args, runcode->num_args);
|.endif

MVMuint64 entry_point = (MVMuint64)runcode->entry_point;
| mov64 FUNCTION, entry_point;
| call FUNCTION
if (runcode->return_type != MVM_RETURN_VOID) {
| mov WORK[runcode->return_register], RV
}
}

void MVM_jit_emit_dispatch(MVMThreadContext *tc, MVMJitCompiler *compiler, MVMJitGraph *jg, MVMJitDispatch *dispatch) {
MVMint16 i;
MVMuint64 callsite = (MVMuint64)dispatch->callsite;
Expand Down
1 change: 1 addition & 0 deletions src/types.h
Expand Up @@ -267,6 +267,7 @@ typedef struct MVMJitData MVMJitData;
typedef struct MVMJitStackSlot MVMJitStackSlot;
typedef struct MVMJitRunByteCode MVMJitRunByteCode;
typedef struct MVMJitRunCCode MVMJitRunCCode;
typedef struct MVMJitRunNativeCall MVMJitRunNativeCall;
typedef struct MVMJitDispatch MVMJitDispatch;
typedef struct MVMJitIsType MVMJitIsType;
typedef struct MVMJitCode MVMJitCode;
Expand Down

0 comments on commit 9111a09

Please sign in to comment.