Entering try-catch with non-empty stack

As a recent thread pointed out, this list so far have been more like
ironruby-talk than ironruby-core. :slight_smile:

So, to start the discussion, I have a question. In
tests/ironruby/Runtime/Block/test_closure, I see this comment:

TODO:

assert_equal(foo(&p)) were replaced by x = foo(&p); assert_equal(x)

known DLR bug (entering try-catch with non-empty stack)

This looks like a same problem JRuby encountered and solved. As
Charles is on the list, he could provide some insight. :slight_smile:

A good introduction to this issue from JRuby point of view was written
by Ola B.:

Sanghyeon S. wrote:

This looks like a same problem JRuby encountered and solved. As
Charles is on the list, he could provide some insight. :slight_smile:

A good introduction to this issue from JRuby point of view was written
by Ola B.:
Ola Bini: Programming Language Synchronicity: The pain of compiling try-catch

I don’t think this qualifies as a bug; both the JVM and the CLR prepare
a new activation (and an empty stack) when you enter an
exception-handling section. For a language like Ruby, where you can, for
example, prepare arguments to a method call by doing a loop or
begin/rescue that ultimately return a value, you need to be able to
maintain the stack. XRuby’s approach is to save the stack, but I don’t
believe they support all such situations. JRuby generates a new method
for such situations, to allow the original activation maintain the same
stack state. In theory both approaches work, but they both have their
own complications. Currently we create what’s called “synthetic methods”
in the JVM to contain the body of e.g. a begin block attached to a
rescue block. We may also have to do this for while blocks when there’s
a chance that stack state must be maintained. I think we can determine
statically when we need to create synthetic methods and when we can’t.

  • Charlie

We are thinking about an AST transformation that would push forward
expression evaluations, store results to temp variables and reload them
where necessary. But we didn’t conclude on this yet. Introducing
additional method calls is IMO not necessary.

Tomas

Tomas M. wrote:

We are thinking about an AST transformation that would push forward expression evaluations, store results to temp variables and reload them where necessary. But we didn’t conclude on this yet. Introducing additional method calls is IMO not necessary.

To me the complexity of this approach is for many nested sets of such
expressions:

x = 1
x += begin
x += begin
x += begin
x += begin
raise
rescue
1
end
end
end
end

This is somewhat contrived, but there are many cases of at least a
couple nested expressions with exception handling that may happen during
stack-building. You would need to continue pushing down and storing
values on the stack at each level, restoring as you climb back out.

FWIW, the above works ok in JRuby right now, but if the begin/rescue is
replaced with while loops it fails to compile. I will likely have to use
the same approach for while loops, since they also implicitly handle
LocalJumpError exceptions.

  • Charlie