case MONO_PATCH_INFO_SIGNATURE:
encode_signature (acfg, (MonoMethodSignature*)patch_info->data.target, p, &p);
break;
+ case MONO_PATCH_INFO_GSHAREDVT_CALL:
+ encode_signature (acfg, (MonoMethodSignature*)patch_info->data.gsharedvt->sig, p, &p);
+ encode_method_ref (acfg, patch_info->data.gsharedvt->method, p, &p);
+ break;
default:
g_warning ("unable to handle jump info %d", patch_info->type);
g_assert_not_reached ();
{
MonoMethodSignature *sig;
guint32 flags;
- int i, param_count, call_conv;
+ int i, param_count, call_conv, gen_param_count = 0;
guint8 *p = buf;
gboolean hasthis, explicit_this, has_gen_params;
explicit_this = (flags & 0x40) != 0;
call_conv = flags & 0x0F;
- g_assert (!has_gen_params);
-
+ if (has_gen_params)
+ gen_param_count = decode_value (p, &p);
param_count = decode_value (p, &p);
if (target && param_count != target->param_count)
return NULL;
case MONO_PATCH_INFO_SIGNATURE:
ji->data.target = decode_signature (aot_module, p, &p);
break;
+ case MONO_PATCH_INFO_GSHAREDVT_CALL: {
+ MonoJumpInfoGSharedVtCall *info = g_new0 (MonoJumpInfoGSharedVtCall, 1);
+ info->sig = decode_signature (aot_module, p, &p);
+ g_assert (info->sig);
+ info->method = decode_resolve_method_ref (aot_module, p, &p);
+ g_assert (info->method);
+
+ ji->data.target = info;
+ break;
+ }
default:
g_warning ("unhandled type %d", ji->type);
g_assert_not_reached ();
return 1;
return 0;
}
+
+ interface BIFace {
+ object AMethod ();
+ }
+
+ class Base<TAbsolute, T2> : BIFace {
+
+ public TAbsolute Clock { get; set; }
+
+ public virtual object AMethod () {
+ return Clock;
+ }
+ }
+
+ class BClass : Base<long, long> {
+ }
+
+ public static int test_0_regress_1 () {
+ BIFace c = new BClass ();
+ object o = c.AMethod ();
+ if (!(o is long) || ((long)o != 0))
+ return 1;
+ return 0;
+ }
}
\ No newline at end of file
return emit_rgctx_fetch (cfg, rgctx, entry);
}
+static MonoInst*
+emit_get_rgctx_gsharedvt_call (MonoCompile *cfg, int context_used,
+ MonoMethodSignature *sig, MonoMethod *cmethod, MonoRgctxInfoType rgctx_type)
+{
+ MonoJumpInfoGSharedVtCall *call_info;
+ MonoJumpInfoRgctxEntry *entry;
+ MonoInst *rgctx;
+
+ call_info = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoJumpInfoGSharedVtCall));
+ call_info->sig = sig;
+ call_info->method = cmethod;
+
+ entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->current_method, context_used & MONO_GENERIC_CONTEXT_USED_METHOD, MONO_PATCH_INFO_GSHAREDVT_CALL, call_info, rgctx_type);
+ rgctx = emit_get_rgctx (cfg, cfg->current_method, context_used);
+
+ return emit_rgctx_fetch (cfg, rgctx, entry);
+}
+
/*
* emit_get_rgctx_method:
*
* Making generic calls out of gsharedvt methods.
*/
if (cmethod && cfg->gsharedvt && mini_is_gsharedvt_signature (cfg, fsig)) {
+ MonoRgctxInfoType info_type;
+
if (virtual) {
//if (cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE)
//GSHAREDVT_FAILURE (*ip);
GSHAREDVT_FAILURE (*ip);
if (virtual && (cmethod->flags & METHOD_ATTRIBUTE_VIRTUAL))
- addr = emit_get_rgctx_method (cfg, context_used,
- cmethod, MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE_VIRT);
+ info_type = MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE_VIRT;
else
- addr = emit_get_rgctx_method (cfg, context_used,
- cmethod, MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE);
+ info_type = MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE;
+ addr = emit_get_rgctx_gsharedvt_call (cfg, context_used, fsig, cmethod, info_type);
+
ins = (MonoInst*)mono_emit_calli (cfg, fsig, sp, addr, imt_arg, vtable_arg);
goto call_end;
} else if (calli && cfg->gsharedvt && mini_is_gsharedvt_signature (cfg, fsig)) {
} else if (cfg->gsharedvt && mini_is_gsharedvt_signature (cfg, fsig)) {
MonoInst *addr;
- addr = emit_get_rgctx_method (cfg, context_used,
- cmethod, MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE);
+ addr = emit_get_rgctx_gsharedvt_call (cfg, context_used, fsig, cmethod, MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE);
mono_emit_calli (cfg, fsig, sp, addr, NULL, vtable_arg);
} else if (context_used &&
(!mono_method_is_generic_sharable_impl (cmethod, TRUE) ||
case MONO_RGCTX_INFO_METHOD_RGCTX:
case MONO_RGCTX_INFO_METHOD_CONTEXT:
case MONO_RGCTX_INFO_REMOTING_INVOKE_WITH_CHECK:
- case MONO_RGCTX_INFO_METHOD_DELEGATE_CODE:
- case MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE:
- case MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE_VIRT: {
+ case MONO_RGCTX_INFO_METHOD_DELEGATE_CODE: {
MonoMethod *method = data;
MonoMethod *inflated_method;
MonoType *inflated_type = mono_class_inflate_generic_type (&method->klass->byval_arg, context);
g_assert (inflated_method->klass == inflated_class);
return inflated_method;
}
+ case MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE:
+ case MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE_VIRT: {
+ MonoJumpInfoGSharedVtCall *info = data;
+ MonoMethod *method = info->method;
+ MonoMethod *inflated_method;
+ MonoType *inflated_type = mono_class_inflate_generic_type (&method->klass->byval_arg, context);
+ MonoClass *inflated_class = mono_class_from_mono_type (inflated_type);
+ MonoJumpInfoGSharedVtCall *res;
+
+ // FIXME:
+ res = g_new0 (MonoJumpInfoGSharedVtCall, 1);
+ /* Keep the original signature */
+ res->sig = info->sig;
+
+ mono_metadata_free_type (inflated_type);
+
+ mono_class_init (inflated_class);
+
+ g_assert (!method->wrapper_type);
+
+ if (inflated_class->byval_arg.type == MONO_TYPE_ARRAY ||
+ inflated_class->byval_arg.type == MONO_TYPE_SZARRAY) {
+ inflated_method = mono_method_search_in_array_class (inflated_class,
+ method->name, method->signature);
+ } else {
+ inflated_method = mono_class_inflate_generic_method (method, context);
+ }
+ mono_class_init (inflated_method->klass);
+ g_assert (inflated_method->klass == inflated_class);
+ res->method = inflated_method;
+
+ return res;
+ }
case MONO_RGCTX_INFO_CLASS_FIELD:
case MONO_RGCTX_INFO_FIELD_OFFSET: {
}
case MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE:
case MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE_VIRT: {
- MonoMethod *caller_method = oti->data;
- MonoMethod *method = data;
+ MonoJumpInfoGSharedVtCall *call_info = data;
+ MonoMethodSignature *call_sig;
+ MonoMethod *method;
gpointer addr;
MonoJitInfo *caller_ji, *callee_ji;
gboolean virtual = oti->info_type == MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE_VIRT;
MonoGenericJitInfo *gji, *callee_gji = NULL;
gboolean callee_gsharedvt;
+ /* This is the original generic signature used by the caller */
+ call_sig = call_info->sig;
+ /* This is the instantiated method which is called */
+ method = call_info->method;
+
g_assert (method->is_inflated);
if (!virtual)
*/
if (virtual || !callee_gsharedvt) {
gpointer info;
- MonoMethod *gm;
MonoMethodSignature *sig, *gsig;
g_assert (method->is_inflated);
- /* Have to pass TRUE for is_gshared since METHOD might not be gsharedvt but we need its shared version */
- gm = mini_get_shared_method_full (method, FALSE, TRUE);
- g_assert (gm != method);
-
- gm = caller_method;
-
sig = mono_method_signature (method);
- gsig = mono_method_signature (gm);
+ gsig = call_sig;
info = mono_arch_get_gsharedvt_call_info (addr, sig, gsig, gji->generic_sharing_context, FALSE, vcall_offset, FALSE);
* FIXME: Optimize this.
*/
- if (caller_method == method) {
+ if (call_sig == mono_method_signature (method)) {
} else {
sig = mono_method_signature (method);
gsig = mono_method_signature (callee_ji->method);
addr = add_gsharedvt_in_wrapper (info);
sig = mono_method_signature (method);
- gsig = mono_method_signature (caller_method);
+ gsig = call_sig;
info = mono_arch_get_gsharedvt_call_info (addr, sig, gsig, gji->generic_sharing_context, FALSE, -1, FALSE);
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 = 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;
+ }
default:
g_assert_not_reached ();
break;
int vt_offset;
} MonoJumpInfoImtTramp;
+typedef struct MonoJumpInfoGSharedVtCall MonoJumpInfoGSharedVtCall;
+
typedef struct MonoJumpInfo MonoJumpInfo;
struct MonoJumpInfo {
MonoJumpInfo *next;
MonoJumpInfoBBTable *table;
MonoJumpInfoRgctxEntry *rgctx_entry;
MonoJumpInfoImtTramp *imt_tramp;
+ MonoJumpInfoGSharedVtCall *gsharedvt;
MonoMethodSignature *sig;
} data;
};
MonoRgctxInfoType info_type;
};
+/* Contains information about a gsharedvt call */
+struct MonoJumpInfoGSharedVtCall {
+ /* The original signature of the call */
+ MonoMethodSignature *sig;
+ /* The method which is called */
+ MonoMethod *method;
+};
+
typedef enum {
MONO_TRAMPOLINE_JIT,
MONO_TRAMPOLINE_JUMP,
PATCH_INFO(GC_CARD_TABLE_ADDR, "gc_card_table_addr")
PATCH_INFO(CASTCLASS_CACHE, "castclass_cache")
PATCH_INFO(SIGNATURE, "signature")
+PATCH_INFO(GSHAREDVT_CALL, "gsharedvt_call")
PATCH_INFO(NONE, "none")