521f457103104640d30d52f96e65503dc4e7b40f
[mono.git] / mcs / mcs / TODO
1 Anonymous methods
2 -----------------
3
4
5 Iterators
6 ---------
7
8         * Study side effects with assign
9         * Study TemporaryStorage/LocalStorage -> Merge/rename
10
11 Instance idea
12 -------------
13
14         It would be nice to have things that can be "instances" to have an
15         EmitInstance method (this would default to nothing).
16
17         The idea is to be able to use efficiently the instance data on stack
18         manipulations, as opposed to the current scheme, where we basically have
19         a few special cases.
20
21 Optimization ideas
22 ------------------
23
24         Currently when we build a type cache, it contains private members,
25         internal members, and internal protected members;   We should trim
26         these out, as it shows up on the profile.
27
28         We create too many Arraylists;  When we know the size, we should create
29         an array;
30
31         During parsing we use arraylists to accumulate data, like this:
32
33                 thing:
34                 
35                 thing_list
36                         : thing { $$ =new ArrayList (); $$.Add ($1); }
37                         | thing_list thing { ArrayList a = $1; a.Add ($2); $$ = a; }
38
39         We probably could start using "Pairs" there:
40
41                 thing_list
42                         : thing { $$ = new Pair ($1, null); }
43                         | thing_list thing { Pair p = $1; $$ = new Pair ($2, $1); }
44
45
46 Anonymous Methods
47 -----------------
48
49         Plan:
50
51                 * Resolve anonymous methods before.
52                 * Each time a Local matches, if the mode is `InAnonymous', flag
53                   the VariableInfo for `proxying'.
54                 * During Resolve track the depth required for local variables.
55                 * Before Emit, create proxy classes with proper depth.
56                 * Emit.
57
58         Return Type:
59                 During Resolve, track all the return types.
60                 Allow for ec.ReturnType to be null, indicating `Pending Return Evaluation' 
61
62
63         Open question:
64                 Create a toplevel block for anonymous methods?  
65
66 EmitContext.ResolveTypeTree
67 ---------------------------
68
69         We should investigate its usage.  The problem is that by default
70         this will be set when calling FindType, that triggers a more expensive
71         lookup.
72
73         I believe we should pass the current EmitContext (which has this turned off
74         by default) to ResolveType/REsolveTypeExpr and then have the routines that
75         need ResolveType to pass null as the emit context.
76
77 DeclareLocal audit
78 ------------------
79
80         DeclareLocal is used in various statements.  The audit should be done
81         in two steps:
82
83                 * Identify all the declare locals.
84
85                 * Identify its uses.
86
87                 * Find if we can make wrapper functions for all of them.
88
89         Then we can move DeclareLocal into a helper class.
90
91         This is required to fix foreach in iterators.
92
93 Large project:
94 --------------
95
96         Drop FindMembers as our API and instead extract all the data
97         out of a type the first time into our own datastructures, and
98         use that to navigate and search the type instead of the
99         callback based FindMembers.     
100
101         Martin has some some of this work with his TypeHandle code
102         that we could use for this.
103
104 Notes on memory allocation
105 --------------------------
106
107         Outdated:
108
109         A run of the AllocationProfile shows that the compiler allocates roughly
110         30 megabytes of strings.  From those, 20 megabytes come from
111         LookupType.  
112
113         See the notes on current_container problems below on memory usage.  
114
115 LookupTypeReflection:
116 ---------------------
117
118         With something like `System.Object', LookupTypeReflection will be called
119         twice: once to find out that `System' is not a type and once
120         for System.Object.
121
122         This is required because System.Reflection requires that the type/nested types are
123         not separated by a dot but by a plus sign.
124
125         A nested class would be My+Class (My being the toplevel, Class the nested one).
126
127         It is interesting to look at the most called lookups when bootstrapping MCS:
128
129     647 LTR: ArrayList
130     713 LTR: System.Globalization
131     822 LTR: System.Object+Expression
132     904 LTR: Mono.CSharp.ArrayList
133     976 LTR: System.Runtime.CompilerServices
134     999 LTR: Type
135    1118 LTR: System.Runtime
136    1208 LTR: Mono.CSharp.Type
137    1373 LTR: Mono.Languages
138    1599 LTR: System.Diagnostics
139    2036 LTR: System.Text
140    2302 LTR: System.Reflection.Emit
141    2515 LTR: System.Collections
142    4527 LTR: System.Reflection
143   22273 LTR: Mono.CSharp
144   24245 LTR: System
145   27005 LTR: Mono
146
147         Analysis:
148                 The top 9 lookups are done for things which are not types.
149
150                 Mono.CSharp.Type happens to be a common lookup: the class Type
151                 used heavily in the compiler in the default namespace.
152
153                 RED FLAG:
154
155                 Then `Type' is looked up alone a lot of the time, this happens
156                 in parameter declarations and am not entirely sure that this is
157                 correct (FindType will pass to LookupInterfaceOrClass a the current_type.FullName,
158                 which for some reason is null!).  This seems to be a problem with a lost
159                 piece of context during FindType.
160
161                 System.Object is also used a lot as a toplevel class, and we assume it will
162                 have children, we should just shortcut this.
163
164     A cache:
165
166         Adding a cache and adding a catch for `System.Object' to flag that it wont be the
167         root of a hierarchy reduced the MCS bootstrap time from 10.22 seconds to 8.90 seconds.
168
169         This cache is currently enabled with SIMPLE_SPEEDUP in typemanager.cs.  Memory consumption
170         went down from 74 megs to 65 megs with this change.  
171
172 Ideas:
173 ------
174
175         Instead of the hack that *knows* about System.Object not having any children classes,
176         we should just make it simple for a probe to know that there is no need for it.
177
178 The use of DottedName
179 ---------------------
180
181         We could probably use a different system to represent names, like this:
182
183         class Name {
184                 string simplename;
185                 Name parent;
186         }
187
188         So `System.ComponentModel' becomes:
189
190                 x: (System, null)
191                 y: (ComponentModel, x)
192
193         The problem is that we would still need to construct the name to pass to
194         GetType.
195
196         This has been now implemented, its called "QualifiedIdentifier"
197
198 current_container/current_namespace and the DeclSpace
199 -----------------------------------------------------
200
201         We are storing fully qualified names in the DeclSpace instead of the node,
202         this is because `current_namespace' (Namepsace) is not a DeclSpace like
203         `current_container'.
204
205         The reason for storing the full names today is this:
206
207         namespace X {
208                 class Y {
209                 }
210         }
211
212         namespace A {
213                 class Y {
214                 }
215         }
216
217         The problem is that we only use the namespace stack to track the "prefix"
218         for typecontainers, but they are not typecontainers themselves, so we have
219         to use fully qualified names, because both A.X and A.Y would be entered
220         in the toplevel type container.  If we use the short names, there would be
221         a name clash.
222
223         To fix this problem, we have to make namespaces DeclSpaces.
224
225         The full size, contrasted with the size that could be stored is:
226                 corlib:
227                         Size of strings held: 368901
228                         Size of strings short: 147863
229
230                 System:
231                         Size of strings held: 212677
232                         Size of strings short: 97521
233                 
234                 System.XML:
235                         Size of strings held: 128055
236                         Size of strings short: 35782
237                 
238                 System.Data:
239                         Size of strings held: 117896
240                         Size of strings short: 36153
241                 
242                 System.Web:
243                         Size of strings held: 194527
244                         Size of strings short: 58064
245                 
246                 System.Windows.Forms:
247                         Size of strings held: 220495
248                         Size of strings short: 64923
249
250         
251 TODO:
252
253         1. Create a "partial" emit context for each TypeContainer..
254
255         2. EmitContext should be partially constructed.  No IL Generator.
256
257         interface_type review.
258
259         parameter_array, line 952: `note: must be a single dimension array type'.  Validate this
260
261 Dead Code Elimination bugs:
262 ---------------------------
263
264         I should also resolve all the children expressions in Switch, Fixed, Using.
265
266 Major tasks:
267 ------------
268
269         Pinned and volatile require type modifiers that can not be encoded
270         with Reflection.Emit.
271
272         Properties and 17.6.3: Finish it.
273
274         Implement base indexer access.
275
276 readonly variables and ref/out
277         
278 BUGS
279 ----
280
281 * Check for Final when overriding, if the parent is Final, then we cant
282   allow an override.
283
284 * Interface indexers
285
286         I have not figured out why the Microsoft version puts an
287         `instance' attribute, and I am not generating this `instance' attribute.
288
289         Explanation: The reason for the `instance' attribute on
290         indexers is that indexers only apply to instances
291
292 * Break/Continue statements
293
294         A finally block should reset the InLoop/LoopBegin/LoopEnd, as
295         they are logically outside the scope of the loop.
296
297 * Break/continue part 2.
298
299         They should transfer control to the finally block if inside a try/catch
300         block.
301
302 * Method Registration and error CS111
303
304         The way we use the method registration to signal 111 is wrong.
305         
306         Method registration should only be used to register methodbuilders,
307         we need an alternate method of checking for duplicates.
308
309 *
310 > // CSC sets beforefieldinit
311 > class X {
312 >   // .cctor will be generated by compiler
313 >   public static readonly object O = new System.Object ();
314 >   public static void Main () {}
315 > }
316
317
318 PENDING TASKS
319 -------------
320
321 * Merge test 89 and test-34
322
323 * Revisit
324
325         Primary-expression, as it has now been split into 
326         non-array-creation-expression and array-creation-expression.
327                 
328 * Code cleanup
329
330         The information when registering a method in InternalParameters
331         is duplicated, you can always get the types from the InternalParameters
332
333 * Emit modreq for volatiles
334
335         Handle modreq from public apis.
336
337 * Emit `pinned' for pinned local variables.
338
339         Both `modreq' and pinned will require special hacks in the compiler.
340
341 * Make sure that we are pinning the right variable
342
343 * Merge tree.cs, rootcontext.cs
344
345 OPTIMIZATIONS
346 -------------
347
348 * User Defined Conversions is doing way too many calls to do union sets that are not needed
349
350 * Add test case for destructors
351
352 * Places that use `Ldelema' are basically places where I will be
353   initializing a value type.  I could apply an optimization to 
354   disable the implicit local temporary from being created (by using
355   the method in New).
356
357 * Dropping TypeContainer as an argument to EmitContext
358
359         My theory is that I can get rid of the TypeBuilder completely from
360         the EmitContext, and have typecasts where it is used (from
361         DeclSpace to where it matters).  
362
363         The only pending problem is that the code that implements Aliases
364         is on TypeContainer, and probably should go in DeclSpace.
365
366 * Use of local temporary in UnaryMutator
367
368         We should get rid of the Localtemporary there for some cases
369
370         This turns out to be very complex, at least for the post-version,
371         because this case:
372
373                 a = i++
374
375         To produce optimal code, it is necessary for UnaryMutator to know 
376         that it is being assigned to a variable (the way the stack is laid
377         out using dup requires the store to happen inside UnaryMutator).
378
379 * Tests
380
381         Write tests for the various reference conversions.  We have
382         test for all the numeric conversions.
383
384 * Optimizations
385
386         In Indexers and Properties, probably support an EmitWithDup
387         That emits the code to call Get and then leaves a this pointer
388         in the stack, so that later a Store can be emitted using that
389         this pointer (consider Property++ or Indexer++)
390
391 * Optimizations: variable allocation.
392
393         When local variables of a type are required, we should request
394         the variable and later release it when we are done, so that
395         the same local variable slot can be reused later on.
396
397 * Add a cache for the various GetArrayMethod operations.
398
399 * MakeUnionSet Callers
400
401         If the types are the same, there is no need to compute the unionset,
402         we can just use the list from one of the types.
403
404 * Factor the lookup code for class declarations an interfaces
405   (interface.cs:GetInterfaceByName)
406
407 RECOMMENDATIONS
408 ---------------
409
410 * Use of lexer.Location in the parser
411
412         Currently we do:
413
414         TOKEN nt TERMINAL nt TERMINAL nt3 {
415                 $$ = new Blah ($2, $4, $6, lexer.Location);
416         }
417
418         This is bad, because the lexer.Location is for the last item in `nt3'
419
420         We need to change that to use this pattern:
421
422         TOKEN { oob_stack.Push (lexer.Location) } nt TERMINAL nt TERMINAL nt3 {
423                 $$ = new Blah ($3, $5, $7, (Location) oob_stack.Pop ());
424         }
425
426         Notice how numbering of the arguments changes as the
427         { oob_stack.Push (lexer.Location) } takes a "slot"  in the productions.
428
429 * local_variable_declaration
430
431         Not sure that this grammar is correct, we might have to
432         resolve this during semantic analysis.
433