From 16b9b79e55b04a3267104ab9bf5025d2debf9fd3 Mon Sep 17 00:00:00 2001 From: Timo Paulssen Date: Wed, 26 Dec 2018 05:03:32 +0100 Subject: [PATCH] JIT Devirtualize atpos_o To A Smaller Function when the jit already knows the type of VMArray, especially the slot kind, it can skip not only the big switch/case for "which slot type do we have?" but also the check for slot and register mismatch that would throw an exception at run time. --- src/6model/reprs/VMArray.c | 31 +++++++++++++++++++++++++++++++ src/6model/reprs/VMArray.h | 2 ++ src/jit/graph.c | 17 +++++++++++++++++ 3 files changed, 50 insertions(+) diff --git a/src/6model/reprs/VMArray.c b/src/6model/reprs/VMArray.c index 8aaf3fc1b8..94f0da8ee4 100644 --- a/src/6model/reprs/VMArray.c +++ b/src/6model/reprs/VMArray.c @@ -1404,6 +1404,37 @@ static void describe_refs (MVMThreadContext *tc, MVMHeapSnapshotState *ss, MVMST } } +MVMObject *vmarray_direct_atpos_o_to_o(MVMThreadContext *tc, MVMObject *obj, MVMint64 index) { + MVMArrayBody *body = (MVMArrayBody *)OBJECT_BODY(obj); + MVMObject *found; + + if (index < 0) { + index += body->elems; + if (index < 0) + MVM_exception_throw_adhoc(tc, "MVMArray: Index out of bounds"); + } + + if (index >= body->elems) + return tc->instance->VMNull; + + found = body->slots.o[body->start + index]; + return found ? found : tc->instance->VMNull; +} + +void *MVM_VMArray_devirtualize_ins_for_jit(MVMThreadContext *tc, MVMSTable *st, MVMSpeshIns *ins) { + switch (ins->info->opcode) { + case MVM_OP_atpos_o: + if (((MVMArrayREPRData *)st->REPR_data)->slot_type != MVM_ARRAY_OBJ) { + return NULL; + } + break; + default: + return NULL; + } + + return vmarray_direct_atpos_o_to_o; +} + /* Initializes the representation. */ const MVMREPROps * MVMArray_initialize(MVMThreadContext *tc) { return &VMArray_this_repr; diff --git a/src/6model/reprs/VMArray.h b/src/6model/reprs/VMArray.h index 7f6dd175ab..43dc702830 100644 --- a/src/6model/reprs/VMArray.h +++ b/src/6model/reprs/VMArray.h @@ -76,3 +76,5 @@ struct MVMArrayREPRData { MVMObject *elem_type; }; void MVM_VMArray_at_pos(MVMThreadContext *tc, MVMSTable *st, MVMObject *root, void *data, MVMint64 index, MVMRegister *value, MVMuint16 kind); + +void *MVM_VMArray_devirtualize_ins_for_jit(MVMThreadContext *tc, MVMSTable *st, MVMSpeshIns *ins); diff --git a/src/jit/graph.c b/src/jit/graph.c index 1e18d9dac7..89ba1f6c83 100644 --- a/src/jit/graph.c +++ b/src/jit/graph.c @@ -865,6 +865,23 @@ static MVMint32 consume_reprop(MVMThreadContext *tc, MVMJitGraph *jg, ? (void *)((MVMObject*)type_facts->type)->st->REPR->ass_funcs.at_key : (void *)((MVMObject*)type_facts->type)->st->REPR->pos_funcs.at_pos; + /* Can attempt to double-devirt for VMArray */ + if (alternative == 0) { + if (REPR(type_facts->type)->ID == MVM_REPR_ID_VMArray) { + void *alternative_function = MVM_VMArray_devirtualize_ins_for_jit(tc, STABLE(type_facts->type), ins); + + if (alternative_function != NULL) { + MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, MVM_JIT_INTERP_TC }, + { MVM_JIT_REG_VAL, invocant }, + { MVM_JIT_REG_VAL, value } }; + jg_append_call_c(tc, jg, alternative_function, 3, args, MVM_JIT_RV_PTR, dst); + MVM_spesh_graph_add_comment(tc, iter->graph, ins, "JIT: double-devirtualized");; + return 1; + } + } + } + + { MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, MVM_JIT_INTERP_TC }, { MVM_JIT_REG_STABLE, invocant }, { MVM_JIT_REG_VAL, invocant },