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>
13 #include <mono/utils/mono-counters.h>
18 * mono_get_generic_context_from_code:
20 * Return the runtime generic context belonging to the method whose native code
23 MonoGenericSharingContext*
24 mono_get_generic_context_from_code (guint8 *code)
26 MonoJitInfo *jit_info = mono_jit_info_table_find (mono_domain_get (), (char*)code);
30 return mono_jit_info_get_generic_sharing_context (jit_info);
34 * mini_method_get_context:
37 * Returns the generic context of a method or NULL if it doesn't have
38 * one. For an inflated method that's the context stored in the
39 * method. Otherwise it's in the method's generic container or in the
40 * generic container of the method's class.
43 mini_method_get_context (MonoMethod *method)
45 if (method->is_inflated)
46 return mono_method_get_context (method);
47 if (method->is_generic)
48 return &(mono_method_get_generic_container (method)->context);
49 if (method->klass->generic_container)
50 return &method->klass->generic_container->context;
55 * mono_method_check_context_used:
58 * Checks whether the method's generic context uses a type variable.
59 * Returns an int with the bits MONO_GENERIC_CONTEXT_USED_CLASS and
60 * MONO_GENERIC_CONTEXT_USED_METHOD set to reflect whether the
61 * context's class or method instantiation uses type variables.
64 mono_method_check_context_used (MonoMethod *method)
66 MonoGenericContext *method_context = mini_method_get_context (method);
71 return mono_generic_context_check_used (method_context);
75 generic_inst_is_sharable (MonoGenericInst *inst, gboolean allow_type_vars)
79 for (i = 0; i < inst->type_argc; ++i) {
80 MonoType *type = inst->type_argv [i];
83 if (MONO_TYPE_IS_REFERENCE (type))
86 type_type = mono_type_get_type (type);
87 if (allow_type_vars && (type_type == MONO_TYPE_VAR || type_type == MONO_TYPE_MVAR))
97 * mono_generic_context_is_sharable:
98 * @context: a generic context
100 * Returns whether the generic context is sharable. A generic context
101 * is sharable iff all of its type arguments are reference type.
104 mono_generic_context_is_sharable (MonoGenericContext *context, gboolean allow_type_vars)
106 g_assert (context->class_inst || context->method_inst);
108 if (context->class_inst && !generic_inst_is_sharable (context->class_inst, allow_type_vars))
111 if (context->method_inst && !generic_inst_is_sharable (context->method_inst, allow_type_vars))
118 * mono_method_is_generic_impl:
121 * Returns whether the method is either inflated or part of an
125 mono_method_is_generic_impl (MonoMethod *method)
127 return method->klass->generic_class != NULL && method->is_inflated;
131 * mono_method_is_generic_sharable_impl:
133 * @allow_type_vars: whether to regard type variables as reference types
135 * Returns TRUE iff the method is inflated or part of an inflated
136 * class, its context is sharable and it has no constraints on its
137 * type parameters. Otherwise returns FALSE.
140 mono_method_is_generic_sharable_impl (MonoMethod *method, gboolean allow_type_vars)
142 if (!mono_method_is_generic_impl (method))
145 if (method->is_inflated) {
146 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
147 MonoGenericContext *context = &inflated->context;
149 if (!mono_generic_context_is_sharable (context, allow_type_vars))
152 g_assert (inflated->declaring);
154 if (inflated->declaring->is_generic) {
155 g_assert (mono_method_get_generic_container (inflated->declaring)->type_params);
157 if (mono_method_get_generic_container (inflated->declaring)->type_params->constraints)
162 if (method->klass->generic_class) {
163 if (!mono_generic_context_is_sharable (&method->klass->generic_class->context, allow_type_vars))
166 g_assert (method->klass->generic_class->container_class &&
167 method->klass->generic_class->container_class->generic_container &&
168 method->klass->generic_class->container_class->generic_container->type_params);
170 if (method->klass->generic_class->container_class->generic_container->type_params->constraints)
178 generic_inst_equal (MonoGenericInst *inst1, MonoGenericInst *inst2)
189 if (inst1->type_argc != inst2->type_argc)
192 for (i = 0; i < inst1->type_argc; ++i)
193 if (!mono_metadata_type_equal (inst1->type_argv [i], inst2->type_argv [i]))
200 * mono_generic_context_equal_deep:
201 * @context1: a generic context
202 * @context2: a generic context
204 * Returns whether context1's type arguments are equal to context2's
208 mono_generic_context_equal_deep (MonoGenericContext *context1, MonoGenericContext *context2)
210 return generic_inst_equal (context1->class_inst, context2->class_inst) &&
211 generic_inst_equal (context1->method_inst, context2->method_inst);
215 * mini_class_get_container_class:
216 * @class: a generic class
218 * Returns the class's container class, which is the class itself if
219 * it doesn't have generic_class set.
222 mini_class_get_container_class (MonoClass *class)
224 if (class->generic_class)
225 return class->generic_class->container_class;
227 g_assert (class->generic_container);
232 * mini_class_get_context:
233 * @class: a generic class
235 * Returns the class's generic context.
238 mini_class_get_context (MonoClass *class)
240 if (class->generic_class)
241 return &class->generic_class->context;
243 g_assert (class->generic_container);
244 return &class->generic_container->context;
248 * mini_get_basic_type_from_generic:
249 * @gsctx: a generic sharing context
252 * Returns a closed type corresponding to the possibly open type
256 mini_get_basic_type_from_generic (MonoGenericSharingContext *gsctx, MonoType *type)
258 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR))
261 return mono_type_get_basic_type_from_generic (type);
265 * mini_type_stack_size:
266 * @gsctx: a generic sharing context
268 * @align: Pointer to an int for returning the alignment
270 * Returns the type's stack size and the alignment in *align. The
271 * type is allowed to be open.
274 mini_type_stack_size (MonoGenericSharingContext *gsctx, MonoType *t, int *align)
276 return mono_type_stack_size_internal (t, align, gsctx != NULL);
280 * mono_generic_sharing_init:
282 * Register the generic sharing counters.
285 mono_generic_sharing_init (void)