Exceptions

0 views
Skip to first unread message

Dan Sugalski

unread,
Aug 5, 2002, 1:36:49 PM8/5/02
to perl6-i...@perl.org
Okay, it's time for exceptions. So, the proposed ops:


pushx LABEL : Push an exception handler on the stack

throw PMC : Throw an exception object

When an exception is thrown, it pops elements off the control stack
until it gets to an exception handler. (Pops are error pops)
Exception handlers get called with the PMC as the only parameter. If
they don't like the exception they can rethrow it.

This doesn't define exception objects. I'm of two minds on that, so
I'll wait a sec and think on it a little bit.
--
Dan

--------------------------------------"it's like this"-------------------
Dan Sugalski even samurai
d...@sidhe.org have teddy bears and even
teddy bears get drunk

Florian Weimer

unread,
Aug 5, 2002, 2:40:16 PM8/5/02
to Dan Sugalski, perl6-i...@perl.org
Dan Sugalski <d...@sidhe.org> writes:

> Okay, it's time for exceptions. So, the proposed ops:

> pushx LABEL : Push an exception handler on the stack
>
> throw PMC : Throw an exception object
>
> When an exception is thrown, it pops elements off the control stack
> until it gets to an exception handler. (Pops are error pops)

Why pop the handler elements? Sometimes, it could make sense to
handle the exception in the raising context.

Dan Sugalski

unread,
Aug 5, 2002, 2:48:28 PM8/5/02
to Florian Weimer, perl6-i...@perl.org

Handling exceptions in-place is somewhat problematic, which is why
we're not going to do it at the moment. We could, though, if we need
to, by overriding the master exception handling stuff. (We'll need to
do that at the lowest level to allow catching of interpreter
exceptions from within opcode functions, but...)

We can see about a master exception override handler--the
architecture should support that easily enough.

Simon Glover

unread,
Aug 5, 2002, 2:50:36 PM8/5/02
to Dan Sugalski, perl6-i...@perl.org

On Mon, 5 Aug 2002, Dan Sugalski wrote:

> pushx LABEL : Push an exception handler on the stack
>
> throw PMC : Throw an exception object
>
> When an exception is thrown, it pops elements off the control stack
> until it gets to an exception handler. (Pops are error pops)
> Exception handlers get called with the PMC as the only parameter. If
> they don't like the exception they can rethrow it.

What happens if the program hasn't defined any exception handlers?
Do we push a default handler onto the stack at interpreter start-up
time, or is there some other fall-back mechanism?

Simon

Jerome Vouillon

unread,
Aug 5, 2002, 2:49:17 PM8/5/02
to Dan Sugalski, perl6-i...@perl.org

On Mon, Aug 05, 2002 at 01:36:49PM -0400, Dan Sugalski wrote:
> Okay, it's time for exceptions. So, the proposed ops:
>
> pushx LABEL : Push an exception handler on the stack
>
> throw PMC : Throw an exception object
>
> When an exception is thrown, it pops elements off the control stack
> until it gets to an exception handler. (Pops are error pops)

You don't really need a pushx opcode. If the "die" is in the scope of
a "catch", then you can directy jump to the handler. Otherwise, you
unwind the stack until you arrive in the scope of a "catch". In order
to know whether this is the case, you simply build a table at compile
time which associate to each possible return address a corresponding
handler (if any). The advantage is that the cost of "catch" is null
when no exception is raised. As a subroutine block is implicitely a
"catch" (it catches return exceptions), this may be interesting.

-- Jerome

Tanton Gibbs

unread,
Aug 5, 2002, 3:03:21 PM8/5/02
to Dan Sugalski, Jerome Vouillon, perl6-i...@perl.org
> You don't really need a pushx opcode. If the "die" is in the scope of
> a "catch", then you can directy jump to the handler. Otherwise, you
> unwind the stack until you arrive in the scope of a "catch". In order
> to know whether this is the case, you simply build a table at compile
> time which associate to each possible return address a corresponding
> handler (if any).

With the dynamic nature of perl, I would imagine that catch blocks could be
installed at runtime making this approach less attractive. You would have
to continually maintain the table as the program is running. It is still
not that bad, but it may be just as efficient to do the pushx.

As far as thinking of return and break as exceptions, I believe that could
be detremental. It simplifies things from a language design perspective,
but it will degrade performance from an implementation perspective.
Instead, we should assume that return, break, etc... will work in the normal
fashion. If the perl6 interpreter notices that break is not inside a loop
or that return is not inside a function, it can generate a special exception
that operates in the way described by Larry.

Tanton

John Porter

unread,
Aug 5, 2002, 3:43:38 PM8/5/02
to perl6-i...@perl.org
Simon Glover wrote:
> What happens if the program hasn't defined any exception handlers?
> Do we push a default handler onto the stack at interpreter start-up
> time, or is there some other fall-back mechanism?

Um... yes. I believe all language environments that support
exceptions install a default handler at startup.
Even C++ has one. (I think it calls abort.)

--
John Douglas Porter

Dan Sugalski

