[jit] Add an inline version of the rgctx fetch trampolines, not yet used.
authorZoltan Varga <vargaz@gmail.com>
Mon, 15 Jun 2015 22:59:41 +0000 (18:59 -0400)
committerZoltan Varga <vargaz@gmail.com>
Mon, 15 Jun 2015 22:59:41 +0000 (18:59 -0400)
mono/mini/ir-emit.h
mono/mini/method-to-ir.c
mono/mini/mini-generic-sharing.c
mono/mini/mini-runtime.c
mono/mini/mini.h

index fe05ecca2d36a5569abfd30b622b71bf3868d86b..eeea8d938145942265353fe04d3a117800ff2d37 100644 (file)
@@ -754,8 +754,8 @@ handle_gsharedvt_ldaddr (MonoCompile *cfg)
                (b)->real_offset = cfg->real_offset;    \
        } while (0)
 
-/* Emit a one-way conditional branch */
-/* 
+/*
+ * Emit a one-way conditional branch and start a new bblock.
  * The inst_false_bb field of the cond branch will not be set, the JIT code should be
  * prepared to deal with this.
  */
index f74d90af7814c7422548f69649ea7a52ef3ba64d..f4d972781e6dc0703e472326d4001909c9008ba2 100644 (file)
@@ -3368,6 +3368,12 @@ mini_emit_initobj (MonoCompile *cfg, MonoInst *dest, const guchar *ip, MonoClass
        }
 }
 
