(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.
*/
}
}
+/*
+ * 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)
{
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*
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"
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;
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);