LCG + Debuggability, and your feedback
I mentioned earlier that you can debug Reflection.Emit code. Unfortunately, Ref.Emit code can't be unloaded unless you unload the entire appdomain. I wanted to lay out the current landscape, and then get feedback about possible solutions.
In Whidbey, we added Light Weight CodeGen (LCG), which are dynamically generated methods that can be garbage collected. This fixes the unloading problem with Ref.Emit code. Unfortunately, LCG methods aren't really debuggable. You can't currently associate them with source, and they're basically hidden when debugging. In Whidbey, they show up as an “InternalFrame” marker in the callstack, which has no information other than the annotation that there is some dynamic code on the stack. If a debug event fires (such as an exception / Debug.break statement) is in dynamic method, we will stop, and then it’s nice to have that internal Frame on the callstack. But nothing is really debuggable about it in Whidbey.
In other words, with ICorDebug (and thus debuggers like VS that use that):
- You can’t set breakpoints in dynamic methods (LCG)
- You can’t see the IL of dynamic methods
- You can’t see the locals / arguments of dynamic methods
- You can’t map dynamic methods back to source code
- You can’t step into or out of dynamic methods (it’s like native code when managed-only debugging)
Workarounds?
The current workarounds are:
1) Use windbg and SOS. See demo here
2) Use Ref.Emit for code that you want to be debuggable.
3) Use other tricks, like Haibo's IL visualizer.
But ultimately in Whidbey (.NET 2.0), you're forced to choose between debuggability (use Ref.Emit or normal code) vs. fine-grained unloadability beyond just appdomain unloading (use LCG).
Your feedback?
There's a few ways the CLR can solve this, including (but not limited to):
1. Make LCG debuggable, particularly adding the ability to associate source information with LCG methods, like you do with normal Ref.Emit when you call MarkSequencePoint.
2. Make Ref.Emit code collectable, ala LCG.
Do folks out there have any preference in solution?
I realize there's also a large dial about what is considered debuggable. Eg, source-level debuggability, vs. assembly level vs. IL level. (I could do a whole other blog entry about that). Any comments on where the dial should be set are welcome too.
Comments
Anonymous
November 14, 2006
The comment has been removedAnonymous
November 14, 2006
Having ability to step debug LCG methods would be great. Even if it is at IL level only.Anonymous
November 14, 2006
Tough choice, however I'd vote for making Ref.Emit code collectable, mainly because as a side effect, you would potentially improve existing libraries using Ref.Emit. I have used LCG a lot, and found I've typically generated very small methods. There are usually to replace reflection for performance. That being the case, I've not had the need to debug any LCG code. Using the IL Visualizer has been adequate.Anonymous
November 14, 2006
Please make Ref.Emit code collectable.Anonymous
November 16, 2006
I was glad to hear many positive feedbacks about the DebuggerVisualizer for DynamicMethod ; on the sadAnonymous
December 05, 2006
I vote for making LCG debuggable. I really want a general purpose IL debugger (i.e. make IL a first-class citizen in the debugger IDE), but I'll settle for a LCG debugger. I've used Haibo's visualizer; it rocks, and it makes me want more.Anonymous
December 06, 2006
David - can you elaborate? There's a spectrum of "debuggability". Are you content to be able to debug the LCG IL? Or do you want source-level debugging for LCG (ie, associate generate LCG with source) like you have for ref.emit?Anonymous
December 06, 2006
Hi Mike, I want source level debugging with LCG....and more :-) Ideally it would be as easy to use, powerful, intuitive and integrated as the C# IDE debugger; for that matter, I want IL support in DevStudio (I know, it aint likely to happen, but you asked :-) ). It would be cool to be able to use a wizard to generate the skelton of an IL project.... Debugging LCG is important but I really want source level debugging because I want to write some code in IL. There are a number of .NET constructs that are only possible to do in IL because the feature is not surfaced in C# (my language of choice). For example, exception filters and fault handlers....a grab-bag of utilities I can wrap up in a DLL and expose as nice, easy-to-use .net classes. Thanks, DaveAnonymous
December 06, 2006
The comment has been removedAnonymous
December 06, 2006
I honestly can't say which is more important. My gut says that I need to be able to debug any code I write. But....for production code it may be more important to be able to unload ref.emit. It's a tradeoff between ease of development versus features that the user sees.Anonymous
December 08, 2006
I'm looking for feedback about Ref.Emit usage patterns. When using Ref.Emit , how many types do you generallyAnonymous
December 08, 2006
Making Ref.Emit collectable It covers so much more. I don't see a loss of anything compared to LCGAnonymous
May 24, 2007
The CLR team recently had a compiler dev Lab on campus in building 20, with a strong focus on dynamic