Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer

Re^4: How does CATCH_SET optimize efficiency?

by dave_the_m (Prior)
on Dec 16, 2012 at 18:08 UTC ( #1009080=note: print w/replies, xml ) Need Help??

in reply to Re^3: How does CATCH_SET optimize efficiency?
in thread How does CATCH_SET optimize efficiency?

One way of looking at it is that a naive implementation would have have every eval, require, try etc push a new jumplevel and enter a new runops loop. That way, when an exception occurs and a longjump occurs, the inner runops loop execution is popped of the C stack, and control returns to pp_entertry or whereever, which can then handle the exception how it wants.

An optimisation to this is to have a flag (je_mustcatch) that can be set to indicate that the caller of the current runops loop can catch longjumps, handle the exception, and if necessary restart a new runops loop. In this case, there's no need to push a new jumplevel and runops loop each time.

The top-level execution of a perl program consists of setting up a jump level and entering a runops loop, so it sets je_mustcatch to false there: the top-level is already set up to handle expections.

Whenever perl code is called "from C" rather than directly from perl, such as FETCHes, overload code, or perl code called from XS, then it creates a new runops loop, but in this case the loop isn't protected by a new jumplevel and expection handler. So the caller of FETCH sets je_mustcatch to true, to notify any potential eval ops that they should set up their own handler.

So the net effect is that in practice, eval {} almost never has to push a new jump level and runops.


  • Comment on Re^4: How does CATCH_SET optimize efficiency?

Replies are listed 'Best First'.
Re^5: How does CATCH_SET optimize efficiency?
by PerlOnTheWay (Scribe) on Dec 17, 2012 at 04:11 UTC

    But FETCH is always called "from C", so the je_mustcatch is always true, and the eval ops will always create a new runops loop.

    Why not set up a new runops loop directly in the first place?

      Why not set up a new runops loop directly in the first place?
      I'm not sure I understand you. When the tie magic code calls FETCH, it starts a new runops loop to execute the ops within the FETCH sub (but it doesn't do a JMPENV_PUSH). If the FETCH function doesn't do any eval-ly stuff, then that's it. If the FETCH does eval {}, then the first time pp_entertry is called, a second runops loop is started, and JMPENV_PUSH is done. The rest of the ops within that eval, and continuing outside that eval, are executed within the inner runops loop, including any ops within second and subsequent eval {}'s. Finally, when FETCH returns, two runops loops and a jump level are exited.


        Dave, thanks, this clarify things a lot!

        So when there're multiple evals in a FETCH, and an exception is triggered, it will always restart from right after the first eval, no matter what, as only the first eval actually does JMPENV_PUSH, is it right?

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1009080]
[mz2255]: I'm trying to post a question to "seekers of perl wisdom" but always getting a permission denied when I want to submit. There are no links in my post...
[ambrus]: again? someone complained about this just a few days ago (although eventually they could post)
[choroba]: Can you post the question in mz2255's scratchpad?
[ambrus]: Corion, if you're here, can you check the spam filter logs to see what's triggering this time?

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (9)
As of 2017-10-19 15:19 GMT
Find Nodes?
    Voting Booth?
    My fridge is mostly full of:

    Results (255 votes). Check out past polls.