Unify the different gsharedvt constrained call jit icalls into one.
authorZoltan Varga <vargaz@gmail.com>
Wed, 24 Jul 2013 02:13:49 +0000 (04:13 +0200)
committerZoltan Varga <vargaz@gmail.com>
Wed, 24 Jul 2013 02:13:49 +0000 (04:13 +0200)
mono/mini/jit-icalls.c
mono/mini/jit-icalls.h
mono/mini/method-to-ir.c
mono/mini/mini.c

index ef75b39730e9aba2ac20736d042e9ace82325f3d..009d5e913732e057a560628890fa36c5cb39130a 100644 (file)
@@ -1190,62 +1190,20 @@ constrained_gsharedvt_call_setup (gpointer mp, MonoMethod *cmethod, MonoClass *k
        return m;
 }
 
-MonoObject*
-mono_object_tostring_gsharedvt (gpointer mp, MonoMethod *cmethod, MonoClass *klass)
-{
-       MonoMethod *m;
-       gpointer this_arg;
-
-       m = constrained_gsharedvt_call_setup (mp, cmethod, klass, &this_arg);
-       return mono_runtime_invoke (m, this_arg, NULL, NULL);
-}
-
-int
-mono_object_gethashcode_gsharedvt (gpointer mp, MonoMethod *cmethod, MonoClass *klass)
-{
-       MonoMethod *m;
-       gpointer this_arg;
-       MonoObject *res;
-       gpointer p;
-
-       m = constrained_gsharedvt_call_setup (mp, cmethod, klass, &this_arg);
-       // FIXME: This boxes the result
-       res = mono_runtime_invoke (m, this_arg, NULL, NULL);
-       p = mono_object_unbox (res);
-       return *(int*)p;
-}
-
-MonoBoolean
-mono_object_equals_gsharedvt (gpointer mp, MonoMethod *cmethod, MonoClass *klass, MonoObject *arg)
-{
-       MonoMethod *m;
-       gpointer this_arg;
-       MonoObject *res;
-       gpointer p;
-       void **args;
-
-       m = constrained_gsharedvt_call_setup (mp, cmethod, klass, &this_arg);
-       // FIXME: This boxes the result
-       args = (void**)&arg;
-       res = mono_runtime_invoke (m, this_arg, args, NULL);
-       p = mono_object_unbox (res);
-       return *(MonoBoolean*)p;
-}
-
 /*
  * mono_gsharedvt_constrained_call:
  *
  *   Make a call to CMETHOD using the receiver MP, which is assumed to be of type KLASS. ARGS contains
  * the arguments to the method in the format used by mono_runtime_invoke ().
  */
-void
+MonoObject*
 mono_gsharedvt_constrained_call (gpointer mp, MonoMethod *cmethod, MonoClass *klass, gpointer *args)
 {
        MonoMethod *m;
        gpointer this_arg;
 
        m = constrained_gsharedvt_call_setup (mp, cmethod, klass, &this_arg);
-       mono_runtime_invoke (m, this_arg, args, NULL);
+       return mono_runtime_invoke (m, this_arg, args, NULL);
 }
 
 void
