2 * generic-sharing.c: Support functions for generic sharing.
5 * Mark Probst (mark.probst@gmail.com)
7 * (C) 2007 Novell, Inc.
12 #include <mono/metadata/class.h>
17 generic_inst_uses_type (MonoGenericInst *inst, MonoType *type)
24 for (i = 0; i < inst->type_argc; ++i)
25 if (mono_metadata_type_equal (type, inst->type_argv [i]))
30 static int context_check_context_used (MonoGenericContext *context, MonoGenericContext *shared_context);
33 type_check_context_used (MonoType *type, MonoGenericContext *context, gboolean recursive)
37 if (generic_inst_uses_type (context->class_inst, type))
38 context_used |= MONO_GENERIC_CONTEXT_USED_CLASS;
39 if (generic_inst_uses_type (context->method_inst, type))
40 context_used |= MONO_GENERIC_CONTEXT_USED_METHOD;
43 int t = mono_type_get_type (type);
45 if (t == MONO_TYPE_CLASS)
46 context_used |= mono_class_check_context_used (mono_type_get_class (type), context);
47 else if (t == MONO_TYPE_GENERICINST) {
48 MonoGenericClass *gclass = type->data.generic_class;
50 context_used |= context_check_context_used (&gclass->context, context);
51 context_used |= mono_class_check_context_used (gclass->container_class, context);
59 inst_check_context_used (MonoGenericInst *inst, MonoGenericContext *context)
67 for (i = 0; i < inst->type_argc; ++i)
68 context_used |= type_check_context_used (inst->type_argv [i], context, TRUE);
74 context_check_context_used (MonoGenericContext *context, MonoGenericContext *shared_context)
78 context_used |= inst_check_context_used (context->class_inst, shared_context);
79 context_used |= inst_check_context_used (context->method_inst, shared_context);
85 mono_method_check_context_used (MonoMethod *method, MonoGenericContext *context)
87 MonoGenericContext *method_context = mono_method_get_context (method);
92 return context_check_context_used (method_context, context);
96 mono_class_check_context_used (MonoClass *class, MonoGenericContext *context)
100 context_used |= type_check_context_used (&class->this_arg, context, FALSE);
101 context_used |= type_check_context_used (&class->byval_arg, context, FALSE);
103 if (class->generic_class)
104 context_used |= context_check_context_used (&class->generic_class->context, context);
110 generic_inst_is_sharable (MonoGenericInst *inst)
114 for (i = 0; i < inst->type_argc; ++i) {
115 int type = mono_type_get_type (inst->type_argv [i]);
117 if (type != MONO_TYPE_CLASS && type != MONO_TYPE_STRING && type != MONO_TYPE_OBJECT &&
118 type != MONO_TYPE_SZARRAY && type != MONO_TYPE_ARRAY)
126 generic_context_is_sharable (MonoGenericContext *context)
128 g_assert (context->class_inst || context->method_inst);
130 if (context->class_inst && !generic_inst_is_sharable (context->class_inst))
133 if (context->method_inst && !generic_inst_is_sharable (context->method_inst))
140 mono_method_is_generic_impl (MonoMethod *method)
142 return method->klass->generic_class != NULL && method->is_inflated;
146 mono_method_is_generic_sharable_impl (MonoMethod *method)
148 if (!mono_method_is_generic_impl (method))
151 if (method->is_inflated) {
152 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
153 MonoGenericContext *context = &inflated->context;
155 if (!generic_context_is_sharable (context))
158 g_assert (inflated->declaring);
160 if (inflated->declaring->generic_container) {
161 g_assert (inflated->declaring->generic_container->type_params);
163 if (inflated->declaring->generic_container->type_params->constraints)
168 if (method->klass->generic_class) {
169 if (!generic_context_is_sharable (&method->klass->generic_class->context))
172 g_assert (method->klass->generic_class->container_class &&
173 method->klass->generic_class->container_class->generic_container &&
174 method->klass->generic_class->container_class->generic_container->type_params);
176 if (method->klass->generic_class->container_class->generic_container->type_params->constraints)
183 static MonoGenericInst*
184 share_generic_inst (MonoCompile *cfg, MonoGenericInst *inst)
186 MonoType **type_argv;
192 type_argv = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoType*) * inst->type_argc);
194 for (i = 0; i < inst->type_argc; ++i)
195 type_argv [i] = &mono_defaults.object_class->byval_arg;
197 return mono_metadata_get_generic_inst (inst->type_argc, type_argv);
201 mono_make_shared_context (MonoCompile *cfg, MonoGenericContext *context)
203 MonoGenericContext *shared = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoGenericContext));
205 shared->class_inst = share_generic_inst (cfg, context->class_inst);
206 shared->method_inst = share_generic_inst (cfg, context->method_inst);
212 mini_get_basic_type_from_generic (MonoGenericSharingContext *gsctx, MonoType *type)
214 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)) {
215 /* FIXME: we support sharing only of reference types */
217 return &mono_defaults.object_class->byval_arg;
223 mini_type_stack_size (MonoGenericSharingContext *gsctx, MonoType *t, int *align)
225 return mono_type_stack_size_internal (t, align, gsctx != NULL);