Skip to content

Commit

Permalink
Fix rw args of JITed calls to JITed native calls
Browse files Browse the repository at this point in the history
getarg_* are used to read (possibly modified) values back from the args buffer.
This is currently done only for native calls (after a nativeinvoke). However
the JIT does not emit any code for the corresponding arg_* ops for a
nativeinvoke. Instead the values are read directly from the WORK registers and
the arg_* ops are only used to mark those registers. This means that there's
nothing in the args buffer to read from.

So instead, turn the getarg_* ops into plain set ops and take the value from
the original WORK register.
  • Loading branch information
niner committed Sep 3, 2018
1 parent 96b88eb commit c49fc88
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/jit/x64/emit.dasc
Expand Up @@ -624,7 +624,7 @@ void MVM_jit_emit_primitive(MVMThreadContext *tc, MVMJitCompiler *compiler, MVMJ
case MVM_OP_getarg_n:
case MVM_OP_getarg_s:
case MVM_OP_getarg_i: {
MVMint32 reg = ins->operands[0].reg.orig;
MVMuint16 reg = ins->operands[0].reg.orig;
MVMuint16 idx = ins->operands[1].reg.orig;
| mov TMP1, TC->cur_frame;
| mov TMP1, FRAME:TMP1->args;
Expand Down
20 changes: 20 additions & 0 deletions src/spesh/optimize.c
Expand Up @@ -2257,6 +2257,23 @@ static void analyze_phi(MVMThreadContext *tc, MVMSpeshGraph *g, MVMSpeshIns *ins
/*fprintf(stderr, "a PHI node of %d operands had no intersecting flags\n", ins->info->num_operands);*/
}
}
/* getarg_* are used to read (possibly modified) values back from the args
* buffer. This is done only for native calls (after a nativeinvoke). However
* the JIT does not emit any code for the corresponding arg_* ops for a
* nativeinvoke. Instead the values are read directly from the WORK registers
* and the arg_* ops are only used to mark those registers. This means that
* there's nothing in the args buffer to read from. So instead, turn the
* getarg_* ops into plain set ops and take the value from the original WORK
* register. Set elimination will be able to optimize this further. */
static void optimize_getarg(MVMThreadContext *tc, MVMSpeshGraph *g, MVMSpeshBB *bb, MVMSpeshIns *ins, MVMSpeshCallInfo *arg_info) {
MVMSpeshFacts *src_facts = MVM_spesh_get_facts(tc, g, ins->operands[1]);
if (src_facts->flags & MVM_SPESH_FACT_KNOWN_VALUE) {
ins->info = MVM_op_get_op(MVM_OP_set);
ins->operands[1] = arg_info->arg_ins[src_facts->value.i]->operands[1];
MVM_spesh_usages_add_by_reg(tc, g, ins->operands[1], ins);
MVM_spesh_usages_delete(tc, g, src_facts, ins);
}
}
static void optimize_bb_switch(MVMThreadContext *tc, MVMSpeshGraph *g, MVMSpeshBB *bb,
MVMSpeshPlanned *p) {
MVMSpeshCallInfo arg_info;
Expand Down Expand Up @@ -2333,6 +2350,9 @@ static void optimize_bb_switch(MVMThreadContext *tc, MVMSpeshGraph *g, MVMSpeshB
case MVM_OP_invoke_o:
optimize_call(tc, g, bb, ins, p, 1, &arg_info);
break;
case MVM_OP_getarg_i:
optimize_getarg(tc, g, bb, ins, &arg_info);
break;
case MVM_OP_speshresolve:
if (p) {
/* Rewriting spesh plugins will insert a bunch of instructions
Expand Down

0 comments on commit c49fc88

Please sign in to comment.