[mono][aot] Implement fetching from the rgctx in llvmonly mode using inline code...
authorZoltan Varga <vargaz@gmail.com>
Thu, 1 Jul 2021 15:23:10 +0000 (11:23 -0400)
committerGitHub <noreply@github.com>
Thu, 1 Jul 2021 15:23:10 +0000 (11:23 -0400)
calling mono_fill_class_rgctx ().
Also bump the initial size of the rgctx to 16 to allow loading more entries without doing
a nested lookup.

src/mono/mono/mini/jit-icalls.c
src/mono/mono/mini/method-to-ir.c
src/mono/mono/mini/mini-generic-sharing.c
src/mono/mono/mini/mini.c
src/mono/mono/mini/mini.h

index 0bc127c..189eae7 100644 (file)
@@ -1512,10 +1512,6 @@ mono_fill_class_rgctx (MonoVTable *vtable, int index)
        ERROR_DECL (error);
        gpointer res;
 
-       /*
-        * This is perf critical.
-        * fill_runtime_generic_context () contains a fallpath.
-        */
        res = mono_class_fill_runtime_generic_context (vtable, index, error);
        if (!is_ok (error)) {
                mono_error_set_pending_exception (error);
index d011f3b..9f1df4e 100644 (file)
@@ -2583,106 +2583,74 @@ emit_rgctx_fetch_inline (MonoCompile *cfg, MonoInst *rgctx, MonoJumpInfoRgctxEnt
 {
        MonoInst *call;
 
-       // FIXME: No fastpath since the slot is not a compile time constant
-       MonoInst *args [2] = { rgctx };
-       EMIT_NEW_AOTCONST (cfg, args [1], MONO_PATCH_INFO_RGCTX_SLOT_INDEX, entry);
-       if (entry->in_mrgctx)
-               call = mono_emit_jit_icall (cfg, mono_fill_method_rgctx, args);
-       else
-               call = mono_emit_jit_icall (cfg, mono_fill_class_rgctx, args);
-       return call;
-#if 0
-       /*
-        * FIXME: This can be called during decompose, which is a problem since it creates
-        * new bblocks.
-        * Also, the fastpath doesn't work since the slot number is dynamically allocated.
-        */
-       int i, slot, depth, index, rgctx_reg, val_reg, res_reg;
-       gboolean mrgctx;
-       MonoBasicBlock *is_null_bb, *end_bb;
-       MonoInst *res, *ins, *call;
-       MonoInst *args[16];
-
-       slot = mini_get_rgctx_entry_slot (entry);
-
-       mrgctx = MONO_RGCTX_SLOT_IS_MRGCTX (slot);
-       index = MONO_RGCTX_SLOT_INDEX (slot);
-       if (mrgctx)
-               index += MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT / TARGET_SIZEOF_VOID_P;
-       for (depth = 0; ; ++depth) {
-               int size = mono_class_rgctx_get_array_size (depth, mrgctx);
-
-               if (index < size - 1)
-                       break;
-               index -= size - 1;
+       MonoInst *slot_ins;
+       EMIT_NEW_AOTCONST (cfg, slot_ins, MONO_PATCH_INFO_RGCTX_SLOT_INDEX, entry);
+
+       // Can't add basic blocks during decompose/interp entry mode etc.
+       // FIXME: Add a fastpath for in_mrgctx
+       if (cfg->after_method_to_ir || cfg->gsharedvt || cfg->interp_entry_only || entry->in_mrgctx) {
+               MonoInst *args [2] = { rgctx, slot_ins };
+               if (entry->in_mrgctx)
+                       call = mono_emit_jit_icall (cfg, mono_fill_method_rgctx, args);
+               else
+                       call = mono_emit_jit_icall (cfg, mono_fill_class_rgctx, args);
+               return call;
        }
 
-       NEW_BBLOCK (cfg, end_bb);
-       NEW_BBLOCK (cfg, is_null_bb);
+       MonoBasicBlock *slowpath_bb, *end_bb;
+       MonoInst *ins, *res;
+       int rgctx_reg, res_reg;
 
-       if (mrgctx) {
-               rgctx_reg = rgctx->dreg;
-       } else {
-               rgctx_reg = alloc_preg (cfg);
+       /*
+        * rgctx = vtable->runtime_generic_context;
+        * if (rgctx) {
+        *    val = rgctx [slot + 1];
+        *    if (val)
+        *       return val;
+        * }
+        * <slowpath>
+        */
+       NEW_BBLOCK (cfg, end_bb);
+       NEW_BBLOCK (cfg, slowpath_bb);
 
-               MONO_EMIT_NEW_LOAD_MEMBASE (cfg, rgctx_reg, rgctx->dreg, MONO_STRUCT_OFFSET (MonoVTable, runtime_generic_context));
-               // FIXME: Avoid this check by allocating the table when the vtable is created etc.
-               NEW_BBLOCK (cfg, is_null_bb);
+       rgctx_reg = alloc_preg (cfg);
+       MONO_EMIT_NEW_LOAD_MEMBASE (cfg, rgctx_reg, rgctx->dreg, MONO_STRUCT_OFFSET (MonoVTable, runtime_generic_context));
+       // FIXME: Avoid this check by allocating the table when the vtable is created etc.
+       MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, rgctx_reg, 0);
+       MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, slowpath_bb);
 
-               MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, rgctx_reg, 0);
-               MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, is_null_bb);
-       }
+       int table_size = mono_class_rgctx_get_array_size (0, FALSE);
+       MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, slot_ins->dreg, table_size - 1);
+       MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBGE, slowpath_bb);
 
