2010-02-15 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / mini / mini-generic-sharing.c
1 /*
2  * generic-sharing.c: Support functions for generic sharing.
3  *
4  * Author:
5  *   Mark Probst (mark.probst@gmail.com)
6  *
7  * (C) 2007 Novell, Inc.
8  */
9
10 #include <config.h>
11
12 #include <mono/metadata/class.h>
13 #include <mono/utils/mono-counters.h>
14
15 #include "mini.h"
16
17 /*
18  * mono_get_generic_context_from_code:
19  *
20  *   Return the runtime generic context belonging to the method whose native code
21  * contains CODE.
22  */
23 MonoGenericSharingContext*
24 mono_get_generic_context_from_code (guint8 *code)
25 {
26         MonoJitInfo *jit_info = mini_jit_info_table_find (mono_domain_get (), (char*)code, NULL);
27
28         g_assert (jit_info);
29
30         return mono_jit_info_get_generic_sharing_context (jit_info);
31 }
32
33 MonoGenericContext*
34 mini_method_get_context (MonoMethod *method)
35 {
36         return mono_method_get_context_general (method, TRUE);
37 }
38
39 /*
40  * mono_method_check_context_used:
41  * @method: a method
42  *
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.
47  */
48 int
49 mono_method_check_context_used (MonoMethod *method)
50 {
51         MonoGenericContext *method_context = mini_method_get_context (method);
52         int context_used = 0;
53
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);
61         }
62
63         return context_used;
64 }
65
66 static gboolean
67 generic_inst_equal (MonoGenericInst *inst1, MonoGenericInst *inst2)
68 {
69         int i;
70
71         if (!inst1) {
72                 g_assert (!inst2);
73                 return TRUE;
74         }
75
76         g_assert (inst2);
77
78         if (inst1->type_argc != inst2->type_argc)
79                 return FALSE;
80
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;
84
85         return TRUE;
86 }
87
88 /*
89  * mono_generic_context_equal_deep:
90  * @context1: a generic context
91  * @context2: a generic context
92  *
93  * Returns whether context1's type arguments are equal to context2's
94  * type arguments.
95  */
96 gboolean
97 mono_generic_context_equal_deep (MonoGenericContext *context1, MonoGenericContext *context2)
98 {
99         return generic_inst_equal (context1->class_inst, context2->class_inst) &&
100                 generic_inst_equal (context1->method_inst, context2->method_inst);
101 }
102
103 /*
104  * mini_class_get_container_class:
105  * @class: a generic class
106  *
107  * Returns the class's container class, which is the class itself if
108  * it doesn't have generic_class set.
109  */
110 MonoClass*
111 mini_class_get_container_class (MonoClass *class)
112 {
113         if (class->generic_class)
114                 return class->generic_class->container_class;
115
116         g_assert (class->generic_container);
117         return class;
118 }
119
120 /*
121  * mini_class_get_context:
122  * @class: a generic class
123  *
124  * Returns the class's generic context.
125  */
126 MonoGenericContext*
127 mini_class_get_context (MonoClass *class)
128 {
129         if (class->generic_class)
130                 return &class->generic_class->context;
131
132         g_assert (class->generic_container);
133         return &class->generic_container->context;
134 }
135
136 /*
137  * mini_get_basic_type_from_generic:
138  * @gsctx: a generic sharing context
139  * @type: a type
140  *
141  * Returns a closed type corresponding to the possibly open type
142  * passed to it.
143  */
144 MonoType*
145 mini_get_basic_type_from_generic (MonoGenericSharingContext *gsctx, MonoType *type)
146 {
147         if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR))
148                 g_assert (gsctx);
149
150         return mono_type_get_basic_type_from_generic (type);
151 }
152
153 /*
154  * mini_type_get_underlying_type:
155  *
156  *   Return the underlying type of TYPE, taking into account enums, byref and generic
157  * sharing.
158  */
159 MonoType*
160 mini_type_get_underlying_type (MonoGenericSharingContext *gsctx, MonoType *type)
161 {
162         if (type->byref)
163                 return &mono_defaults.int_class->byval_arg;
164         return mono_type_get_basic_type_from_generic (mono_type_get_underlying_type (type));
165 }
166
167 /*
168  * mini_type_stack_size:
169  * @gsctx: a generic sharing context
170  * @t: a type
171  * @align: Pointer to an int for returning the alignment
172  *
173  * Returns the type's stack size and the alignment in *align.  The
174  * type is allowed to be open.
175  */
176 int
177 mini_type_stack_size (MonoGenericSharingContext *gsctx, MonoType *t, int *align)
178 {
179         gboolean allow_open = TRUE;
180
181         // FIXME: Some callers might not pass in a gsctx
182         //allow_open = gsctx != NULL;
183         return mono_type_stack_size_internal (t, align, allow_open);
184 }
185
186 /*
187  * mini_type_stack_size_full:
188  *
189  *   Same as mini_type_stack_size, but handle pinvoke data types as well.
190  */
191 int
192 mini_type_stack_size_full (MonoGenericSharingContext *gsctx, MonoType *t, guint32 *align, gboolean pinvoke)
193 {
194         int size;
195
196         if (pinvoke) {
197                 size = mono_type_native_stack_size (t, align);
198         } else {
199                 int ialign;
200
201                 if (align) {
202                         size = mini_type_stack_size (gsctx, t, &ialign);
203                         *align = ialign;
204                 } else {
205                         size = mini_type_stack_size (gsctx, t, NULL);
206                 }
207         }
208         
209         return size;
210 }
211
212 /*
213  * mono_generic_sharing_init:
214  *
215  * Register the generic sharing counters.
216  */
217 void
218 mono_generic_sharing_init (void)
219 {
220 }