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