+/*
+ * emit_get_rgctx:
+ *
+ *   Emit IR to return either the this pointer for instance method,
+ * or the mrgctx for static methods.
+ */
 static MonoInst*
 emit_get_rgctx (MonoCompile *cfg, MonoMethod *method, int context_used)
 {
@@ -3432,10 +3438,100 @@ mono_patch_info_rgctx_entry_new (MonoMemPool *mp, MonoMethod *method, gboolean i
        return res;
 }
 
+/*
+ * emit_rgctx_fetch:
+ *
+ *   Emit IR to load the value of the rgctx entry ENTRY from the rgctx
+ * given by RGCTX.
+ */
 static inline MonoInst*
 emit_rgctx_fetch (MonoCompile *cfg, MonoInst *rgctx, MonoJumpInfoRgctxEntry *entry)
 {
+       /* Inline version, not currently used */
+#if 0
+       int i, slot, depth, index, rgctx_reg, val_reg, res_reg;
+       gboolean mrgctx;
+       MonoBasicBlock *is_null_bb, *end_bb;
+       MonoInst *res, *ins, *call;
+
+       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 / sizeof (gpointer);
+       for (depth = 0; ; ++depth) {
+               int size = mono_class_rgctx_get_array_size (depth, mrgctx);
+
+               if (index < size - 1)
+                       break;
+               index -= size - 1;
+       }
+
+       NEW_BBLOCK (cfg, end_bb);
+       NEW_BBLOCK (cfg, is_null_bb);
+
+       if (mrgctx) {
+               rgctx_reg = rgctx->dreg;
+       } else {
+               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.
+               NEW_BBLOCK (cfg, is_null_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);
+       }
+
+       for (i = 0; i < depth; ++i) {
+               int array_reg = alloc_preg (cfg);
+
+               /* 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);
+       }
+
+       /* fetch slot */
+       val_reg = alloc_preg (cfg);
+       MONO_EMIT_NEW_LOAD_MEMBASE (cfg, val_reg, rgctx_reg, (index + 1) * sizeof (gpointer));
+       /* 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);
+
+       /* Fastpath */
+       res_reg = alloc_preg (cfg);
+       MONO_INST_NEW (cfg, res, OP_MOVE);
+       res->dreg = res_reg;
+       res->sreg1 = val_reg;
+       MONO_ADD_INS (cfg->cbb, res);
+       MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
+
+       /* Slowpath */
+       MONO_START_BB (cfg, is_null_bb);
+       // FIXME: This should use a jit icall
+       call = mono_emit_abs_call (cfg, MONO_PATCH_INFO_RGCTX_FETCH, entry, helper_sig_rgctx_lazy_fetch_trampoline, &rgctx);
+       MONO_INST_NEW (cfg, ins, OP_MOVE);
+       ins->dreg = res_reg;
+       ins->sreg1 = call->dreg;
+       MONO_ADD_INS (cfg->cbb, ins);
+
+       MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
+
+       MONO_START_BB (cfg, end_bb);
+
+       return res;
+#else
        return mono_emit_abs_call (cfg, MONO_PATCH_INFO_RGCTX_FETCH, entry, helper_sig_rgctx_lazy_fetch_trampoline, &rgctx);
+#endif
 }
 
 static MonoInst*
index 6e04ca2e22c6c314c4f5882b33e85401af1dcae0..f6ec4979abd7a5418850d3512ed17b26ccda3024 100644 (file)
@@ -3084,6 +3084,68 @@ mini_get_shared_method (MonoMethod *method)
        return mini_get_shared_method_full (method, FALSE, FALSE);
 }
 
+int
+mini_get_rgctx_entry_slot (MonoJumpInfoRgctxEntry *entry)
+{
+       guint32 slot = -1;
+
+       switch (entry->data->type) {
+       case MONO_PATCH_INFO_CLASS:
+               slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, &entry->data->data.klass->byval_arg, entry->info_type, mono_method_get_context (entry->method));
+               break;
+       case MONO_PATCH_INFO_METHOD:
+       case MONO_PATCH_INFO_METHODCONST:
+               slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, entry->data->data.method, entry->info_type, mono_method_get_context (entry->method));
+               break;
+       case MONO_PATCH_INFO_FIELD:
+               slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, entry->data->data.field, entry->info_type, mono_method_get_context (entry->method));
+               break;
+       case MONO_PATCH_INFO_SIGNATURE:
+               slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, entry->data->data.sig, entry->info_type, mono_method_get_context (entry->method));
+               break;
+       case MONO_PATCH_INFO_GSHAREDVT_CALL: {
+               MonoJumpInfoGSharedVtCall *call_info = g_malloc0 (sizeof (MonoJumpInfoGSharedVtCall)); //mono_domain_alloc0 (domain, sizeof (MonoJumpInfoGSharedVtCall));
+
+               memcpy (call_info, entry->data->data.gsharedvt, sizeof (MonoJumpInfoGSharedVtCall));
+               slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, call_info, entry->info_type, mono_method_get_context (entry->method));
+               break;
+       }
+       case MONO_PATCH_INFO_GSHAREDVT_METHOD: {
+               MonoGSharedVtMethodInfo *info;
+               MonoGSharedVtMethodInfo *oinfo = entry->data->data.gsharedvt_method;
+               int i;
+
+               /* Make a copy into the domain mempool */
+               info = g_malloc0 (sizeof (MonoGSharedVtMethodInfo)); //mono_domain_alloc0 (domain, sizeof (MonoGSharedVtMethodInfo));
+               info->method = oinfo->method;
+               info->num_entries = oinfo->num_entries;
+               info->entries = g_malloc0 (sizeof (MonoRuntimeGenericContextInfoTemplate) * info->num_entries);
+               for (i = 0; i < oinfo->num_entries; ++i) {
+                       MonoRuntimeGenericContextInfoTemplate *otemplate = &oinfo->entries [i];
+                       MonoRuntimeGenericContextInfoTemplate *template = &info->entries [i];
+
+                       memcpy (template, otemplate, sizeof (MonoRuntimeGenericContextInfoTemplate));
+               }
+               slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, info, entry->info_type, mono_method_get_context (entry->method));
+               break;
+       }
+       case MONO_PATCH_INFO_VIRT_METHOD: {
+               MonoJumpInfoVirtMethod *info;
+               MonoJumpInfoVirtMethod *oinfo = entry->data->data.virt_method;
+
+               info = g_malloc0 (sizeof (MonoJumpInfoVirtMethod));
+               memcpy (info, oinfo, sizeof (MonoJumpInfoVirtMethod));
+               slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, info, entry->info_type, mono_method_get_context (entry->method));
+               break;
+       }
+       default:
+               g_assert_not_reached ();
+               break;
+       }
+
+       return slot;
+}
+
 #if defined(ENABLE_GSHAREDVT)
 
 #include "../../../mono-extensions/mono/mini/mini-generic-sharing-gsharedvt.c"
