Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

A question about .begin_eh

8 views
Skip to first unread message

Bob Rogers

unread,
Jun 11, 2006, 11:52:14 AM6/11/06
to Chip Salzenberg, Allison Randal, perl6-i...@perl.org
I notice the following paragraph, vintage late May, in
pdd23_exceptions.pod:

A C<.begin_eh> directive marks the beginning of a span of
opcodes which the programmer expects to throw an exception. If
an exception occurs in the execution of the given opcode span,
Parrot will transfer control to I<LABEL>.

I assume this means that you intend to replace the current methodology
of searching for an Exception_Handler object on the control stack when
an error is thrown with a search through sub metadata. How do you
envision this interacting with C<pushaction>, e.g.? Currently, it is
straightforward for find_exception_handler to DTRT WRT other control
stack entries. Would the metadata also contain information about
C<pushaction> and such?

TIA,

-- Bob Rogers
http://rgrjr.dyndns.org/

P.S. FWIW, I am asking now because I have begun to work again on
dynamic binding -- which of course makes this problem worse.

Chip Salzenberg

unread,
Jun 12, 2006, 9:54:24 AM6/12/06
to Bob Rogers, Allison Randal, perl6-i...@perl.org
On Sun, Jun 11, 2006 at 11:52:14AM -0400, Bob Rogers wrote:
> I notice the following paragraph, vintage late May, in
> pdd23_exceptions.pod:
>
> A C<.begin_eh> directive marks the beginning of a span of
> opcodes which the programmer expects to throw an exception. If
> an exception occurs in the execution of the given opcode span,
> Parrot will transfer control to I<LABEL>.
>
> I assume this means that you intend to replace the current methodology
> of searching for an Exception_Handler object on the control stack when
> an error is thrown with a search through sub metadata.

That's the plan. The upside is that on the non-exceptional case, nothing at
all needs to be done. I just couldn't see the value in making the VM
allocate and free memory blocks on the control stack, over and over, when
no exceptions are occurring.

> How do you envision this interacting with C<pushaction>, e.g.? Currently,
> it is straightforward for find_exception_handler to DTRT WRT other control
> stack entries. Would the metadata also contain information about
> C<pushaction> and such?

I hadn't decided either way about C<pushaction>. Seems to me that either
way will work though. Could you spell out a little more of what you see
as being bad (or harder)?

> P.S. FWIW, I am asking now because I have begun to work again on
> dynamic binding -- which of course makes this problem worse.

I can't see how. Dynamically bind all you want, but the code of each
subroutine is fixed at compile time. Having static metadata is no sin as
long as as the data that they're meta of are also static.
--
Chip Salzenberg <ch...@pobox.com>

Bob Rogers

unread,
Jun 12, 2006, 8:24:55 PM6/12/06
to Chip Salzenberg, Allison Randal, perl6-i...@perl.org
From: Chip Salzenberg <ch...@pobox.com>
Date: Mon, 12 Jun 2006 06:54:24 -0700

On Sun, Jun 11, 2006 at 11:52:14AM -0400, Bob Rogers wrote:
> I notice the following paragraph, vintage late May, in
> pdd23_exceptions.pod:
>
> A C<.begin_eh> directive marks the beginning of a span of
> opcodes which the programmer expects to throw an exception. If
> an exception occurs in the execution of the given opcode span,
> Parrot will transfer control to I<LABEL>.
>
> I assume this means that you intend to replace the current methodology
> of searching for an Exception_Handler object on the control stack when
> an error is thrown with a search through sub metadata.

That's the plan. The upside is that on the non-exceptional case, nothing at
all needs to be done. I just couldn't see the value in making the VM
allocate and free memory blocks on the control stack, over and over, when
no exceptions are occurring.