index 50509fcef2708fe8710b9ff52833218117ffa452..54455c96e8002f9d7bd4c108d4904a25e862c031 100644 (file)
@@ -175,13 +175,8 @@ mono_object_isinst_with_cache (MonoObject *obj, MonoClass *klass, gpointer *cach
 MonoObject*
 mono_object_castclass_with_cache (MonoObject *obj, MonoClass *klass, gpointer *cache);
 
-MonoObject* mono_object_tostring_gsharedvt (gpointer mp, MonoMethod *cmethod, MonoClass *klass) MONO_INTERNAL;
-
-int mono_object_gethashcode_gsharedvt (gpointer mp, MonoMethod *cmethod, MonoClass *klass) MONO_INTERNAL;
-
-MonoBoolean mono_object_equals_gsharedvt (gpointer mp, MonoMethod *cmethod, MonoClass *klass, MonoObject *arg) MONO_INTERNAL;
-
-void mono_gsharedvt_constrained_call (gpointer mp, MonoMethod *cmethod, MonoClass *klass, gpointer *args) MONO_INTERNAL;
+MonoObject*
+mono_gsharedvt_constrained_call (gpointer mp, MonoMethod *cmethod, MonoClass *klass, gpointer *args) MONO_INTERNAL;
 
 void mono_gsharedvt_value_copy (gpointer dest, gpointer src, MonoClass *klass) MONO_INTERNAL;
 
index bc379b7d648585160059196b76ca786bb1d97f07..8b6974554497dfd912a967573f2135ec6f7dd053 100644 (file)
@@ -7669,30 +7669,18 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        /*
                                         * Constrained calls need to behave differently at runtime dependending on whenever the receiver is instantiated as ref type or as a vtype.
                                         */
-                                       /* Special case Object methods as they are easy to implement */
-                                       if (cmethod->klass == mono_defaults.object_class) {
-                                               MonoInst *args [16];
-
-                                               args [0] = sp [0];
-                                               EMIT_NEW_METHODCONST (cfg, args [1], cmethod);
-                                               args [2] = emit_get_rgctx_klass (cfg, mono_class_check_context_used (constrained_call), constrained_call, MONO_RGCTX_INFO_KLASS);
-
-                                               if (!strcmp (cmethod->name, "ToString")) {
-                                                       ins = mono_emit_jit_icall (cfg, mono_object_tostring_gsharedvt, args);
-                                               } else if (!strcmp (cmethod->name, "Equals")) {
-                                                       args [3] = sp [1];
-                                                       ins = mono_emit_jit_icall (cfg, mono_object_equals_gsharedvt, args);
-                                               } else if (!strcmp (cmethod->name, "GetHashCode")) {
-                                                       ins = mono_emit_jit_icall (cfg, mono_object_gethashcode_gsharedvt, args);
-                                               } else {
-                                                       GSHAREDVT_FAILURE (*ip);
-                                               }
-                                               goto call_end;
-                                       } else if (constrained_call->valuetype && cmethod->klass->valuetype) {
+                                       if ((cmethod->klass != mono_defaults.object_class) && constrained_call->valuetype && cmethod->klass->valuetype) {
                                                /* The 'Own method' case below */
-                                       } else if ((cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE) && MONO_TYPE_IS_VOID (fsig->ret) && (fsig->param_count == 0 || (fsig->param_count == 1 && MONO_TYPE_IS_REFERENCE (fsig->params [0])))) {
+                                       } else if (((cmethod->klass == mono_defaults.object_class) || (cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE)) &&
+                                                          (MONO_TYPE_IS_VOID (fsig->ret) || fsig->ret->type == MONO_TYPE_I4 || fsig->ret->type == MONO_TYPE_BOOLEAN || fsig->ret->type == MONO_TYPE_STRING) &&
+                                                          (fsig->param_count == 0 || (fsig->param_count == 1 && MONO_TYPE_IS_REFERENCE (fsig->params [0])))) {
                                                MonoInst *args [16];
 
+                                               /*
+                                                * This case handles calls to object:ToString()/Equals()/GetHashCode(), plus some simple interface calls enough to support
+                                                * AsyncTaskMethodBuilder.
+                                                */
+
                                                args [0] = sp [0];
                                                EMIT_NEW_METHODCONST (cfg, args [1], cmethod);
                                                args [2] = emit_get_rgctx_klass (cfg, mono_class_check_context_used (constrained_call), constrained_call, MONO_RGCTX_INFO_KLASS);
@@ -7709,8 +7697,26 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                                } else {
                                                        EMIT_NEW_ICONST (cfg, args [3], 0);
                                                }
-
                                                ins = mono_emit_jit_icall (cfg, mono_gsharedvt_constrained_call, args);
+                                               emit_widen = FALSE;
+
+                                               if (fsig->ret->type == MONO_TYPE_I4 || fsig->ret->type == MONO_TYPE_BOOLEAN) {
+                                                       MonoInst *add;
+                                                       int dreg;
+
+                                                       /* Unbox */
+                                                       NEW_BIALU_IMM (cfg, add, OP_ADD_IMM, alloc_dreg (cfg, STACK_MP), ins->dreg, sizeof (MonoObject));
+                                                       MONO_ADD_INS (cfg->cbb, add);
+                                                       dreg = alloc_ireg (cfg);
+                                                       /* Load value */
+                                                       if (fsig->ret->type == MONO_TYPE_BOOLEAN)
+                                                               NEW_LOAD_MEMBASE (cfg, ins, OP_LOADU1_MEMBASE, dreg, add->dreg, 0);
+                                                       else
+                                                               NEW_LOAD_MEMBASE (cfg, ins, OP_LOADI4_MEMBASE, dreg, add->dreg, 0);
+                                                       MONO_ADD_INS (cfg->cbb, ins);
+                                                       /* ins represents the call result */
+                                               }
+
                                                goto call_end;
                                        } else {
                                                GSHAREDVT_FAILURE (*ip);
index fc8ffdb2374e3faca5827c49e33f33d6d93be897..2e320d44b506dc36a945d5775643ef3fde32bb8e 100644 (file)
@@ -7265,10 +7265,7 @@ mini_init (const char *filename, const char *runtime_version)
        register_icall (mono_array_new_4, "mono_array_new_4", "object ptr int int int int", FALSE);
        register_icall (mono_get_native_calli_wrapper, "mono_get_native_calli_wrapper", "ptr ptr ptr ptr", FALSE);
        register_icall (mono_resume_unwind, "mono_resume_unwind", "void", TRUE);
-       register_icall (mono_object_tostring_gsharedvt, "mono_object_tostring_gsharedvt", "object ptr ptr ptr", TRUE);
-       register_icall (mono_object_gethashcode_gsharedvt, "mono_object_gethashcode_gsharedvt", "int ptr ptr ptr", TRUE);
-       register_icall (mono_object_equals_gsharedvt, "mono_object_equals_gsharedvt", "int ptr ptr ptr object", TRUE);
-       register_icall (mono_gsharedvt_constrained_call, "mono_gsharedvt_constrained_call", "void ptr ptr ptr ptr", TRUE);
+       register_icall (mono_gsharedvt_constrained_call, "mono_gsharedvt_constrained_call", "object ptr ptr ptr ptr", TRUE);
        register_icall (mono_gsharedvt_value_copy, "mono_gsharedvt_value_copy", "void ptr ptr ptr", TRUE);
 
        register_icall (mono_gc_wbarrier_value_copy_bitmap, "mono_gc_wbarrier_value_copy_bitmap", "void ptr ptr int int", FALSE);