Pass the original call signature too to the code handling MONO_METHOD_MONO_RGCTX_INFO...
authorZoltan Varga <vargaz@gmail.com>
Sat, 9 Feb 2013 03:59:04 +0000 (04:59 +0100)
committerZoltan Varga <vargaz@gmail.com>
Sat, 9 Feb 2013 04:19:55 +0000 (05:19 +0100)
mono/mini/aot-compiler.c
mono/mini/aot-runtime.c
mono/mini/gshared.cs
mono/mini/method-to-ir.c
mono/mini/mini-generic-sharing.c
mono/mini/mini.c
mono/mini/mini.h
mono/mini/patch-info.h

index fd87cdda4eca878774b8c0af1ffc53235dad0118..00506a0c2f0b0e92523c6774228fc1acf73ebd15 100644 (file)
@@ -4527,6 +4527,10 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint
        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 ();
index b7da7989865e8fe569c0ef9048a8fe935e983766..f98b0de6ba5c720aecb3a73a03bd254218103448 100644 (file)
@@ -668,7 +668,7 @@ decode_signature_with_target (MonoAotModule *module, MonoMethodSignature *target
 {
        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;
 
@@ -679,8 +679,8 @@ decode_signature_with_target (MonoAotModule *module, MonoMethodSignature *target
        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;
@@ -2921,6 +2921,16 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin
        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 ();
index ca2c6d04311c37c4004e9a54163792c5afb50d3c..57ad7d9d5ae699336e1fc4c14173634f044ed524 100644 (file)
@@ -935,4 +935,28 @@ public class Tests
                        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
index fafa06ef34807a0121fd334ff42eb9c1e34cf5ec..409fe87d947b9ce567d1ff6b926d9632a371b804 100644 (file)
@@ -3058,6 +3058,24 @@ emit_get_rgctx_sig (MonoCompile *cfg, int context_used,
        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:
  *
@@ -7574,6 +7592,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                         * 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);
@@ -7597,11 +7617,11 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        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)) {
@@ -8784,8 +8804,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                } 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) ||
index d3173c4539c676fed0ff441a9ff39e043a8a5586..43cf3dd342ccea6480c4a3dbbd82367b5c1665b5 100644 (file)
@@ -533,9 +533,7 @@ inflate_info (MonoRuntimeGenericContextInfoTemplate *oti, MonoGenericContext *co
        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);
@@ -558,6 +556,39 @@ inflate_info (MonoRuntimeGenericContextInfoTemplate *oti, MonoGenericContext *co
                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: {
@@ -1056,8 +1087,9 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti
        }
        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;
@@ -1065,6 +1097,11 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti
                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)
@@ -1115,19 +1152,12 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti
                 */
                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);
 
@@ -1159,7 +1189,7 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti
                         * 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); 
@@ -1169,7 +1199,7 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti
                                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);
 
index 6b820f8811351372b85dc25b0b85ddb4ceb00fd8..6d178d2aa4ce5fb8a8228276400260681e4bafe8 100644 (file)
@@ -3277,6 +3277,13 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
                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;
index 9d788873078a5d1e455251231820fae80bfb8d5a..0ea3f82188ca13a1709750b8b7efd0ef9dcac2c7 100644 (file)
@@ -1117,6 +1117,8 @@ typedef struct MonoJumpInfoImtTramp {
        int vt_offset;
 } MonoJumpInfoImtTramp;
 
+typedef struct MonoJumpInfoGSharedVtCall MonoJumpInfoGSharedVtCall;
+
 typedef struct MonoJumpInfo MonoJumpInfo;
 struct MonoJumpInfo {
        MonoJumpInfo *next;
@@ -1146,6 +1148,7 @@ struct MonoJumpInfo {
                MonoJumpInfoBBTable *table;
                MonoJumpInfoRgctxEntry *rgctx_entry;
                MonoJumpInfoImtTramp *imt_tramp;
+               MonoJumpInfoGSharedVtCall *gsharedvt;
                MonoMethodSignature *sig;
        } data;
 };
@@ -1158,6 +1161,14 @@ struct MonoJumpInfoRgctxEntry {
        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,
index 8cd3f4120885f63855be38d71e0802960d5230be..53800be31bb64b78d7635fdb8f7c5e931ae1325d 100644 (file)
@@ -43,4 +43,5 @@ PATCH_INFO(LLVM_IMT_TRAMPOLINE, "llvm_imt_trampoline")
 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")