I've been writing some weird code lately.
As I was falling asleep last night, I thought about pluggable runloops and figured out a way to instrument the standard runloop in such a way as to provide loads of debugging information to pure-Perl code written by people who don't want to have to dive into XS to learn interesting things.
Perl, not generating machine code directly, has a runloop that takes the optree generated by the compiler and walks it in order. It's a very simple subroutine in run.c that basically says "Call the function pointer of the current op, which returns the next op. If that next op exists, repeat."
Instrumenting that turns out to be pretty easy. The only tricky part is making sure that the tracing code doesn't itself get traced, which would lead to all sorts of infinite recursions.
Okay, another tricky part is making sure not to leave any residue of the calls to the tracing code on the stack without requiring that non-XS programmers always end their code with bare return statements. (If you've ever used call_method()
, you probably know that G_VOID
doesn't cut it here. I know that too, but I wasted a few minutes not knowing that.)
Anyway, here's Runops::Trace 0.01. It's not spectacular or even useful, but it totally works as a proof of concept. There's a little more design to do on the user side, such as "Which parts of the op should the user be able to see?" and "How should users be able to trace certain ops but not others?", so let me know if you have any opinions.
If you don't care, I'll give you a moral for this story anyway: if you're poking at the Perl interpreter and your code doesn't segfault, it must be fairly correct.
Sounds much like one of the quotes in the rotation here:
I’m currently dodging core dumps falling from the sky, but I think I’m running in generally right direction… – Jarkko Hietaniemi