-       for (i = 0; i < depth; ++i) {
-               int array_reg = alloc_preg (cfg);
+       int shifted_slot_reg = alloc_ireg (cfg);
+       EMIT_NEW_BIALU_IMM (cfg, ins, OP_ISHL_IMM, shifted_slot_reg, slot_ins->dreg, TARGET_SIZEOF_VOID_P == 8 ? 3 : 2);
 
-               /* load ptr to next array */
-               if (mrgctx && i == 0)
-                       MONO_EMIT_NEW_LOAD_MEMBASE (cfg, array_reg, rgctx_reg, MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT);
-               else
-                       MONO_EMIT_NEW_LOAD_MEMBASE (cfg, array_reg, rgctx_reg, 0);
-               rgctx_reg = array_reg;
-               /* is the ptr null? */
-               MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, rgctx_reg, 0);
-               /* if yes, jump to actual trampoline */
-               MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, is_null_bb);
-       }
+       int addr_reg = alloc_preg (cfg);
+       EMIT_NEW_UNALU (cfg, ins, OP_MOVE, addr_reg, rgctx_reg);
+       EMIT_NEW_BIALU (cfg, ins, OP_PADD, addr_reg, addr_reg, shifted_slot_reg);
+       int val_reg = alloc_preg (cfg);
+       MONO_EMIT_NEW_LOAD_MEMBASE (cfg, val_reg, addr_reg, TARGET_SIZEOF_VOID_P);
 
-       /* fetch slot */
-       val_reg = alloc_preg (cfg);
-       MONO_EMIT_NEW_LOAD_MEMBASE (cfg, val_reg, rgctx_reg, (index + 1) * TARGET_SIZEOF_VOID_P);
-       /* is the slot null? */
        MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, val_reg, 0);
-       /* if yes, jump to actual trampoline */
-       MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, is_null_bb);
+       MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, slowpath_bb);
 
-       /* Fastpath */
        res_reg = alloc_preg (cfg);
-       MONO_INST_NEW (cfg, ins, OP_MOVE);
-       ins->dreg = res_reg;
-       ins->sreg1 = val_reg;
-       MONO_ADD_INS (cfg->cbb, ins);
+       EMIT_NEW_UNALU (cfg, ins, OP_MOVE, res_reg, val_reg);
        res = ins;
        MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
 
-       /* Slowpath */
-       MONO_START_BB (cfg, is_null_bb);
-       args [0] = rgctx;
-       EMIT_NEW_ICONST (cfg, args [1], index);
-       if (mrgctx)
-               call = mono_emit_jit_icall (cfg, mono_fill_method_rgctx, args);
-       else
-               call = mono_emit_jit_icall (cfg, mono_fill_class_rgctx, args);
-       MONO_INST_NEW (cfg, ins, OP_MOVE);
-       ins->dreg = res_reg;
-       ins->sreg1 = call->dreg;
-       MONO_ADD_INS (cfg->cbb, ins);
+       MONO_START_BB (cfg, slowpath_bb);
+       slowpath_bb->out_of_line = TRUE;
+
+       MonoInst *args[2] = { rgctx, slot_ins };
+       call = mono_emit_jit_icall (cfg, mono_fill_class_rgctx, args);
+       EMIT_NEW_UNALU (cfg, ins, OP_MOVE, res_reg, call->dreg);
        MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
 
        MONO_START_BB (cfg, end_bb);
 
        return res;
-#endif
 }
 
 /*
index 7cf7389..a596cf3 100644 (file)
@@ -2877,7 +2877,7 @@ lookup_or_register_info (MonoMemoryManager *mem_manager, MonoClass *klass, MonoM
 static inline int
 class_rgctx_array_size (int n)
 {
-       return 4 << n;
+       return 16 << n;
 }
 
 static inline int
index ae87e44..72a5bf4 100644 (file)
@@ -3543,6 +3543,8 @@ mini_method_compile (MonoMethod *method, guint32 opts, JitFlags flags, int parts
                cfg->opt &= ~MONO_OPT_BRANCH;
        }
 
+       cfg->after_method_to_ir = TRUE;
+
        /* todo: remove code when we have verified that the liveness for try/catch blocks
         * works perfectly 
         */
index c865bf5..2afc62d 100644 (file)
@@ -1479,6 +1479,7 @@ typedef struct {
        guint            self_init : 1;
        guint            code_exec_only : 1;
        guint            interp_entry_only : 1;
+       guint            after_method_to_ir : 1;
        guint8           uses_simd_intrinsics;
        int              r4_stack_type;
        gpointer         debug_info;