-Major tasks:
-------------
+EmitContext.ResolveTypeTree
+---------------------------
- Apply the method verification process to indexers and properties as well.
+ We should investigate its usage. The problem is that by default
+ this will be set when calling FindType, that triggers a more expensive
+ lookup.
- Properties and 17.6.3: Finish it.
+ I believe we should pass the current EmitContext (which has this turned off
+ by default) to ResolveType/REsolveTypeExpr and then have the routines that
+ need ResolveType to pass null as the emit context.
-BUGS
+Idea
----
-* Adding variables.
+ Keep a cache of name lookups at the DeclSpace level
- We do add variables in a number of places, and this is erroneous:
+Large project:
+--------------
- void a (int b)
- {
- int b;
- }
+ Drop FindMembers as our API and instead extract all the data
+ out of a type the first time into our own datastructures, and
+ use that to navigate and search the type instead of the
+ callback based FindMembers.
+
+ Martin has some some of this work with his TypeHandle code
+ that we could use for this.
+
+Notes on memory allocation
+--------------------------
+
+ A run of the AllocationProfile shows that the compiler allocates roughly
+ 30 megabytes of strings. From those, 20 megabytes come from
+ LookupType.
+
+ See the notes on current_container problems below on memory usage.
+
+GetNamespaces
+-------------
+
+ Obtaining the list of namespaces is an expensive process because
+ Reflection.Emit does not provide a quick way of pulling the data out,
+ and it is too slow to load it.
+
+ Calling GetNamespaces on my machine (1Ghz):
+
+ * Takes half a second with the standard assemblies (corlib + System);
+ Fetching the types from it takes 0.0028650 seconds.
+
+ * Loading the top 10 largest assemblies we ship with Mono makes MCS take
+ 8 seconds to startup the first time, subsequent invocations take 2 seconds.
+
+ Fetching all the types (Assembly.GetTypes ()) for all the assemblies takes
+ 0.0069170 seconds.
+
+ So pulling all the types takes very little time, maybe we should look into our
+ Hashtable implementation to make it more optimal.
+
+ This prohibits re-writting SimpleName to take advantage of
+ knowing the namespace names in advance. Knowing the namespaces in advance
+ would allow me to reduce the guesswork in which we are currently engaged
+ to find a type definition.
+
+LookupTypeReflection:
+---------------------
+
+ With something like `System.Object', LookupTypeReflection will be called
+ twice: once to find out that `System' is not a type and once
+ for System.Object.
+
+ This is required because System.Reflection requires that the type/nested types are
+ not separated by a dot but by a plus sign.
+
+ A nested class would be My+Class (My being the toplevel, Class the nested one).
+
+ It is interesting to look at the most called lookups when bootstrapping MCS:
+
+ 647 LTR: ArrayList
+ 713 LTR: System.Globalization
+ 822 LTR: System.Object+Expression
+ 904 LTR: Mono.CSharp.ArrayList
+ 976 LTR: System.Runtime.CompilerServices
+ 999 LTR: Type
+ 1118 LTR: System.Runtime
+ 1208 LTR: Mono.CSharp.Type
+ 1373 LTR: Mono.Languages
+ 1599 LTR: System.Diagnostics
+ 2036 LTR: System.Text
+ 2302 LTR: System.Reflection.Emit
+ 2515 LTR: System.Collections
+ 4527 LTR: System.Reflection
+ 22273 LTR: Mono.CSharp
+ 24245 LTR: System
+ 27005 LTR: Mono
+
+ Analysis:
+ The top 9 lookups are done for things which are not types.
+
+ Mono.CSharp.Type happens to be a common lookup: the class Type
+ used heavily in the compiler in the default namespace.
+
+ RED FLAG:
+
+ Then `Type' is looked up alone a lot of the time, this happens
+ in parameter declarations and am not entirely sure that this is
+ correct (FindType will pass to LookupInterfaceOrClass a the current_type.FullName,
+ which for some reason is null!). This seems to be a problem with a lost
+ piece of context during FindType.
+
+ System.Object is also used a lot as a toplevel class, and we assume it will
+ have children, we should just shortcut this.
- Also:
+ A cache:
- void a (int b)
- {
- foreach (int b ...)
- ;
+ Adding a cache and adding a catch for `System.Object' to flag that it wont be the
+ root of a hierarchy reduced the MCS bootstrap time from 10.22 seconds to 8.90 seconds.
+
+ This cache is currently enabled with SIMPLE_SPEEDUP in typemanager.cs. Memory consumption
+ went down from 74 megs to 65 megs with this change.
+
+Ideas:
+------
+
+ Instead of the hack that *knows* about System.Object not having any children classes,
+ we should just make it simple for a probe to know that there is no need for it.
+
+The use of DottedName
+---------------------
+
+ We could probably use a different system to represent names, like this:
+
+ class Name {
+ string simplename;
+ Name parent;
}
-* Visibility
+ So `System.ComponentModel' becomes:
+
+ x: (System, null)
+ y: (ComponentModel, x)
- I am not reporting errors on visibility yet.
+ The problem is that we would still need to construct the name to pass to
+ GetType.
-* Interfaces
+current_container/current_namespace and the DeclSpace
+-----------------------------------------------------
- For indexers, the output of ix2.cs is different from our
- compiler and theirs. They use a DefaultMemberAttribute, which
- I have yet to figure out:
+ We are storing fully qualified names in the DeclSpace instead of the node,
+ this is because `current_namespace' (Namepsace) is not a DeclSpace like
+ `current_container'.
- .class interface private abstract auto ansi INTERFACE
- {
- .custom instance void [mscorlib]System.Reflection.DefaultMemberAttribute::.ctor(string)
- = ( 01 00 04 49 74 65 6D 00 00 ) // ...Item..
- ...
+ The reason for storing the full names today is this:
+
+ namespace X {
+ class Y {
+ }
}
-* Interface indexers
+ namespace A {
+ class Y {
+ }
+ }
- I have not figured out why the Microsoft version puts an
- `instance' attribute, and I am not generating this `instance' attribute.
+ The problem is that we only use the namespace stack to track the "prefix"
+ for typecontainers, but they are not typecontainers themselves, so we have
+ to use fully qualified names, because both A.X and A.Y would be entered
+ in the toplevel type container. If we use the short names, there would be
+ a name clash.
- Explanation: The reason for the `instance' attribute on
- indexers is that indexers only apply to instances
+ To fix this problem, we have to make namespaces DeclSpaces.
-* Handle destructors specially
+ The full size, contrasted with the size that could be stored is:
+ corlib:
+ Size of strings held: 368901
+ Size of strings short: 147863
- Turn ~X () { a () } into:
- void Finalize () { try { a (); } finally { base.Finalize (); } }
+ System:
+ Size of strings held: 212677
+ Size of strings short: 97521
+
+ System.XML:
+ Size of strings held: 128055
+ Size of strings short: 35782
+
+ System.Data:
+ Size of strings held: 117896
+ Size of strings short: 36153
+
+ System.Web:
+ Size of strings held: 194527
+ Size of strings short: 58064
+
+ System.Windows.Forms:
+ Size of strings held: 220495
+ Size of strings short: 64923
- The code is mostly done, but `base' is missing. The reason it is
- missing is because we have to implement visibility first.
+
+TODO:
-* Method Names
+ 1. Create a "partial" emit context for each TypeContainer..
- Method names could be; `IFACE.NAME' in the method declaration,
- stating that they implement a specific interface method.
+ 2. EmitContext should be partially constructed. No IL Generator.
- We currently fail to parse it.
+ interface_type review.
-* Arrays
+ parameter_array, line 952: `note: must be a single dimension array type'. Validate this
- We need to make sure at *compile time* that the arguments in
- the expression list of an array creation are always positive.
+Dead Code Elimination bugs:
+---------------------------
-* Implement dead code elimination in statement.cs
+ I should also resolve all the children expressions in Switch, Fixed, Using.
+
+Major tasks:
+------------
- It is pretty simple to implement dead code elimination in
- if/do/while
+ Pinned and volatile require type modifiers that can not be encoded
+ with Reflection.Emit.
-* Indexer bugs:
+ Properties and 17.6.3: Finish it.
- the following wont work:
+ Implement base indexer access.
- x [0] = x [1] = N
+readonly variables and ref/out
+
+BUGS
+----
- if x has indexers, the value of x [N] set is set to void. This needs to be
- fixed.
+* Check for Final when overriding, if the parent is Final, then we cant
+ allow an override.
-* Array declarations
+* Interface indexers
- Multi-dim arrays are declared as [,] instead of [0..,0..]
+ I have not figured out why the Microsoft version puts an
+ `instance' attribute, and I am not generating this `instance' attribute.
+
+ Explanation: The reason for the `instance' attribute on
+ indexers is that indexers only apply to instances
* Break/Continue statements
They should transfer control to the finally block if inside a try/catch
block.
-* Conversions and overflow
-
- I am not using the checked state while doing type casts,
- they should result in conv.ovf.XXX
-
* Method Registration and error CS111
The way we use the method registration to signal 111 is wrong.
Method registration should only be used to register methodbuilders,
we need an alternate method of checking for duplicates.
-* Mapping of methods
-
- Currently various hashtables fail because the Equals implementation
- for MethodBuilders is not complete enough. We could work around this
- by having our own Hashtable implementation.
-
-* We need to catch:
-
- extern string Property {
- get { }
- }
-
- The get there should only have a semicolon
-
*
> // CSC sets beforefieldinit
> class X {
PENDING TASKS
-------------
- * Implement Goto.
-
- * Unsafe code.
- Making the parser accept unsafe code.
-
- * Implement `base' (BaseAccess class)
-
- * Implement constant folding. We might need to implement
- a new `Constant' class and derive Literal from it.
+* Merge test 89 and test-34
-* OUT Variables passed as OUT variables.
+* Revisit
- Currently we pass the pointer to the pointer (see expression.cs:Argument.Emit)
-
-* Function Declarations
-
- Support PINvoke/Internallcall and extern declarated-functions.
-
-* Manual field layout in structures
-
-* Make the rules for inheritance/overriding apply to
- properties, operators and indexers (currently we only do this
- on methods).
-
-* Handle volatile
-
-* Support Re-Throw exceptions:
+ Primary-expression, as it has now been split into
+ non-array-creation-expression and array-creation-expression.
+
+* Code cleanup
- try {
- X ();
- } catch (SomeException e){
- LogIt ();
- throw;
- }
+ The information when registering a method in InternalParameters
+ is duplicated, you can always get the types from the InternalParameters
-* Static flow analysis
+* Emit modreq for volatiles
- Required to warn about reachability of code and definite
- assignemt as well as missing returns on functions.
+ Handle modreq from public apis.
-* Implement `goto case expr'
+* Emit `pinned' for pinned local variables.
- switch (x){
- case 1: print ("1"); goto case 4;
- case 2: ...
- case 4: ...
- }
+ Both `modreq' and pinned will require special hacks in the compiler.
-* Code cleanup
+* Make sure that we are pinning the right variable
- The information when registering a method in InternalParameters
- is duplicated, you can always get the types from the InternalParameters
+* Merge tree.cs, rootcontext.cs
OPTIMIZATIONS
-------------
-* Emitcontext
-
- Do we really need to instanciate this variable all the time?
-
- It could be static for all we care, and just use it for making
- sure that there are no recursive invocations on it.
-
-* Static-ization
+* User Defined Conversions is doing way too many calls to do union sets that are not needed
- Since AppDomain exists, maybe we can get rid of all the stuff
- that is part of the `compiler instance' and just use globals
- everywhere.
+* Add test case for destructors
+* Places that use `Ldelema' are basically places where I will be
+ initializing a value type. I could apply an optimization to
+ disable the implicit local temporary from being created (by using
+ the method in New).
-* Constructors
+* Dropping TypeContainer as an argument to EmitContext
- Currently it calls the parent constructor before initializing fields.
- It should do it the other way around.
+ My theory is that I can get rid of the TypeBuilder completely from
+ the EmitContext, and have typecasts where it is used (from
+ DeclSpace to where it matters).
-* Reducer and -Literal
+ The only pending problem is that the code that implements Aliases
+ is on TypeContainer, and probably should go in DeclSpace.
- Maybe we should never handle -Literal in Unary expressions and let
- the reducer take care of it always?
+* Use of local temporary in UnaryMutator
-* Use of EmitBranchable
+ We should get rid of the Localtemporary there for some cases
- Currently I use brfalse/brtrue in the code for statements, instead of
- using the EmitBranchable function that lives in Binary
+ This turns out to be very complex, at least for the post-version,
+ because this case:
-* Create an UnimplementedExpcetion
+ a = i++
- And use that instead of plain Exceptions to flag compiler errors.
+ To produce optimal code, it is necessary for UnaryMutator to know
+ that it is being assigned to a variable (the way the stack is laid
+ out using dup requires the store to happen inside UnaryMutator).
-* ConvertImplicit
+* Emitcontext
- Currently ConvertImplicit will not catch things like:
+ Do we really need to instanciate this variable all the time?
- - IntLiteral in a float context to generate a -FloatLiteral.
- Instead it will perform an integer load followed by a conversion.
+ It could be static for all we care, and just use it for making
+ sure that there are no recursive invocations on it.
* Tests
Write tests for the various reference conversions. We have
test for all the numeric conversions.
-* Remove the tree dumper, cleanup `public readonly'
-
- And make all the stuff which is `public readonly' be private unless
- required.
-
* Optimizations
In Indexers and Properties, probably support an EmitWithDup
in the stack, so that later a Store can be emitted using that
this pointer (consider Property++ or Indexer++)
+* Optimizations: variable allocation.
+
+ When local variables of a type are required, we should request
+ the variable and later release it when we are done, so that
+ the same local variable slot can be reused later on.
* Add a cache for the various GetArrayMethod operations.
-
+* TypeManager.FindMembers:
+
+ Instead of having hundreds of builder_to_blah hash table, have
+ a single one that maps a TypeBuilder `t' to a set of classes
+ that implement an interface that supports FindMembers.
+
+* MakeUnionSet Callers
+
+ If the types are the same, there is no need to compute the unionset,
+ we can just use the list from one of the types.
+
+* Factor the lookup code for class declarations an interfaces
+ (interface.cs:GetInterfaceByName)
+
RECOMMENDATIONS
---------------
Not sure that this grammar is correct, we might have to
resolve this during semantic analysis.
-
-* Try/Catch
-
- Investigate what is the right value to return from `Emit' in
- there (ie, for the `all code paths return')
-
-
-* Optimizations
-
- Only create one `This' instance per class, and reuse it.
-
- Maybe keep a pool of constants/literals (zero, 1)?
-