2008-09-09 Carlos Alberto Cortez <calberto.cortez@gmail.com>
[mono.git] / docs / generic-sharing
1 -*- outline -*-
2
3 Generic code sharing
4 ====================
5
6 * Porting
7
8 ** Generic class init trampoline
9
10 The generic class init trampoline is very similar to the class init
11 trampoline, with the exception that the VTable of the class to be
12 inited is passed in a register, MONO_ARCH_VTABLE_REG.  That can be the
13 same as the IMT register.
14
15 The call to the generic class init trampoline is never patched because
16 the VTable is not constant - it depends on the type arguments of the
17 class/method doing the call to the trampoline.  For that reason, the
18 trampoline needs a fast path for the case that the class is already
19 inited.  See tramp-x86.c for how to portably figure out the number of
20 the bit in the bit-field that needs to be checked.
21
22 ** RGCTX register
23
24 Generic shared code needs access to type information.  This
25 information is contained in a RGCTX for non-generic methods and in an
26 MRGCTX for generic methods.  It is passed in one of several ways,
27 depending on the type of the called method:
28
29   1. Non-generic non-static methods of reference types have access to
30      the RGCTX via the "this" argument (this->vtable->rgctx).
31
32   2. Non-generic static methods of reference types and non-generic
33      methods of value types need to be passed a pointer to the
34      caller's class's VTable in the MONO_ARCH_RGCTX_REG register.
35
36   3. Generic methods need to be passed a pointer to the MRGCTX in the
37      MONO_ARCH_RGCTX_REG register.
38
39 The MONO_ARCH_RGCTX_REG must not be clobbered by trampolines.
40
41 MONO_ARCH_RGCTX_REG can be the same as the IMT register for now, but
42 this might change in the future when we implement virtual generic
43 method calls (more) efficiently.
44
45 This register lifetime starts at the call site that loads it and
46 ends in the callee prologue when it is either discarded or stored
47 into a local variable.
48
49 It's better to avoid registers used for argument passing for the RGCTX
50 as it would make the code dealing with calling conventions code a lot harder.
51  
52 ** Method prologue
53
54 Generic shared code that have a RGCTX receive it in RGCTX_REG. There must be
55 a check in mono_arch_emit_prolog for MonoCompile::rgctx_var and if set
56 store it. See mini-x86.c for reference.  
57
58 ** Dealing with types
59
60 Types passed to arch functions might be type parameters
61 (MONO_TYPE_(M)VAR) if the MonoGenericSharingContext* argument is
62 non-NULL.  For example, an argument or return type in a method passed
63 to mono_arch_find_this_argument() could be a MONO_TYPE_VAR.  To guard
64 for that case use mini_get_basic_type_from_generic() on the type.  See
65 get_call_info() in mini-x86.c, for example.
66
67 ** (M)RGCTX lazy fetch trampoline
68
69 The purpose of the lazy fetch trampoline is to fetch a slot from an
70 (M)RGCTX which might not be inited, yet.  In the latter case, it needs
71 to go make a transition to unmanaged code to fill the slot.  This is
72 the layout of a RGCTX:
73
74      +---------------------------------+
75      | next | slot 0 | slot 1 | slot 2 |
76      +--|------------------------------+
77         |
78   +-----+
79   |  +---------------------------------
80   +->| next | slot 3 | slot 4 | slot 5 ....
81      +--|------------------------------
82         |
83   +-----+
84   |  +------------------------------------
85   +->| next | slot 10 | slot 11 | slot 12 ....
86      +--|---------------------------------
87         .
88         .
89         .
90
91 For fetching a slot from a RGCTX the trampoline is passed a pointer to
92 the VTable.  From there it has to fetch the pointer to the RGCTX,
93 which might be null.  Then it has to traverse the correct number of
94 "next" links, each of which might be NULL.  Arriving at the right
95 array it needs to fetch the slot, which might also be NULL.  If any of
96 the NULL cases, the trampoline must transition to unmanaged code to
97 potentially setup the RGCTX and fill the slot.  Here is pseudo-code
98 for fetching slot 11:
99
100     ; vtable ptr in r1
101     ; fetch RGCTX array 0
102     r2 = *(r1 + offsetof(MonoVTable, runtime_generic_context))
103     if r2 == NULL goto unmanaged
104     ; fetch RGCTX array 1
105     r2 = *r2
106     if r2 == NULL goto unmanaged
107     ; fetch RGCTX array 2
108     r2 = *r2
109     if r2 == NULL goto unmanaged
110     ; fetch slot 11
111     r2 = *(r2 + 2 * sizeof (gpointer))
112     if r2 == NULL goto unmanaged
113     return r2
114   unmanaged:
115     jump unmanaged_fetch_code
116
117 The number of slots in the arrays must be obtained from the function
118 mono_class_rgctx_get_array_size().
119
120 The MRGCTX case is different in two aspects.  First, the trampoline is
121 not passed a pointer to a VTable, but a pointer directly to the
122 MRGCTX, which is guaranteed not to be NULL (any of the next pointers
123 and any of the slots can be NULL, though).  Second, the layout of the
124 first array is slightly different, in that the first two slots are
125 occupied by a pointers to the class's VTable and to the method's
126 method_inst.  The next pointer is in the third slot and the first
127 actual slot, "slot 0", in the fourth:
128
129      +--------------------------------------------------------+
130      | vtable | method_inst | next | slot 0 | slot 1 | slot 2 |
131      +-------------------------|------------------------------+
132                                .
133                                .
134
135 All other arrays have the same layout as the RGCTX ones, except
136 possibly for their length.
137
138 The function to create the trampoline,
139 mono_arch_create_rgctx_lazy_fetch_trampoline(), gets passed an encoded
140 slot number.  Use the macro MONO_RGCTX_SLOT_IS_MRGCTX to query whether
141 a trampoline for an MRGCTX is needed, as opposed to one for a RGCTX.
142 Use MONO_RGCTX_SLOT_INDEX to get the index of the slot (like 2 for
143 "slot 2" as above).
144
145
146 * Getting generics information about a stack frame
147
148 If a method is compiled with generic sharing, its MonoJitInfo has
149 has_generic_jit_info set.  In that case, the MonoJitInfo is followed
150 (after the MonoJitExceptionInfo array) by a MonoGenericJitInfo.
151
152 The MonoGenericJitInfo contains information about the location of the
153 this/vtable/MRGCTX variable, if the has_this flag is set.  If that is
154 the case, there are two possibilities:
155
156   1. this_in_reg is set.  this_reg is the number of the register where
157      the variable is stored.
158
159   2. this_in_reg is not set.  The variable is stored at offset
160      this_offset from the address in the register with number
161      this_reg.
162
163 The variable can either point to the "this" object, to a vtable or to
164 an MRGCTX:
165
166   1. If the method is a non-generic non-static method of a reference
167      type, the variable points to the "this" object.
168
169   2. If the method is a non-generic static method or a non-generic
170      method of a value type, the variable points to the vtable of the
171      class.
172
173   3. If the method is a generic method, the variable points to the
174      MRGCTX of the method.
175
176
177 * Layout of the MRGCTX
178
179 The MRGCTX is a structure that starts with
180 MonoMethodRuntimeGenericContext, which contains a pointer to the
181 vtable of the class and a pointer to the MonoGenericInst with the type
182 arguments for the method.
183
184
185 * Blog posts about generic code sharing
186
187 http://schani.wordpress.com/2007/09/22/generics-sharing-in-mono/
188 http://schani.wordpress.com/2007/10/12/the-trouble-with-shared-generics/
189 http://schani.wordpress.com/2007/10/15/a-quick-generics-sharing-update/
190 http://schani.wordpress.com/2008/01/29/other-types/
191 http://schani.wordpress.com/2008/02/25/generic-types-are-lazy/
192 http://schani.wordpress.com/2008/03/10/sharing-static-methods/
193 http://schani.wordpress.com/2008/04/22/sharing-everything-and-saving-memory/
194 http://schani.wordpress.com/2008/06/02/sharing-generic-methods/
195 http://schani.wordpress.com/2008/06/27/another-generic-sharing-update/