This is the mail archive of the
kawa@sourceware.org
mailing list for the Kawa project.
Re: SLIME backend
* Jim White [2008-05-28 17:47+0200] writes:
> I think the difficulty mainly lies in having to deal with bytecode
> rather than a nice data structure for code. try-blocks are compiled
> into little tables that are logically HANDLER-BIND AFAICT.
It's arguably more like CONDITION-CASE not HANDLER-BIND. The difference
being that the latter executes the handler in the dynamic extend of the
error whereas the former unwinds the stack before running the handler.
> Also there is the JVM Debugger API, which provides direct access to
> conditions for such things as triggering on any exception and the
> like.
>
>> On the JVM it's rather difficult to decide if and where an exception
>> will be caught without unwinding the stack. But invoking the debugger
>> after unwinding the stack is usually too late, because the most
>> interesting frames are those at which the exception was thrown.
>
> I haven't looked to see if anyone has written a stack walker to
> discover which exceptions are caught where, but it is possible AFAIK.
That's true. But it's only possible to decide where the exception will
be caught the first time but not if/where the first handler will rethrow
the exception. There might be many exception handlers that perform some
minor action before rethrowing. It's pretty much needed to execute the
handlers before you know where the exception will eventually end up.
[BTW, the current JDI only provides access to the "bytecodes" (the VM
instructions) for a method and the constant pool. The exception tables
(and other method attributes) are missing. The instrumentation package
could probably be used to get the tables, but doing stack walking this
way is probably just as slow or even slower than copying the stack
manually with the JDI.]
>> Python seem to solve this dilemma by including information about local
>> variables in exception objects. The SLIME backend does same, but such
>> a strategy is very expensive and will probably never become popular on
>> the JVM.
>
> Language-specific is far easier to deal with than general bytecode for
> sure.
>
> The idea I like for dealing with this sort of thing is to use AOP
> (AspectJ) because you can use it to rewrite bytecode behavior in
> practically any manner desired. And while it is true that performance
> may suffer in some situations, it is a highly flexible approach that
> offers tradeoffs for compile-time vs. load-time weaving and can be
> selective about classes are affected.
I don't think that (automatic) rewriting would help here. Java's
catch/throw can be used as ordinary control structure (like CATCH/THROW
or BLOCK/RETURN-FROM in CL) or as a way to signal an error (like
SIGNAL/CONDITION-CASE in CL). Only the second use is interesting for
debugging. It would be hard to know what the programmers intend was
just by inspecting the bytecodes.
However, AspectJ could be useful for manually rewriting a code base like
Kawa. In some places Kawa should probably use the moral equivalent of
SIGNAL instead of throw.
>> [BTW, I always wonder how expensive fillInStackTrace is. Is there a
>> trick to make this cheap or is it as expensive as it sounds?]
>
> It's expensive but optional.
[Hmm, I guess a efficiency minded guy could override fillInStackTrace
with a noop in his custom throwables indented for control transfers
only. I wonder if Kawa does that for call/cc.]
>
> In fact the code for fillInStackTrace could be the starting point for
> a fancier version that decorates it with the exceptions that are
> caught at each frame. Although on second thought, that may not be the
> case since it is probably native code in the JVM.
>
> So if I wanted a stacktrace with exception handlers and didn't want to
> use the Debugger API, I would do the fillInStackTrace, then for each
> frame get the bytecode for the class of the method
> (ClassLoader.findClass), find the call's location in the bytecode
> using the line number table (this only works for clases compiled with
> debug info on of course), then examine the block surrounding that
> location to see if it is enclosed by a try-block. If there is a
> try-block then it provides a list of the throwable classes that are
> caught there.
You can't get the bytecode for a frame from fillInStackTrace.
fillInStackTrace only returns strings, not real classes/methods.
And strings aren't enough in the presence of multiple class loaders.
The coolest thing would be if fillInStackTrace would fill in the real
continuation. It don't think that that will ever be implemented,
though.
Helmut.