Here's my questions (assuming you can remember from 6+ years ago):
1) What was the hardest part of .NET to understand and/or implement?
2) Were there any surprising things about the .NET runtime/specification that you learnt about along the way?
3) Should JIT.c really be called Interpreter.c :-)
But I'm fairly sure the hardest part to implement was the support for generic types/methods. It made all the code that handles types way more complex (as expected I suppose!), and there's definitely a bug or two remaining. Correctly handling open/closed generic types and construction of types from generic arguments was painful. It didn't help that I initially implemented only non-generic type support, then had to hack generics into it. Were I to start again I'd implement the whole thing in a generic-first way.
The design of classes/structs and they they interact with generics is nice. And the `constained` IL prefix is a really neat optimization to avoid boxing.
The use of type-agnostic CIL instructions (e.g. `add` can work on int, float, ...) is also a nice touch.
JIT literally stands for "Just In Time". It doesn't say what it's actually doing just-in-time ;)
So (in my opinion) JIT.c is correct. It's translating CIL opcodes to dna-internal opcodes, which it does just-in-time just before a method is executed for the first time.
The reason it does this at all is because there are many things to resolve when working from CIL that it's much better to do just once rather than every time a method is executed. A simple example is method references, which are by name in CIL, but are a simple pointer in dna-internal opcodes.
r.e. 'JIT v Interpreted', I should've checked wikipedia, it backs up what you're saying:
> Most often this consists of translation to machine code, which is then executed directly, but can also refer to translation to another format