mirror of https://github.com/icsharpcode/ILSpy.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
239 lines
6.7 KiB
239 lines
6.7 KiB
---- This is a list of old tasks, just here for historical value ---- |
|
|
|
Open question: |
|
Create a toplevel block for anonymous methods? |
|
|
|
Anonymous Methods |
|
----------------- |
|
|
|
Plan: |
|
|
|
* Resolve anonymous methods before. |
|
* Each time a Local matches, if the mode is `InAnonymous', flag |
|
the VariableInfo for `proxying'. |
|
* During Resolve track the depth required for local variables. |
|
* Before Emit, create proxy classes with proper depth. |
|
* Emit. |
|
|
|
Notes on memory allocation |
|
-------------------------- |
|
|
|
Outdated: |
|
|
|
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. |
|
|
|
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. |
|
|
|
A cache: |
|
|
|
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. |
|
|
|
Major tasks: |
|
------------ |
|
|
|
Pinned and volatile require type modifiers that can not be encoded |
|
with Reflection.Emit. |
|
|
|
* Revisit |
|
|
|
Primary-expression, as it has now been split into |
|
non-array-creation-expression and array-creation-expression. |
|
|
|
* Emit `pinned' for pinned local variables. |
|
|
|
Both `modreq' and pinned will require special hacks in the compiler. |
|
|
|
* Make sure that we are pinning the right variable |
|
|
|
* local_variable_declaration |
|
|
|
Not sure that this grammar is correct, we might have to |
|
resolve this during semantic analysis. |
|
|
|
* Optimizations |
|
|
|
In Indexers and Properties, probably support an EmitWithDup |
|
That emits the code to call Get and then leaves a this pointer |
|
in the stack, so that later a Store can be emitted using that |
|
this pointer (consider Property++ or Indexer++) |
|
|
|
* Use of local temporary in UnaryMutator |
|
|
|
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). |
|
|
|
* Interface indexers |
|
|
|
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 |
|
|
|
* Check for Final when overriding, if the parent is Final, then we cant |
|
allow an override. |
|
|
|
Implement base indexer access. |
|
|
|
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 |
|
|
|
|
|
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. |
|
|
|
This has been now implemented, its called "QualifiedIdentifier" |
|
|
|
TODO: |
|
|
|
1. Create a "partial" emit context for each TypeContainer.. |
|
|
|
2. EmitContext should be partially constructed. No IL Generator. |
|
|
|
interface_type review. |
|
|
|
parameter_array, line 952: `note: must be a single dimension array type'. Validate this |
|
|
|
Instance idea |
|
------------- |
|
|
|
It would be nice to have things that can be "instances" to have an |
|
EmitInstance method (this would default to nothing). |
|
|
|
The idea is to be able to use efficiently the instance data on stack |
|
manipulations, as opposed to the current scheme, where we basically have |
|
a few special cases. |
|
|
|
* `yield' is no longer a keyword, it only has special |
|
meaning before a return or break keywords. |
|
|
|
* Study side effects with assign |
|
* Study TemporaryStorage/LocalStorage -> Merge/rename |
|
|
|
|