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