Yes, that's nice. The downside, though, is that you have to do more
work when it's time to throw, but I agree that this is likely to happen
less often, at least for most error-handling situations. (There's also
a load-time cost, I imagine, but it can't be very large.)

Unfortunately, this is a step backwards from my perspective, as it is
already problematic to use Parrot as it exists now to implement ANSI
Common Lisp error signalling semantics, and any approach based on
metadata (being static) will make it more so. However, I can still
implement ANSI semantics using dynamic binding, C<pushaction>, and
continuations that respect both (which they currently do not), though
the result won't interoperate with error handling in the rest of Parrot.

> How do you envision this interacting with C<pushaction>, e.g.? Currently,
> it is straightforward for find_exception_handler to DTRT WRT other control
> stack entries. Would the metadata also contain information about
> C<pushaction> and such?

I hadn't decided either way about C<pushaction>. Seems to me that either
way will work though. Could you spell out a little more of what you see
as being bad (or harder)?

Actions are dynamic state that must nest properly with respect to error
handlers. So you have to know how many actions to pop & invoke when
unwinding the stack before invoking a given error handler. So it seems
to me that you would also have to lexicalize actions in order to give
find_exception_handler a clue. (Or, more accurately, not to take away
the clue that it has.) But you can't lexicalize actions completely
without removing the ability to invoke a closure as a cleanup action!

> P.S. FWIW, I am asking now because I have begun to work again on
> dynamic binding -- which of course makes this problem worse.

I can't see how. Dynamically bind all you want, but the code of each
subroutine is fixed at compile time. Having static metadata is no sin as
long as as the data that they're meta of are also static.
--
Chip Salzenberg <ch...@pobox.com>

True, but not all items on the control stack are as static as error
handlers, and they interact to a large degree.

Dynamic bindings in particular require runtime dynamic state (namely,
the saved values), so there still needs to be something on the control
stack to capture it. Of course, one can store metadata that records how
deep the binding stack should be at each handler (relative to the sub
entrypoint), given the right lexical cues in the source. But since (I
believe) we still need binding and unbinding opcodes that do something
at runtime, and could therefore be conditionalized away, or might even
throw an error, this has its pitfalls.

-- Bob

Bob Rogers

unread,
Jun 15, 2006, 12:03:56 AM6/15/06
to Chip Salzenberg, Allison Randal, perl6-i...@perl.org, perl6-c...@perl.org
From: Chip Salzenberg <ch...@pobox.com>
Date: Wed, 14 Jun 2006 12:05:29 -0700

[ Note to p6c: This thread is about the proposed and only partially
specified ".begin_eh"/".end_eh" directives that would specify exception
handling as a static property of a range of opcodes in a subroutine,
rather than the current dynamic approach of C<push_handler> etc. I'm
including p6c in case Lisp isn't the only language with potential issues
here. See also docs/pdds/clip/pdd23_exceptions.pod.]

On Mon, Jun 12, 2006 at 08:24:55PM -0400, Bob Rogers wrote:
>
> . . .


>
> Unfortunately, this is a step backwards from my perspective, as it is
> already problematic to use Parrot as it exists now to implement ANSI
> Common Lisp error signalling semantics, and any approach based on
> metadata (being static) will make it more so. However, I can still
> implement ANSI semantics using dynamic binding, C<pushaction>, and
> continuations that respect both (which they currently do not), though
> the result won't interoperate with error handling in the rest of Parrot.

{{ Please read the rest of the message before answering this paragraph.
It may be moot. }}

In fact, it's central, and meet to be mooted (in the oldest sense of the
word. ;-)

OK, maybe I don't understand CL or your implmentation strategy, but:
Aren't you planning on -compiling- the CL to PIR?

Yes, of course.

When the form that does exception handling is compiled to PIR, why
can't you translate it to (among other things) a .eh block?

CL handlers are functions (typically closures) that are invoked by ERROR
or SIGNAL in order to decide how to handle the condition [1]. The first
handler that effects a nonlocal exit is considered to have handled the
condition. If no handlers bite, and the condition was signalled by
ERROR, then the debugger is entered; otherwise, SIGNAL just returns --
both still at the point the condition was signalled, with its context
intact. Even if the condition is handled somewhere, returning to a .eh
block isn't quite correct, as then the handler body is running in the
handler's bind-time environment, rather than the dynamic environment of
the error.

Essentially, I don't see how to implement a reasonable facsimile of
ANSI semantics without handlers-as-functions.

In fact, I had thought that this was where the "early draft of
exceptions PDD" thread was going last April. So I proposed essentially
the Lisp model on 29-April, but I never heard back, so I assumed that it
was considered too radical. It would certainly cost an instruction or
two more than the current implementation to establish an error handler.

Separately, what do you mean by "respecting" pushaction in the
continuation implementation?