unread,
Aug 5, 2002, 4:14:01 PM8/5/02
to Jerome Vouillon, perl6-i...@perl.org
At 8:49 PM +0200 8/5/02, Jerome Vouillon wrote:
>On Mon, Aug 05, 2002 at 01:36:49PM -0400, Dan Sugalski wrote:
>> Okay, it's time for exceptions. So, the proposed ops:
>>
>> pushx LABEL : Push an exception handler on the stack
>>
>> throw PMC : Throw an exception object
>>
>> When an exception is thrown, it pops elements off the control stack
>> until it gets to an exception handler. (Pops are error pops)
>
>You don't really need a pushx opcode. If the "die" is in the scope of
>a "catch", then you can directy jump to the handler. Otherwise, you
>unwind the stack until you arrive in the scope of a "catch".

Alas, with perl it's not nearly so easy, I think. Overloaded operator
functions may throw exceptions, so we can't tell if the handler will
be necessary or not. Though that depends on how far we allow
exceptions to propagate, and whether a block actually calls a sub if
we don't let exceptions exit operator functions. (Though I think
we're going to have to)

Dan Sugalski

unread,
Aug 5, 2002, 3:59:03 PM8/5/02
to Simon Glover, perl6-i...@perl.org

We have a default handler in place. If the stack is entirely unwound
with no exception handler, we pitch a big fit to stderr and kill the
interpreter.

Jerome Vouillon

unread,
Aug 5, 2002, 6:47:00 PM8/5/02
to Dan Sugalski, Jerome Vouillon, perl6-i...@perl.org
On Mon, Aug 05, 2002 at 04:14:01PM -0400, Dan Sugalski wrote:
> At 8:49 PM +0200 8/5/02, Jerome Vouillon wrote:
> >You don't really need a pushx opcode. If the "die" is in the scope of
> >a "catch", then you can directy jump to the handler. Otherwise, you
> >unwind the stack until you arrive in the scope of a "catch".
>
> Alas, with perl it's not nearly so easy, I think. Overloaded operator
> functions may throw exceptions, so we can't tell if the handler will
> be necessary or not.

Maybe I was not very clear. The handlers should be gererated anyway.
Only, they don't need to be pushed on the stack. Instead, the handler
that needs to be invoked can be deduced from the current location in
the bytecode.

So, if an overloaded operator function throw an exception, the
exception is not caught by this function, so we start to unwind the
stack. We arrive at some location in the calling function. From this
location, we can find whether there is a handler (using a table). If
there is one, it is invoked. Otherwise, go on unwinding the stack.

-- Jerome

Jerome Vouillon

unread,
Aug 5, 2002, 6:54:06 PM8/5/02
to Tanton Gibbs, Dan Sugalski, Jerome Vouillon, perl6-i...@perl.org
On Mon, Aug 05, 2002 at 02:03:21PM -0500, Tanton Gibbs wrote:
> With the dynamic nature of perl, I would imagine that catch blocks could be
> installed at runtime making this approach less attractive.

I'm not sure of this. I don't think you can install a catch block at
runtime in Perl 5, for instance.

> As far as thinking of return and break as exceptions, I believe that could
> be detremental. It simplifies things from a language design perspective,
> but it will degrade performance from an implementation perspective.
> Instead, we should assume that return, break, etc... will work in the normal
> fashion. If the perl6 interpreter notices that break is not inside a loop
> or that return is not inside a function, it can generate a special exception
> that operates in the way described by Larry.

Sure, we should avoid raising an exception for return and break as
often as possible. But usually, a subroutine will not know whether
such an exception can be thrown during the execution of its body: the
exception may be thrown during a call to another subroutine. So, I
think we will have to install an exception handler at the beginning of
most functions. So, it may be interesting if this has a zero execution
cost.

-- Jerome

Tanton Gibbs

unread,
Aug 5, 2002, 7:28:54 PM8/5/02
to Jerome Vouillon, perl6-i...@perl.org
> > With the dynamic nature of perl, I would imagine that catch blocks could
be
> > installed at runtime making this approach less attractive.
>
> I'm not sure of this. I don't think you can install a catch block at
> runtime in Perl 5, for instance.

If this is the case, then I could see the case for static analysis of the
code. However, we also have to consider whether it will take more time to
build the table than the time it saves through the lookup. We hope that
exceptions will be fairly infrequent (if you discount things like break and
return). Therefore, we shouldn't spend too much time trying to optimize the
infrequent case.

> Sure, we should avoid raising an exception for return and break as
> often as possible. But usually, a subroutine will not know whether
> such an exception can be thrown during the execution of its body: the
> exception may be thrown during a call to another subroutine. So, I
> think we will have to install an exception handler at the beginning of
> most functions. So, it may be interesting if this has a zero execution
> cost.

I'm confused by this, are we talking about return and break exceptions or
more formal "exceptions" as thought of in most other contexts. If we are
discussing the latter than I would say a function should only have a handler
installed if it has a CATCH block. Otherwise, we will clean up the stack as
we go, that shouldn't require its own handler. As far as return and break
go, if the break is in a separate function (which shouldn't be often as that
is going to lead to confusing code), then the perl 6 interpreter can
generate a special break exception that the loop can handle...so, from that
line of reasoning, it would seem that loops will always need an exception
handler, but functions probably won't. Of course, we should add the handler
in anyway to check for "return" exceptions, but they should never be
generated.

Tanton

Reply all
Reply to author
Forward
0 new messages