

Debugging in the Time of JITs - steeples
http://rfrn.org/~shu/2014/05/14/debugging-in-the-time-of-jits.html

======
gsg
Interesting article. I'm writing a toy trace compiler at the moment and
implementing side exits brings up many of the same, rather irritating
problems.

------
Skinney
Would be fun to try to compare this with a decent GC and see what the
difference is likely to be. The reason why I say this is because Javas default
GC pre-allocates a heap (a Java allocation is mostly just bumping a pointer),
and since it "frees" memory by copying survivors to a new space you also avoid
fragmentation.

If it turns out that what you mostly pay for, when using a GC, is that
collection happens at one point in time instead of incrementally, then Go's
plan for the evolution of their GC just became a lot more interesting.

~~~
Skinney
Ahh, commented on the wrong article... Was wondering why I was downvoted :P

------
amelius
It seems to me that we should not make the problem more complicated than
necessary. If you're debugging code written in Javascript, you may assume that
the JIT optimizer is correct. If you need special features enabled (such as
stack traces, etc.), then just pepper the code that _enters_ the JIT with
logging instructions, etc.

There should never be a need to completely disable the JIT optimizer, except
perhaps to debug the JIT itself.

~~~
StefanKarpinski
The issue with debugging JITed code is not that the optimizer may be
incorrect, but rather that optimization wreaks havoc on the correspondence
between source code and what actually executes – things happen in a different
order or not at all, stack frames don't correspond to function calls, etc.
This makes the debugging experience pretty confusing. To get a sense of this,
try using gdb/lldb on code compiled at -O3 with -g turned on so that you still
have debugging symbols. Things are weird. When debugging AOT compiled code,
one avoids this confusing experience by recompiling the entire program in
debug mode with optimizations off. In a JIT environment, what do you do? This
article describes a clever approach: dynamically deoptimize the stack and
transfer control from optimized code to non-optimized code, then debug the
simple, non-optimized version of your program where what's executed lines up
nicely with the source code.

~~~
amelius
Things happening out of order should never be observable. So this should not
be an issue.

~~~
gsg
The only reason things happening out of order is invisible is because
implementors jump through the kinds of hoops described in the article.

One way to understand the requirement for deoptimization is to to think about
where the programmer can observe the difference between an optimized construct
and the naive version. In regular execution there are relatively few places
where the state of the program is observable, allowing freedom to aggressively
optimize - under the debugger there are _no_ places where the state of the
program is unobservable.

