Make sure x86 ATOMIC_CAS doesn't overwrite its own operands.
[mono-debugger.git] / mono / mini / mini-generic-sharing.c
blob54c29067a08353149953d642d717d2119e71ede4
1 /*
2 * generic-sharing.c: Support functions for generic sharing.
4 * Author:
5 * Mark Probst (mark.probst@gmail.com)
7 * (C) 2007 Novell, Inc.
8 */
10 #include <config.h>
12 #include <mono/metadata/class.h>
13 #include <mono/utils/mono-counters.h>
15 #include "mini.h"
18 * mono_get_generic_context_from_code:
20 * Return the runtime generic context belonging to the method whose native code
21 * contains 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);
28 g_assert (jit_info);
30 return mono_jit_info_get_generic_sharing_context (jit_info);
33 MonoGenericContext*
34 mini_method_get_context (MonoMethod *method)
36 return mono_method_get_context_general (method, TRUE);
40 * mono_method_check_context_used:
41 * @method: a method
43 * Checks whether the method's generic context uses a type variable.
44 * Returns an int with the bits MONO_GENERIC_CONTEXT_USED_CLASS and
45 * MONO_GENERIC_CONTEXT_USED_METHOD set to reflect whether the
46 * context's class or method instantiation uses type variables.
48 int
49 mono_method_check_context_used (MonoMethod *method)
51 MonoGenericContext *method_context = mini_method_get_context (method);
52 int context_used = 0;
54 if (!method_context) {
55 /* It might be a method of an array of an open generic type */
56 if (method->klass->rank)
57 context_used = mono_class_check_context_used (method->klass);
58 } else {
59 context_used = mono_generic_context_check_used (method_context);
60 context_used |= mono_class_check_context_used (method->klass);
63 return context_used;
66 static gboolean
67 generic_inst_equal (MonoGenericInst *inst1, MonoGenericInst *inst2)
69 int i;
71 if (!inst1) {
72 g_assert (!inst2);
73 return TRUE;
76 g_assert (inst2);
78 if (inst1->type_argc != inst2->type_argc)
79 return FALSE;
81 for (i = 0; i < inst1->type_argc; ++i)
82 if (!mono_metadata_type_equal (inst1->type_argv [i], inst2->type_argv [i]))
83 return FALSE;
85 return TRUE;
89 * mono_generic_context_equal_deep:
90 * @context1: a generic context
91 * @context2: a generic context
93 * Returns whether context1's type arguments are equal to context2's
94 * type arguments.
96 gboolean
97 mono_generic_context_equal_deep (MonoGenericContext *context1, MonoGenericContext *context2)
99 return generic_inst_equal (context1->class_inst, context2->class_inst) &&
100 generic_inst_equal (context1->method_inst, context2->method_inst);
104 * mini_class_get_container_class:
105 * @class: a generic class
107 * Returns the class's container class, which is the class itself if
108 * it doesn't have generic_class set.
110 MonoClass*
111 mini_class_get_container_class (MonoClass *class)
113 if (class->generic_class)
114 return class->generic_class->container_class;
116 g_assert (class->generic_container);
117 return class;
121 * mini_class_get_context:
122 * @class: a generic class
124 * Returns the class's generic context.
126 MonoGenericContext*
127 mini_class_get_context (MonoClass *class)
129 if (class->generic_class)
130 return &class->generic_class->context;
132 g_assert (class->generic_container);
133 return &class->generic_container->context;
137 * mini_get_basic_type_from_generic:
138 * @gsctx: a generic sharing context
139 * @type: a type
141 * Returns a closed type corresponding to the possibly open type
142 * passed to it.
144 MonoType*
145 mini_get_basic_type_from_generic (MonoGenericSharingContext *gsctx, MonoType *type)
147 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR))
148 g_assert (gsctx);
150 return mono_type_get_basic_type_from_generic (type);
154 * mini_type_get_underlying_type:
156 * Return the underlying type of TYPE, taking into account enums and generic
157 * sharing.
159 MonoType*
160 mini_type_get_underlying_type (MonoGenericSharingContext *gsctx, MonoType *type)
162 return mono_type_get_basic_type_from_generic (mono_type_get_underlying_type (type));
166 * mini_type_stack_size:
167 * @gsctx: a generic sharing context
168 * @t: a type
169 * @align: Pointer to an int for returning the alignment
171 * Returns the type's stack size and the alignment in *align. The
172 * type is allowed to be open.
175 mini_type_stack_size (MonoGenericSharingContext *gsctx, MonoType *t, int *align)
177 gboolean allow_open = TRUE;
179 // FIXME: Some callers might not pass in a gsctx
180 //allow_open = gsctx != NULL;
181 return mono_type_stack_size_internal (t, align, allow_open);
185 * mini_type_stack_size_full:
187 * Same as mini_type_stack_size, but handle pinvoke data types as well.
190 mini_type_stack_size_full (MonoGenericSharingContext *gsctx, MonoType *t, guint32 *align, gboolean pinvoke)
192 int size;
194 if (pinvoke) {
195 size = mono_type_native_stack_size (t, align);
196 } else {
197 int ialign;
199 if (align) {
200 size = mini_type_stack_size (gsctx, t, &ialign);
201 *align = ialign;
202 } else {
203 size = mini_type_stack_size (gsctx, t, NULL);
207 return size;
211 * mono_generic_sharing_init:
213 * Register the generic sharing counters.
215 void
216 mono_generic_sharing_init (void)