}
if (managed_alloc && !(cfg->opt & MONO_OPT_SHARED)) {
- if (known_instance_size)
- EMIT_NEW_ICONST (cfg, iargs [1], mono_gc_get_aligned_size_for_allocator (klass->instance_size));
+ if (known_instance_size) {
+ int size = mono_class_instance_size (klass);
+
+ EMIT_NEW_ICONST (cfg, iargs [1], mono_gc_get_aligned_size_for_allocator (size));
+ }
return mono_emit_method_call (cfg, managed_alloc, iargs, NULL);
}
#endif
if (managed_alloc) {
+ int size = mono_class_instance_size (klass);
+
EMIT_NEW_VTABLECONST (cfg, iargs [0], vtable);
- EMIT_NEW_ICONST (cfg, iargs [1], mono_gc_get_aligned_size_for_allocator (klass->instance_size));
+ EMIT_NEW_ICONST (cfg, iargs [1], mono_gc_get_aligned_size_for_allocator (size));
return mono_emit_method_call (cfg, managed_alloc, iargs, NULL);
}
alloc_ftn = mono_class_get_allocation_ftn (vtable, for_box, &pass_lw);
cil_method = cmethod;
if (constrained_class) {
+ if ((constrained_class->byval_arg.type == MONO_TYPE_VAR || constrained_class->byval_arg.type == MONO_TYPE_MVAR) && cfg->generic_sharing_context) {
+ if (!mini_is_gsharedvt_klass (cfg, constrained_class)) {
+ g_assert (!cmethod->klass->valuetype);
+ if (!mini_type_is_reference (cfg, &constrained_class->byval_arg)) {
+ /* FIXME: gshared type constrained to a primitive type */
+ GENERIC_SHARING_FAILURE (CEE_CALL);
+ }
+ }
+ }
+
if (method->wrapper_type != MONO_WRAPPER_NONE) {
if (cfg->verbose_level > 2)
printf ("DM Constrained call to %s\n", mono_type_get_full_name (constrained_class));
#include "mini.h"
-#define ALLOW_PARTIAL_SHARING TRUE
-//#define ALLOW_PARTIAL_SHARING FALSE
+//#define ALLOW_PARTIAL_SHARING TRUE
+#define ALLOW_PARTIAL_SHARING FALSE
#if 0
#define DEBUG(...) __VA_ARGS__
gboolean allow_partial)
{
int i;
- gboolean has_ref = FALSE;
for (i = 0; i < inst->type_argc; ++i) {
MonoType *type = inst->type_argv [i];
- if (MONO_TYPE_IS_REFERENCE (type) || (allow_type_vars && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR))) {
- has_ref = TRUE;
+ if (MONO_TYPE_IS_REFERENCE (type) || (allow_type_vars && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)))
continue;
- }
- /*
- * Allow non ref arguments, if there is at least one ref argument
- * (partial sharing).
- * FIXME: Allow more types
- */
- if (allow_partial && !type->byref && (((type->type >= MONO_TYPE_BOOLEAN) && (type->type <= MONO_TYPE_R8)) || (type->type == MONO_TYPE_I) || (type->type == MONO_TYPE_U)))
+ /* Allow non ref arguments if they are primitive types or enums (partial sharing). */
+ if (allow_partial && !type->byref && (((type->type >= MONO_TYPE_BOOLEAN) && (type->type <= MONO_TYPE_R8)) || (type->type == MONO_TYPE_I) || (type->type == MONO_TYPE_U) || (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)))
continue;
return FALSE;
}
- if (allow_partial)
- return has_ref;
- else
- return TRUE;
+ return TRUE;
}
/*
if (!partial_sharing_supported ())
allow_partial = FALSE;
+ if (method->klass->image->dynamic)
+ /*
+ * Enabling this causes corlib test failures because the JIT encounters generic instances whose
+ * instance_size is 0.
+ */
+ allow_partial = FALSE;
+
/*
* Generic async methods have an associated state machine class which is a generic struct. This struct
* is too large to be handled by gsharedvt so we make it visible to the AOT compiler by disabling sharing
return res;
}
+static MonoType*
+get_shared_type (MonoType *t, MonoType *type)
+{
+ MonoTypeEnum ttype;
+
+ g_assert (!type->byref && (((type->type >= MONO_TYPE_BOOLEAN) && (type->type <= MONO_TYPE_R8)) || (type->type == MONO_TYPE_I) || (type->type == MONO_TYPE_U) || (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)));
+
+ /* Create a type variable with a constraint which encodes which types can match it */
+ ttype = type->type;
+ if (type->type == MONO_TYPE_VALUETYPE)
+ ttype = mono_class_enum_basetype (type->data.klass)->type;
+ return get_shared_gparam (t, ttype);
+}
+
static MonoType*
get_gsharedvt_type (MonoType *t)
{
}
static MonoGenericInst*
-get_shared_inst (MonoGenericInst *inst, MonoGenericInst *shared_inst, MonoGenericContainer *container, gboolean all_vt, gboolean gsharedvt)
+get_shared_inst (MonoGenericInst *inst, MonoGenericInst *shared_inst, MonoGenericContainer *container, gboolean all_vt, gboolean gsharedvt, gboolean partial)
{
MonoGenericInst *res;
MonoType **type_argv;
for (i = 0; i < inst->type_argc; ++i) {
if (!all_vt && (MONO_TYPE_IS_REFERENCE (inst->type_argv [i]) || inst->type_argv [i]->type == MONO_TYPE_VAR || inst->type_argv [i]->type == MONO_TYPE_MVAR)) {
type_argv [i] = shared_inst->type_argv [i];
+ } else if (partial) {
+ /* These types match the ones in generic_inst_is_sharable () */
+ type_argv [i] = get_shared_type (shared_inst->type_argv [i], inst->type_argv [i]);
} else if (all_vt) {
type_argv [i] = get_gsharedvt_type (shared_inst->type_argv [i]);
} else if (gsharedvt) {
else
inst = shared_context.class_inst;
if (inst)
- shared_context.class_inst = get_shared_inst (inst, shared_context.class_inst, class_container, all_vt, gsharedvt);
+ shared_context.class_inst = get_shared_inst (inst, shared_context.class_inst, class_container, all_vt, gsharedvt, partial);
if (context)
inst = context->method_inst;
else
inst = shared_context.method_inst;
if (inst)
- shared_context.method_inst = get_shared_inst (inst, shared_context.method_inst, method_container, all_vt, gsharedvt);
+ shared_context.method_inst = get_shared_inst (inst, shared_context.method_inst, method_container, all_vt, gsharedvt, partial);
partial = TRUE;
}