Currently, invoking a continuation will unwind the stack past actions
without invoking them, since the unwinding is implicit in the way
continuations re-establish the control stack. The fix is not difficult,
but neither is it completely straightforward, especially as there are
other related bugs in that code. (There is also the semantic issue of
whether an action should be invoked for a given kind of continuation; I
intend to propose [2] that the action should decide.) So I haven't
tried to fix this one yet because I assume it would be easier to clobber
them all at once when implementing related control stack changes for
dynamic binding [2].

> Actions are dynamic state that must nest properly with respect to error
> handlers. So you have to know how many actions to pop & invoke when
> unwinding the stack before invoking a given error handler. So it seems
> to me that you would also have to lexicalize actions in order to give
> find_exception_handler a clue.

Ah, well, that's fine then. In fact we are going to lexicalize actions, in
the form of an optional I<FINALLY_LABEL> on .begin_eh:

.begin_eh [ I<CATCH_LABEL> ] [ , I<FINALLY_LABEL> ]

A 'finally' label gets called on the way out of an exception block whether
or not the departure was the result of an exception. To handle the non-
exception case, I imagine PIR will just emit "call my_finally" when it
encounters the ".end_eh" directive.

Sounds good to me. Several questions/thoughts:

1. By "call", do you mean "jsr" (or "bsr" -- I don't grok the
distinction)? I notice that your example below (which I snipped) uses
"ret" at the end of the 'finally' block, but it's not clear how that
translates into a resumption of stack-unwinding.

2. Since the CL features that would use this construct are
independent, I would never need to emit code that uses both. Instead,
it would be either

.begin_eh I<CATCH_LABEL>

or

.begin_eh ,I<FINALLY_LABEL>

So it might be clearer to have a separate ".begin_finally" and
".end_finally" for the latter. (But of course this is a merely a
trifling question of syntax.)

3. FWIW, the Scheme dynamic-wind feature requires an action to be
invoked when re-entering the context as well as leaving it. But this is
probably not relevant, as a real Scheme implementation would probably
not need Parrot continuations or actions in any case.

On the other hand, since static exception blocks haven't been implemented
yet, it's not too late to ditch the whole change as a bad job, if that's
the right decision for Lisp and other languages. Lispers are people too. :-)

You mean -+<{gasp}>+- I can come out of my closet now?

Seriously, I appreciate your willingness to listen to fans of
minority languages. So far, my strategy has been to propose only
changes that I think will benefit Parrot and Perl 6 in general. In the
future, I may need to suggest changes that are only useful for Lisp, but
I hope by that time I will have released my compiler [3], and the Parrot
world can judge them in context.

FWIW, I confess to being of two minds about stack exception blocks,
even just considering changes from the current functionality, as opposed
to anything additional required for Lisp. On the one hand, I can see
what you're trying to do, and it makes some sense. On the other hand, I
wonder whether this will add a nontrivial dose of complexity for the
sake of a hard-to-measure speedup. Note that this is not about Lisp
semantics; the complexity will still be required for Perl 6 features.

> But you can't lexicalize actions completely without removing the ability
> to invoke a closure as a cleanup action!

Not at all. It just makes you emit the call instruction yourself.
For example . . .

Of course; that's much simpler than what I had in mind. I was assuming
that C<.begin_eh> would nominate a Sub as the cleanup action, instead of
a label. And the only reason I wanted a closure in the first place was
to retain the context, which using a label provides first-hand.

> Dynamic bindings in particular require runtime dynamic state (namely, the
> saved values), so there still needs to be something on the control stack
> to capture it.

I think the 'finally' feature is pretty much what you need for this.
--
Chip Salzenberg <ch...@pobox.com>

I'm afraid I don't see how. The issue is preserving dynamic binding
state when switching contexts via continuation or coroutine. This
context switching may be done an arbitrary number of times, moving both
up and down the call stack, whereas 'finally' semantics seem to be
'fire-once-when-unwinding.' Or is this too being generalized?

Also, though less important, merging dynamic binding into 'finally'
means that debuggers won't be able to tell you which variables are bound
dynamically. (Unless you add metadata to that end, but that makes
introspection more difficult; it seems much easier to have a binding
object that can be queried directly by a PIR-level debugger.)

-- Bob

