1 EmitContext.ResolveTypeTree
2 ---------------------------
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
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.
15 Keep a cache of name lookups at the DeclSpace level
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.
25 Martin has some some of this work with his TypeHandle code
26 that we could use for this.
28 Notes on memory allocation
29 --------------------------
31 A run of the AllocationProfile shows that the compiler allocates roughly
32 30 megabytes of strings. From those, 20 megabytes come from
35 See the notes on current_container problems below on memory usage.
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.
44 Calling GetNamespaces on my machine (1Ghz):
46 * Takes half a second with the standard assemblies (corlib + System);
47 Fetching the types from it takes 0.0028650 seconds.
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.
52 Fetching all the types (Assembly.GetTypes ()) for all the assemblies takes
55 So pulling all the types takes very little time, maybe we should look into our
56 Hashtable implementation to make it more optimal.
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.
66 With something like `System.Object', LookupTypeReflection will be called
67 twice: once to find out that `System' is not a type and once
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.
73 A nested class would be My+Class (My being the toplevel, Class the nested one).
75 It is interesting to look at the most called lookups when bootstrapping MCS:
78 713 LTR: System.Globalization
79 822 LTR: System.Object+Expression
80 904 LTR: Mono.CSharp.ArrayList
81 976 LTR: System.Runtime.CompilerServices
83 1118 LTR: System.Runtime
84 1208 LTR: Mono.CSharp.Type
85 1373 LTR: Mono.Languages
86 1599 LTR: System.Diagnostics
88 2302 LTR: System.Reflection.Emit
89 2515 LTR: System.Collections
90 4527 LTR: System.Reflection
91 22273 LTR: Mono.CSharp
96 The top 9 lookups are done for things which are not types.
98 Mono.CSharp.Type happens to be a common lookup: the class Type
99 used heavily in the compiler in the default namespace.
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.
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.
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.
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.
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.
126 The use of DottedName
127 ---------------------
129 We could probably use a different system to represent names, like this:
136 So `System.ComponentModel' becomes:
139 y: (ComponentModel, x)
141 The problem is that we would still need to construct the name to pass to
144 current_container/current_namespace and the DeclSpace
145 -----------------------------------------------------
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
151 The reason for storing the full names today is this:
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
169 To fix this problem, we have to make namespaces DeclSpaces.
171 The full size, contrasted with the size that could be stored is:
173 Size of strings held: 368901
174 Size of strings short: 147863
177 Size of strings held: 212677
178 Size of strings short: 97521
181 Size of strings held: 128055
182 Size of strings short: 35782
185 Size of strings held: 117896
186 Size of strings short: 36153
189 Size of strings held: 194527
190 Size of strings short: 58064
192 System.Windows.Forms:
193 Size of strings held: 220495
194 Size of strings short: 64923
199 1. Create a "partial" emit context for each TypeContainer..
201 2. EmitContext should be partially constructed. No IL Generator.
203 interface_type review.
205 parameter_array, line 952: `note: must be a single dimension array type'. Validate this
207 Dead Code Elimination bugs:
208 ---------------------------
210 I should also resolve all the children expressions in Switch, Fixed, Using.
215 Pinned and volatile require type modifiers that can not be encoded
216 with Reflection.Emit.
218 Properties and 17.6.3: Finish it.
220 Implement base indexer access.
222 readonly variables and ref/out
227 * Check for Final when overriding, if the parent is Final, then we cant
232 I have not figured out why the Microsoft version puts an
233 `instance' attribute, and I am not generating this `instance' attribute.
235 Explanation: The reason for the `instance' attribute on
236 indexers is that indexers only apply to instances
238 * Break/Continue statements
240 A finally block should reset the InLoop/LoopBegin/LoopEnd, as
241 they are logically outside the scope of the loop.
243 * Break/continue part 2.
245 They should transfer control to the finally block if inside a try/catch
248 * Method Registration and error CS111
250 The way we use the method registration to signal 111 is wrong.
252 Method registration should only be used to register methodbuilders,
253 we need an alternate method of checking for duplicates.
256 > // CSC sets beforefieldinit
258 > // .cctor will be generated by compiler
259 > public static readonly object O = new System.Object ();
260 > public static void Main () {}
267 * Merge test 89 and test-34
271 Primary-expression, as it has now been split into
272 non-array-creation-expression and array-creation-expression.
276 The information when registering a method in InternalParameters
277 is duplicated, you can always get the types from the InternalParameters
279 * Emit modreq for volatiles
281 Handle modreq from public apis.
283 * Emit `pinned' for pinned local variables.
285 Both `modreq' and pinned will require special hacks in the compiler.
287 * Make sure that we are pinning the right variable
289 * Merge tree.cs, rootcontext.cs
294 * User Defined Conversions is doing way too many calls to do union sets that are not needed
296 * Add test case for destructors
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
303 * Dropping TypeContainer as an argument to EmitContext
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).
309 The only pending problem is that the code that implements Aliases
310 is on TypeContainer, and probably should go in DeclSpace.
312 * Use of local temporary in UnaryMutator
314 We should get rid of the Localtemporary there for some cases
316 This turns out to be very complex, at least for the post-version,
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).
327 Do we really need to instanciate this variable all the time?
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.
334 Write tests for the various reference conversions. We have
335 test for all the numeric conversions.
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++)
344 * Optimizations: variable allocation.
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.
350 * Add a cache for the various GetArrayMethod operations.
352 * TypeManager.FindMembers:
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.
358 * MakeUnionSet Callers
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.
363 * Factor the lookup code for class declarations an interfaces
364 (interface.cs:GetInterfaceByName)
369 * Use of lexer.Location in the parser
373 TOKEN nt TERMINAL nt TERMINAL nt3 {
374 $$ = new Blah ($2, $4, $6, lexer.Location);
377 This is bad, because the lexer.Location is for the last item in `nt3'
379 We need to change that to use this pattern:
381 TOKEN { oob_stack.Push (lexer.Location) } nt TERMINAL nt TERMINAL nt3 {
382 $$ = new Blah ($3, $5, $7, (Location) oob_stack.Pop ());
385 Notice how numbering of the arguments changes as the
386 { oob_stack.Push (lexer.Location) } takes a "slot" in the productions.
388 * local_variable_declaration
390 Not sure that this grammar is correct, we might have to
391 resolve this during semantic analysis.