index 33a055fd76ee64f856bcbfcf74de199604fea534..8fee20af405154e02f2a33d0bfa316ee65aa44e1 100644 (file)
@@ -1591,62 +1591,7 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
        case MONO_PATCH_INFO_NONE:
                break;
        case MONO_PATCH_INFO_RGCTX_FETCH: {
-               MonoJumpInfoRgctxEntry *entry = patch_info->data.rgctx_entry;
-               guint32 slot = -1;
-
-               switch (entry->data->type) {
-               case MONO_PATCH_INFO_CLASS:
-                       slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, &entry->data->data.klass->byval_arg, entry->info_type, mono_method_get_context (entry->method));
-                       break;
-               case MONO_PATCH_INFO_METHOD:
-               case MONO_PATCH_INFO_METHODCONST:
-                       slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, entry->data->data.method, entry->info_type, mono_method_get_context (entry->method));
-                       break;
-               case MONO_PATCH_INFO_FIELD:
-                       slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, entry->data->data.field, entry->info_type, mono_method_get_context (entry->method));
-                       break;
-               case MONO_PATCH_INFO_SIGNATURE:
-                       slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, entry->data->data.sig, entry->info_type, mono_method_get_context (entry->method));
-                       break;
-               case MONO_PATCH_INFO_GSHAREDVT_CALL: {
-                       MonoJumpInfoGSharedVtCall *call_info = g_malloc0 (sizeof (MonoJumpInfoGSharedVtCall)); //mono_domain_alloc0 (domain, sizeof (MonoJumpInfoGSharedVtCall));
-
-                       memcpy (call_info, entry->data->data.gsharedvt, sizeof (MonoJumpInfoGSharedVtCall));
-                       slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, call_info, entry->info_type, mono_method_get_context (entry->method));
-                       break;
-               }
-               case MONO_PATCH_INFO_GSHAREDVT_METHOD: {
-                       MonoGSharedVtMethodInfo *info;
-                       MonoGSharedVtMethodInfo *oinfo = entry->data->data.gsharedvt_method;
-                       int i;
-
-                       /* Make a copy into the domain mempool */
-                       info = g_malloc0 (sizeof (MonoGSharedVtMethodInfo)); //mono_domain_alloc0 (domain, sizeof (MonoGSharedVtMethodInfo));
-                       info->method = oinfo->method;
-                       info->num_entries = oinfo->num_entries;
-                       info->entries = g_malloc0 (sizeof (MonoRuntimeGenericContextInfoTemplate) * info->num_entries);
-                       for (i = 0; i < oinfo->num_entries; ++i) {
-                               MonoRuntimeGenericContextInfoTemplate *otemplate = &oinfo->entries [i];
-                               MonoRuntimeGenericContextInfoTemplate *template = &info->entries [i];
-
-                               memcpy (template, otemplate, sizeof (MonoRuntimeGenericContextInfoTemplate));
-                       }
-                       slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, info, entry->info_type, mono_method_get_context (entry->method));
-                       break;
-               }
-               case MONO_PATCH_INFO_VIRT_METHOD: {
-                       MonoJumpInfoVirtMethod *info;
-                       MonoJumpInfoVirtMethod *oinfo = entry->data->data.virt_method;
-
-                       info = g_malloc0 (sizeof (MonoJumpInfoVirtMethod));
-                       memcpy (info, oinfo, sizeof (MonoJumpInfoVirtMethod));
-                       slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, info, entry->info_type, mono_method_get_context (entry->method));
-                       break;
-               }
-               default:
-                       g_assert_not_reached ();
-                       break;
-               }
+               int slot = mini_get_rgctx_entry_slot (patch_info->data.rgctx_entry);
 
                target = mono_create_rgctx_lazy_fetch_trampoline (slot);
                break;
index 7137143a0040c09e15c46702ef8e8e5555608275..31057fe21b0ce6927f4aa4de6e5922f6f3c357f8 100644 (file)
@@ -2837,6 +2837,7 @@ MonoType* mini_type_get_underlying_type (MonoGenericSharingContext *gsctx, MonoT
 MonoMethod* mini_get_shared_method (MonoMethod *method);
 MonoMethod* mini_get_shared_method_to_register (MonoMethod *method);
 MonoMethod* mini_get_shared_method_full (MonoMethod *method, gboolean all_vt, gboolean is_gsharedvt);
+int mini_get_rgctx_entry_slot (MonoJumpInfoRgctxEntry *entry);
 
 int mini_type_stack_size (MonoGenericSharingContext *gsctx, MonoType *t, int *align);
 int mini_type_stack_size_full (MonoGenericSharingContext *gsctx, MonoType *t, guint32 *align, gboolean pinvoke);