# Friday, March 26, 2004
« Q & A | Main | Backward Branch Constraints »
Debugging Support

I finished and fixed the local variable analysis and made various improvements to the debugging experience (in Visual Studio .NET). In the process I discovered some quirks in jikes' debugging tables. It associates two line numbers with the same bytecode address when that bytecode address is also the start of an exception block. It also (I think incorrectly) starts a local variable scope before the store instruction that first initializes that local variable. Javac starts the local variable scope immediately after the first store to that local, this makes more sense to me, but also required a hack in the local variable debugging support to make sure that the IL variable scope starts at the right position (i.e. before the first store to that local variable).

To make local variable scopes work, I had to change the bytecode compiler to emit IL in the same order as the original Java bytecode. For some reason I originally wrote the compiler to do the same code flow analysis as the verifier and this resulted in a somewhat arbitrary order of the generated IL. I finally fixed that and I also removed the recursion from the compiler (it now uses an explicit stack to keep track of exception blocks).

Note that unreachable code is still not compiled (it can't be verified, so it can't be compiled), but there will be nop IL instructions for each unreachable bytecode instruction, so you can set breakpoints and move the instruction pointer there. This could be a bit confusing and I probably should fix it at some point (by not emitting the nops).

I also had to reintroduce the automatic downcasting of locals, because I realised that it is possible to write bytecode by hand that depends on this (Java source will never require it). In non-debug builds of classpath.dll this introduces 12 (unnecessary) downcasts, so that's not really worth optimising.

What's new?

  • When compiling with -debug option, dead store are not optimized out anymore.
  • When compiling with -debug option, local variables are merged based on LocalVariableTable information.
  • When compiling with -debug option, the first instruction of a method will always (except when compiling with -Xmethodtrace) have an associated line number now (to enable stepping into the method).
  • When compiling with -debug option, local variables are now scoped based on LocalVariableTable information. Different locals with the same name are now handled correctly in the debugger.
  • Made helper method MethodInfo caching more consistent.
  • Method arguments that are value types are now boxed on method entry and not on each individual load, this makes them behave consistent with local variables.
  • Reusing method argument local variable slots (with different types) is now fully supported. I've never seen a Java compiler do this, but it is legal.
  • lookupswitch/tableswitch branches into exception blocks are now handled correctly (exception block is split around branch target). This completes branch/exception block handling. I originally thought that this would never happen, but apparently it does.
  • Added a helper method to emit Ldc_I4 that always uses the optimal encoding.
  • Added a class loader check to the System.arraycopy optimization check, to make sure that we're in fact calling System.arraycopy on the bootstrap version of java.lang.System.
  • Many fixes to the local variable analysis.
  • Added -srcpath option to ikvmc. If specified, this prepends the specified path and the package name to the source file name in the debugging information. In most cases this will be the correct location for the source file and will allow the debugger to automatically load the correct source.
  • Added AWT peer for Window.

New snapshots: just the binaries and source plus binaries.

Friday, March 26, 2004 11:30:36 AM (W. Europe Standard Time, UTC+01:00)  #    Comments [1] Tracked by:
"Free Poker online" (Free Poker online) [Trackback]