8 * Study side effects with assign
9 * Study TemporaryStorage/LocalStorage -> Merge/rename
14 It would be nice to have things that can be "instances" to have an
15 EmitInstance method (this would default to nothing).
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
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.
28 We create too many Arraylists; When we know the size, we should create
31 During parsing we use arraylists to accumulate data, like this:
36 : thing { $$ =new ArrayList (); $$.Add ($1); }
37 | thing_list thing { ArrayList a = $1; a.Add ($2); $$ = a; }
39 We probably could start using "Pairs" there:
42 : thing { $$ = new Pair ($1, null); }
43 | thing_list thing { Pair p = $1; $$ = new Pair ($2, $1); }
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.
59 During Resolve, track all the return types.
60 Allow for ec.ReturnType to be null, indicating `Pending Return Evaluation'
64 Create a toplevel block for anonymous methods?
66 EmitContext.ResolveTypeTree
67 ---------------------------
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
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.
80 DeclareLocal is used in various statements. The audit should be done
83 * Identify all the declare locals.
87 * Find if we can make wrapper functions for all of them.
89 Then we can move DeclareLocal into a helper class.
91 This is required to fix foreach in iterators.
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.
101 Martin has some some of this work with his TypeHandle code
102 that we could use for this.
104 Notes on memory allocation
105 --------------------------
109 A run of the AllocationProfile shows that the compiler allocates roughly
110 30 megabytes of strings. From those, 20 megabytes come from
113 See the notes on current_container problems below on memory usage.
115 LookupTypeReflection:
116 ---------------------
118 With something like `System.Object', LookupTypeReflection will be called
119 twice: once to find out that `System' is not a type and once
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.
125 A nested class would be My+Class (My being the toplevel, Class the nested one).
127 It is interesting to look at the most called lookups when bootstrapping MCS:
130 713 LTR: System.Globalization
131 822 LTR: System.Object+Expression
132 904 LTR: Mono.CSharp.ArrayList
133 976 LTR: System.Runtime.CompilerServices
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
148 The top 9 lookups are done for things which are not types.
150 Mono.CSharp.Type happens to be a common lookup: the class Type
151 used heavily in the compiler in the default namespace.
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.
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.
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.
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.
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.
178 The use of DottedName
179 ---------------------
181 We could probably use a different system to represent names, like this:
188 So `System.ComponentModel' becomes:
191 y: (ComponentModel, x)
193 The problem is that we would still need to construct the name to pass to
196 This has been now implemented, its called "QualifiedIdentifier"
198 current_container/current_namespace and the DeclSpace
199 -----------------------------------------------------
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
205 The reason for storing the full names today is this:
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
223 To fix this problem, we have to make namespaces DeclSpaces.
225 The full size, contrasted with the size that could be stored is:
227 Size of strings held: 368901
228 Size of strings short: 147863
231 Size of strings held: 212677
232 Size of strings short: 97521
235 Size of strings held: 128055
236 Size of strings short: 35782
239 Size of strings held: 117896
240 Size of strings short: 36153
243 Size of strings held: 194527
244 Size of strings short: 58064
246 System.Windows.Forms:
247 Size of strings held: 220495
248 Size of strings short: 64923
253 1. Create a "partial" emit context for each TypeContainer..
255 2. EmitContext should be partially constructed. No IL Generator.
257 interface_type review.
259 parameter_array, line 952: `note: must be a single dimension array type'. Validate this
261 Dead Code Elimination bugs:
262 ---------------------------
264 I should also resolve all the children expressions in Switch, Fixed, Using.
269 Pinned and volatile require type modifiers that can not be encoded
270 with Reflection.Emit.
272 Properties and 17.6.3: Finish it.
274 Implement base indexer access.
276 readonly variables and ref/out
281 * Check for Final when overriding, if the parent is Final, then we cant
286 I have not figured out why the Microsoft version puts an
287 `instance' attribute, and I am not generating this `instance' attribute.
289 Explanation: The reason for the `instance' attribute on
290 indexers is that indexers only apply to instances
292 * Break/Continue statements
294 A finally block should reset the InLoop/LoopBegin/LoopEnd, as
295 they are logically outside the scope of the loop.
297 * Break/continue part 2.
299 They should transfer control to the finally block if inside a try/catch
302 * Method Registration and error CS111
304 The way we use the method registration to signal 111 is wrong.
306 Method registration should only be used to register methodbuilders,
307 we need an alternate method of checking for duplicates.
310 > // CSC sets beforefieldinit
312 > // .cctor will be generated by compiler
313 > public static readonly object O = new System.Object ();
314 > public static void Main () {}
321 * Merge test 89 and test-34
325 Primary-expression, as it has now been split into
326 non-array-creation-expression and array-creation-expression.
330 The information when registering a method in InternalParameters
331 is duplicated, you can always get the types from the InternalParameters
333 * Emit modreq for volatiles
335 Handle modreq from public apis.
337 * Emit `pinned' for pinned local variables.
339 Both `modreq' and pinned will require special hacks in the compiler.
341 * Make sure that we are pinning the right variable
343 * Merge tree.cs, rootcontext.cs
348 * User Defined Conversions is doing way too many calls to do union sets that are not needed
350 * Add test case for destructors
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
357 * Dropping TypeContainer as an argument to EmitContext
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).
363 The only pending problem is that the code that implements Aliases
364 is on TypeContainer, and probably should go in DeclSpace.
366 * Use of local temporary in UnaryMutator
368 We should get rid of the Localtemporary there for some cases
370 This turns out to be very complex, at least for the post-version,
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).
381 Write tests for the various reference conversions. We have
382 test for all the numeric conversions.
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++)
391 * Optimizations: variable allocation.
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.
397 * Add a cache for the various GetArrayMethod operations.
399 * MakeUnionSet Callers
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.
404 * Factor the lookup code for class declarations an interfaces
405 (interface.cs:GetInterfaceByName)
410 * Use of lexer.Location in the parser
414 TOKEN nt TERMINAL nt TERMINAL nt3 {
415 $$ = new Blah ($2, $4, $6, lexer.Location);
418 This is bad, because the lexer.Location is for the last item in `nt3'
420 We need to change that to use this pattern:
422 TOKEN { oob_stack.Push (lexer.Location) } nt TERMINAL nt TERMINAL nt3 {
423 $$ = new Blah ($3, $5, $7, (Location) oob_stack.Pop ());
426 Notice how numbering of the arguments changes as the
427 { oob_stack.Push (lexer.Location) } takes a "slot" in the productions.
429 * local_variable_declaration
431 Not sure that this grammar is correct, we might have to
432 resolve this during semantic analysis.