[llvmonly] Add support for runtime invokes with nullable arguments.
authorZoltan Varga <vargaz@gmail.com>
Wed, 6 Jan 2016 12:51:12 +0000 (07:51 -0500)
committerZoltan Varga <vargaz@gmail.com>
Wed, 6 Jan 2016 12:51:22 +0000 (07:51 -0500)
mono/mini/Makefile.am.in
mono/mini/aot-compiler.c
mono/mini/mini-runtime.c

index ab9fe4f39f064d32fd343ee64362a2aea3439129..5be413b012ca0233670ba64803a9fde932787712 100755 (executable)
@@ -744,7 +744,7 @@ llvmonlycheck: mono $(llvmonly_regtests)
        cp $(llvmonly_regtests) generics-variant-types.dll TestDriver.dll fullaot-tmp/
        MONO_PATH=fullaot-tmp $(top_builddir)/runtime/mono-wrapper  --aot=llvmonly fullaot-tmp/{generics-variant-types.dll,TestDriver.dll,*.exe} || exit 1
        ln -s $$PWD/mono fullaot-tmp/
-       for i in $(llvmonly_regtests); do echo $$i; MONO_PATH=fullaot-tmp $(top_builddir)/runtime/mono-wrapper --llvmonly fullaot-tmp/$$i --exclude '!FULLAOT' --exclude '!BITCODE' $(ARCH_FULLAOT_EXCLUDE) || exit 1; done
+       for i in $(llvmonly_regtests); do echo $$i; MONO_PATH=fullaot-tmp $(top_builddir)/runtime/mono-wrapper --llvmonly fullaot-tmp/$$i --exclude '!FULLAOT' --exclude '!BITCODE' --exclude GSHAREDVT || exit 1; done
 
 gccheck: gc-test.exe
        MONO_GC_PARAMS=stack-mark=precise MONO_GC_DEBUG=clear-at-gc ./mono-sgen gc-test.exe     
index 4b18c2042ae09f6579be072721ff16d4dd3d4704..63a330d537097562e70e49bfd89c1bbae9e913ae 100644 (file)
@@ -6957,21 +6957,44 @@ add_gsharedvt_wrappers (MonoAotCompile *acfg, MonoMethodSignature *sig, gboolean
                if (copy->ret->type == MONO_TYPE_VAR || copy->ret->type == MONO_TYPE_MVAR || copy->ret->type == MONO_TYPE_GENERICINST)
                        concrete = FALSE;
                for (i = 0; i < sig->param_count; ++i) {
-                       copy->params [i] = mini_get_underlying_type (sig->params [i]);
-                       if (copy->params [i]->type == MONO_TYPE_VAR || copy->params [i]->type == MONO_TYPE_MVAR || copy->params [i]->type == MONO_TYPE_GENERICINST)
-                               concrete = FALSE;
+                       MonoType *t = mini_get_underlying_type (sig->params [i]);
+                       /*
+                        * Create a concrete type for Nullable<T_REF> etc.
+                        * FIXME: Generalize this
+                        */
+                       if (t->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type (t))) {
+                               MonoType *arg = mono_class_from_mono_type (t)->generic_class->context.class_inst->type_argv[0];
+                               arg = mini_get_underlying_type (arg);
+                               if (arg->type == MONO_TYPE_VAR || arg->type == MONO_TYPE_MVAR || arg->type == MONO_TYPE_GENERICINST) {
+                                       concrete = FALSE;
+                               } else {
+                                       MonoGenericContext ctx;
+                                       MonoClass *klass;
+                                       MonoType *args [16];
+
+                                       memset (&ctx, 0, sizeof (MonoGenericContext));
+                                       args [0] = arg;
+                                       ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+
+                                       klass = mono_class_inflate_generic_class (mono_defaults.generic_nullable_class, &ctx);
+                                       t = &klass->byval_arg;
+                               }
+                       } else {
+                               if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR || t->type == MONO_TYPE_GENERICINST)
+                                       concrete = FALSE;
+                       }
+                       copy->params [i] = t;
                }
                if (concrete) {
                        copy->has_type_parameters = 0;
-                       sig = copy;
 
                        if (gsharedvt_in) {
-                               wrapper = mini_get_gsharedvt_in_sig_wrapper (sig);
+                               wrapper = mini_get_gsharedvt_in_sig_wrapper (copy);
                                add_extra_method (acfg, wrapper);
                        }
 
                        if (gsharedvt_out) {
-                               wrapper = mini_get_gsharedvt_out_sig_wrapper (sig);
+                               wrapper = mini_get_gsharedvt_out_sig_wrapper (copy);
                                add_extra_method (acfg, wrapper);
                        }
 
index ef749c100a6ab43e584c79cc197bf85f20e38337..91bc9018668a915c7243bc4e08e826015c7cb82a 100644 (file)
@@ -2161,14 +2161,9 @@ gboolean
 mini_gsharedvt_runtime_invoke_supported (MonoMethodSignature *sig)
 {
        gboolean supported = TRUE;
-       int i;
-
-       for (i = 0; i < sig->param_count; ++i) {
-               MonoType *t = sig->params [i];
 
-               if (t->byref && t->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type (t)))
-                       supported = FALSE;
-       }
+       if (sig->ret->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type (sig->ret)))
+               supported = FALSE;
 
        return supported;
 }
@@ -2509,6 +2504,20 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec
                for (i = 0; i < sig->param_count; ++i) {
                        MonoType *t = sig->params [i];
 
+                       if (t->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type (t))) {
+                               MonoClass *klass = mono_class_from_mono_type (t);
+                               guint8 *nullable_buf;
+                               int size;
+
+                               size = mono_class_value_size (klass, NULL);
+                               nullable_buf = g_alloca (size);
+                               g_assert (nullable_buf);
+
+                               /* The argument pointed to by params [i] is either a boxed vtype or null */
+                               mono_nullable_init (nullable_buf, (MonoObject*)params [i], klass);
+                               params [i] = nullable_buf;
+                       }
+
                        if (MONO_TYPE_IS_REFERENCE (t)) {
                                param_refs [i] = params [i];
                                params [i] = &(param_refs [i]);