Add cleanup call.
[mono.git] / mcs / mcs / TODO
1 Notes on memory allocation
2 --------------------------
3
4         A run of the AllocationProfile shows that the compiler allocates roughly
5         30 megabytes of strings.  From those, 20 megabytes come from
6         LookupType.  
7
8         See the notes on current_container problems below on memory usage.  
9
10 GetNamespaces
11 -------------
12
13         Obtaining the list of namespaces is an expensive process because
14         Reflection.Emit does not provide a quick way of pulling the data out,
15         and it is too slow to load it.
16
17         Calling GetNamespaces on my machine (1Ghz):
18
19                 * Takes half a second with the standard assemblies (corlib + System);
20                   Fetching the types from it takes 0.0028650 seconds. 
21
22                 * Loading the top 10 largest assemblies we ship with Mono makes MCS take 
23                   8 seconds to startup the first time, subsequent invocations take 2 seconds.
24
25                   Fetching all the types (Assembly.GetTypes ()) for all the assemblies takes
26                   0.0069170 seconds.
27
28         So pulling all the types takes very little time, maybe we should look into our
29         Hashtable implementation to make it more optimal.
30
31         This prohibits re-writting SimpleName to take advantage of
32         knowing the namespace names in advance.  Knowing the namespaces in advance
33         would allow me to reduce the guesswork in which we are currently engaged
34         to find a type definition.
35
36 LookupTypeReflection:
37 ---------------------
38
39         With something like `System.Object', LookupTypeReflection will be called
40         twice: once to find out that `System' is not a type and once
41         for System.Object.
42
43         This is required because System.Reflection requires that the type/nested types are
44         not separated by a dot but by a plus sign.
45
46         A nested class would be My+Class (My being the toplevel, Class the nested one).
47
48         It is interesting to look at the most called lookups when bootstrapping MCS:
49
50     647 LTR: ArrayList
51     713 LTR: System.Globalization
52     822 LTR: System.Object+Expression
53     904 LTR: Mono.CSharp.ArrayList
54     976 LTR: System.Runtime.CompilerServices
55     999 LTR: Type
56    1118 LTR: System.Runtime
57    1208 LTR: Mono.CSharp.Type
58    1373 LTR: Mono.Languages
59    1599 LTR: System.Diagnostics
60    2036 LTR: System.Text
61    2302 LTR: System.Reflection.Emit
62    2515 LTR: System.Collections
63    4527 LTR: System.Reflection
64   22273 LTR: Mono.CSharp
65   24245 LTR: System
66   27005 LTR: Mono
67
68         Analysis:
69                 The top 9 lookups are done for things which are not types.
70
71                 Mono.CSharp.Type happens to be a common lookup: the class Type
72                 used heavily in the compiler in the default namespace.
73
74                 RED FLAG:
75
76                 Then `Type' is looked up alone a lot of the time, this happens
77                 in parameter declarations and am not entirely sure that this is
78                 correct (FindType will pass to LookupInterfaceOrClass a the current_type.FullName,
79                 which for some reason is null!).  This seems to be a problem with a lost
80                 piece of context during FindType.
81
82                 System.Object is also used a lot as a toplevel class, and we assume it will
83                 have children, we should just shortcut this.
84
85     A cache:
86
87         Adding a cache and adding a catch for `System.Object' to flag that it wont be the
88         root of a hierarchy reduced the MCS bootstrap time from 10.22 seconds to 8.90 seconds.
89
90         This cache is currently enabled with SIMPLE_SPEEDUP in typemanager.cs.  Memory consumption
91         went down from 74 megs to 65 megs with this change.  
92
93 Ideas:
94 ------
95
96         Instead of the hack that *knows* about System.Object not having any children classes,
97         we should just make it simple for a probe to know that there is no need for it.
98
99 The use of DottedName
100 ---------------------
101
102         We could probably use a different system to represent names, like this:
103
104         class Name {
105                 string simplename;
106                 Name parent;
107         }
108
109         So `System.ComponentModel' becomes:
110
111                 x: (System, null)
112                 y: (ComponentModel, x)
113
114         The problem is that we would still need to construct the name to pass to
115         GetType.
116
117 current_container/current_namespace and the DeclSpace
118 -----------------------------------------------------
119
120         We are storing fully qualified names in the DeclSpace instead of the node,
121         this is because `current_namespace' (Namepsace) is not a DeclSpace like
122         `current_container'.
123
124         The reason for storing the full names today is this:
125
126         namespace X {
127                 class Y {
128                 }
129         }
130
131         namespace A {
132                 class Y {
133                 }
134         }
135
136         The problem is that we only use the namespace stack to track the "prefix"
137         for typecontainers, but they are not typecontainers themselves, so we have
138         to use fully qualified names, because both A.X and A.Y would be entered
139         in the toplevel type container.  If we use the short names, there would be
140         a name clash.
141
142         To fix this problem, we have to make namespaces DeclSpaces.
143
144         The full size, contrasted with the size that could be stored is:
145                 corlib:
146                         Size of strings held: 368901
147                         Size of strings short: 147863
148
149                 System:
150                         Size of strings held: 212677
151                         Size of strings short: 97521
152                 
153                 System.XML:
154                         Size of strings held: 128055
155                         Size of strings short: 35782
156                 
157                 System.Data:
158                         Size of strings held: 117896
159                         Size of strings short: 36153
160                 
161                 System.Web:
162                         Size of strings held: 194527
163                         Size of strings short: 58064
164                 
165                 System.Windows.Forms:
166                         Size of strings held: 220495
167                         Size of strings short: 64923
168
169         
170 TODO:
171
172         1. Create a "partial" emit context for each TypeContainer..
173
174         2. EmitContext should be partially constructed.  No IL Generator.
175
176         interface_type review.
177
178         parameter_array, line 952: `note: must be a single dimension array type'.  Validate this
179
180 Dead Code Elimination bugs:
181 ---------------------------
182
183         I should also resolve all the children expressions in Switch, Fixed, Using.
184
185 Major tasks:
186 ------------
187
188         Pinned and volatile require type modifiers that can not be encoded
189         with Reflection.Emit.
190
191         Properties and 17.6.3: Finish it.
192
193         Implement base indexer access.
194
195 readonly variables and ref/out
196         
197 BUGS
198 ----
199
200 * Check for Final when overriding, if the parent is Final, then we cant
201   allow an override.
202
203 * Interface indexers
204
205         I have not figured out why the Microsoft version puts an
206         `instance' attribute, and I am not generating this `instance' attribute.
207
208         Explanation: The reason for the `instance' attribute on
209         indexers is that indexers only apply to instances
210
211 * Break/Continue statements
212
213         A finally block should reset the InLoop/LoopBegin/LoopEnd, as
214         they are logically outside the scope of the loop.
215
216 * Break/continue part 2.
217
218         They should transfer control to the finally block if inside a try/catch
219         block.
220
221 * Method Registration and error CS111
222
223         The way we use the method registration to signal 111 is wrong.
224         
225         Method registration should only be used to register methodbuilders,
226         we need an alternate method of checking for duplicates.
227
228 *
229 > // CSC sets beforefieldinit
230 > class X {
231 >   // .cctor will be generated by compiler
232 >   public static readonly object O = new System.Object ();
233 >   public static void Main () {}
234 > }
235
236
237 PENDING TASKS
238 -------------
239
240 * Merge test 89 and test-34
241
242 * Revisit
243
244         Primary-expression, as it has now been split into 
245         non-array-creation-expression and array-creation-expression.
246                 
247 * Code cleanup
248
249         The information when registering a method in InternalParameters
250         is duplicated, you can always get the types from the InternalParameters
251
252 * Emit modreq for volatiles
253
254         Handle modreq from public apis.
255
256 * Emit `pinned' for pinned local variables.
257
258         Both `modreq' and pinned will require special hacks in the compiler.
259
260 * Make sure that we are pinning the right variable
261
262 * Merge tree.cs, rootcontext.cs
263
264 OPTIMIZATIONS
265 -------------
266
267 * User Defined Conversions is doing way too many calls to do union sets that are not needed
268
269 * Add test case for destructors
270
271 * Places that use `Ldelema' are basically places where I will be
272   initializing a value type.  I could apply an optimization to 
273   disable the implicit local temporary from being created (by using
274   the method in New).
275
276 * Dropping TypeContainer as an argument to EmitContext
277
278         My theory is that I can get rid of the TypeBuilder completely from
279         the EmitContext, and have typecasts where it is used (from
280         DeclSpace to where it matters).  
281
282         The only pending problem is that the code that implements Aliases
283         is on TypeContainer, and probably should go in DeclSpace.
284
285 * Use of local temporary in UnaryMutator
286
287         We should get rid of the Localtemporary there for some cases
288
289         This turns out to be very complex, at least for the post-version,
290         because this case:
291
292                 a = i++
293
294         To produce optimal code, it is necessary for UnaryMutator to know 
295         that it is being assigned to a variable (the way the stack is laid
296         out using dup requires the store to happen inside UnaryMutator).
297
298 * Emitcontext
299
300         Do we really need to instanciate this variable all the time?
301
302         It could be static for all we care, and just use it for making
303         sure that there are no recursive invocations on it.
304
305 * Tests
306
307         Write tests for the various reference conversions.  We have
308         test for all the numeric conversions.
309
310 * Optimizations
311
312         In Indexers and Properties, probably support an EmitWithDup
313         That emits the code to call Get and then leaves a this pointer
314         in the stack, so that later a Store can be emitted using that
315         this pointer (consider Property++ or Indexer++)
316
317 * Optimizations: variable allocation.
318
319         When local variables of a type are required, we should request
320         the variable and later release it when we are done, so that
321         the same local variable slot can be reused later on.
322
323 * Add a cache for the various GetArrayMethod operations.
324
325 * TypeManager.FindMembers:
326
327         Instead of having hundreds of builder_to_blah hash table, have
328         a single one that maps a TypeBuilder `t' to a set of classes
329         that implement an interface that supports FindMembers.
330
331 * MakeUnionSet Callers
332
333         If the types are the same, there is no need to compute the unionset,
334         we can just use the list from one of the types.
335
336 * Factor the lookup code for class declarations an interfaces
337   (interface.cs:GetInterfaceByName)
338
339 RECOMMENDATIONS
340 ---------------
341
342 * Use of lexer.Location in the parser
343
344         Currently we do:
345
346         TOKEN nt TERMINAL nt TERMINAL nt3 {
347                 $$ = new Blah ($2, $4, $6, lexer.Location);
348         }
349
350         This is bad, because the lexer.Location is for the last item in `nt3'
351
352         We need to change that to use this pattern:
353
354         TOKEN { oob_stack.Push (lexer.Location) } nt TERMINAL nt TERMINAL nt3 {
355                 $$ = new Blah ($3, $5, $7, (Location) oob_stack.Pop ());
356         }
357
358         Notice how numbering of the arguments changes as the
359         { oob_stack.Push (lexer.Location) } takes a "slot"  in the productions.
360
361 * local_variable_declaration
362
363         Not sure that this grammar is correct, we might have to
364         resolve this during semantic analysis.
365