+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.
+
+ 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.
+
+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;
+ }
+
+ So `System.ComponentModel' becomes:
+
+ x: (System, null)
+ y: (ComponentModel, x)
+
+ The problem is that we would still need to construct the name to pass to
+ GetType.
+
+current_container/current_namespace and the DeclSpace
+-----------------------------------------------------
+
+ 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'.
+
+ The reason for storing the full names today is this:
+
+ namespace X {
+ class Y {
+ }
+ }
+
+ namespace A {
+ class Y {
+ }
+ }
+
+ 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.
+
+ To fix this problem, we have to make namespaces DeclSpaces.
+
+ The full size, contrasted with the size that could be stored is:
+ corlib:
+ Size of strings held: 368901
+ Size of strings short: 147863
+
+ 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
+
+
TODO:
1. Create a "partial" emit context for each TypeContainer..
BUGS
----
-* We suck at reporting what turns out to be error -6. Use the standard error message
- instead.
-
* Check for Final when overriding, if the parent is Final, then we cant
allow an override.
PENDING TASKS
-------------
-* IMprove error handling here:
-
- public static Process ()
-
- THat assumes that it is a constructor, check if its the same name
- as the class, if not report a different error than the one we use now.
-
* Merge test 89 and test-34
* Revisit
Primary-expression, as it has now been split into
non-array-creation-expression and array-creation-expression.
-* Static flow analysis
-
- Required to warn about reachability of code and definite
- assignemt as well as missing returns on functions.
-
* Code cleanup
The information when registering a method in InternalParameters
* Make sure that we are pinning the right variable
-* Maybe track event usage? Currently I am not tracking these, although they
- are fields.
-
* Merge tree.cs, rootcontext.cs
OPTIMIZATIONS
We should get rid of the Localtemporary there for some cases
+ This turns out to be very complex, at least for the post-version,
+ because this case:
+
+ a = i++
+
+ 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).
+
* 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.
-* ConvertImplicit
-
- Currently ConvertImplicit will not catch things like:
-
- - IntLiteral in a float context to generate a -FloatLiteral.
- Instead it will perform an integer load followed by a conversion.
-
* Tests
Write tests for the various reference conversions. We have
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 all the FindMembers in all the FindMembers providers.
-
* Factor the lookup code for class declarations an interfaces
(interface.cs:GetInterfaceByName)
// (C) 2001 Ximian, Inc (http://www.ximian.com)
//
//
+
+//
+// We will eventually remove the SIMPLE_SPEEDUP, and should never change
+// the behavior of the compilation. This can be removed if we rework
+// the code to get a list of namespaces available.
+//
+#define SIMPLE_SPEEDUP
+
using System;
using System.Globalization;
using System.Collections;
return null;
}
+ static Hashtable negative_hits = new Hashtable ();
+
//
// This function is used when you want to avoid the lookups, and want to go
// directly to the source. This will use the cache.
if (t != null)
return t;
+#if SIMPLE_SPEEDUP
+ if (negative_hits.Contains (name))
+ return null;
+#endif
+
//
// Optimization: ComposedCast will work with an existing type, and might already have the
// full name of the type, so the full system lookup can probably be avoided.
types [name] = t;
return t;
}
+
+ //
+ // We know that System.Object does not have children, and since its the parent of
+ // all the objects, it always gets probbed for inner classes.
+ //
+ if (top_level_type == "System.Object")
+ return null;
string newt = top_level_type + "+" + String.Join ("+", elements, n, count - n);
t = LookupTypeDirect (newt);
types [newt] = t;
return t;
}
+
+#if SIMPLE_SPEEDUP
+ negative_hits [name] = true;
+#endif
return null;
}
namespaces [ns] = ns;
}
}
+ Console.WriteLine ("Namespaces: " + namespaces.Count);
return namespaces;
}
+
+ public static void GetAllTypes ()
+ {
+ Hashtable namespaces = new Hashtable ();
+
+ foreach (Assembly a in assemblies){
+ foreach (Type t in a.GetTypes ()){
+ }
+ }
+
+ foreach (ModuleBuilder mb in modules){
+ foreach (Type t in mb.GetTypes ()){
+ }
+ }
+ }
/// <summary>
/// Returns the C# name of a type if possible, or the full type name otherwise