P.S. This has probably already occurred to you, but at some point you
will need to tell me whether I can proceed with implementing dynamic
binding on the current implementation, or whether I should wait until
you've designed/implemented/punted static exception blocks.

================

[1] http://www.lispworks.com/documentation/HyperSpec/Body/m_handle.htm#handler-bind

[2] See http://rgrjr.dyndns.org/perl/dynbind-proposal-v2.html for the
latest draft.

[3] At which time I will have truly left the closet.

Bob Rogers

unread,
Jul 8, 2006, 5:10:57 PM7/8/06
to Chip Salzenberg, Allison Randal, parrot-...@perl.org
From: Chip Salzenberg <ch...@pobox.com>
Date: Sat, 24 Jun 2006 21:56:32 -0700

On Sat, Jun 24, 2006 at 11:18:41PM -0400, Bob Rogers wrote:
> Such an implementation is truly and utterly stackless, which means that
> dynamic-wind needs to keep its own stack explicitly, and similarly for
> dynamic binding (which, IIUC, is generally implemented in terms of
> dynamic-wind).

... actually describes Parrot, present and future. Parrot doesn't need to
recurse in C to invoke continuations or closures . . .

Understood. However, Parrot uses an explicit chain of "Parrot_Context
=> RetContinuation => Parrot_Context => ...", which (IIUC) is something
a pure CPS implementation does not require. That's all I meant.

And my intended implementation of dynamic-wind actually does require
its own stack, separate from the current control stack . ..

Is there a PDD forthcoming? If not (or even if so), would you (Allison
now, presumably?) like help writing it?

Chip Salzenberg

unread,
Jul 8, 2006, 6:20:08 PM7/8/06
to Bob Rogers, Allison Randal, parrot-...@perl.org
On Sat, Jul 08, 2006 at 05:10:57PM -0400, Bob Rogers wrote:
> And my intended implementation of dynamic-wind actually does require
> its own stack, separate from the current control stack . ..
>
> Is there a PDD forthcoming? If not (or even if so), would you (Allison
> now, presumably?) like help writing it?

As for me, namespaces need to be fully and completely put to bed before I
can move on.

I'd love to do exceptions next, but I suspect that I can't really do
exceptions properly until we have proper dynamic scopes. EHs may not be
controlled entirely by the general dynamic scope mechanism, but their
definitions and mechanisms for "entering" and "leaving" must be identical.

Personally I'd love to see your interpretation of dynamic-wind in Parrot.
And PDD format is a fine format to present a complete idea so that it can be
easily understood and, perhaps, adopted.

PS: All of this is about foreground projects. Background and bug fixes
always go on.
--
Chip Salzenberg <ch...@pobox.com>

Bob Rogers

unread,
Jul 9, 2006, 9:47:08 PM7/9/06
to Chip Salzenberg, Allison Randal, parrot-...@perl.org
From: Chip Salzenberg <ch...@pobox.com>
Date: Sat, 8 Jul 2006 15:20:08 -0700

On Sat, Jul 08, 2006 at 05:10:57PM -0400, Bob Rogers wrote:
> And my intended implementation of dynamic-wind actually does require
> its own stack, separate from the current control stack . ..
>
> Is there a PDD forthcoming? If not (or even if so), would you (Allison
> now, presumably?) like help writing it?

As for me, namespaces need to be fully and completely put to bed before I
can move on.

I'd love to do exceptions next, but I suspect that I can't really do
exceptions properly until we have proper dynamic scopes. EHs may not be
controlled entirely by the general dynamic scope mechanism, but their
definitions and mechanisms for "entering" and "leaving" must be identical.

I think you're right. And even if not, I think all of this is
sufficiently deeply tangled that we have to assume that it all needs to
be untangled together.

Personally I'd love to see your interpretation of dynamic-wind in Parrot.
And PDD format is a fine format to present a complete idea so that it can be
easily understood and, perhaps, adopted.

My currently thinking is reflected here:

http://rgrjr.dyndns.org/perl/dynbind-proposal-v3.html

But it's not in PDD format yet (being still too polemical, among other
reasons), and it's still not finished, though I hope you find it useful.
I really want to understand how exception handling has to work in order
to support Perl 6 in order to ensure that all of the tools in the
dynamic environment toolbox work with each other smoothly.

-- Bob

0 new messages