Open leonerd opened 3 years ago
To solve this I could imagine two possibilities.
Both involve keeping track of the prevailing COP in effect for deferred recursive calls, and somehow ensuring that the invoked function is aware of it. For toplevel functions and code this would be the first op itself because that will be a COP, but for anything else (e.g. these LOGOP op_other branches) we can instead pass the prevailing COP we encountered at the time.
1) Change the signature of the PL_rpeepp function to pass a COP as well.
2) Keep the signature but ensure that PL_curcop
itself is set to the correct value before invoking the function.
Option 1 is conceptually neater, but more disruptive in causing a code-level breakage of existing code. Option 2 avoids sourcecode breakage, but then code written presuming the new style will silently give the wrong results on older perls, rather than failing to compile as it would under option 1.
On Sat, May 08, 2021 at 09:06:17AM -0700, Paul Evans wrote:
To solve this I could imagine two possibilities.
Both involve keeping track of the prevailing COP in effect for deferred recursive calls, and somehow ensuring that the invoked function is aware of it. For toplevel functions and code this would be the first op itself because that will be a COP, but for anything else (e.g. these LOGOP op_other branches) we can instead pass the prevailing COP we encountered at the time.
1) Change the signature of the PL_rpeepp function to pass a COP as well.
2) Keep the signature but ensure that
PL_curcop
itself is set to the correct value before invoking the function.Option 1 is conceptually neater, but more disruptive in causing a code-level breakage of existing code. Option 2 avoids sourcecode breakage, but then code written presuming the new style will silently give the wrong results on older perls, rather than failing to compile as it would under option 1.
In general, isn't PL_curcop already localised to the current COP when calling rpeep?
-- Dave's first rule of Opera: If something needs saying, say it: don't warble it.
Modules which wish to install custom recursive peephole optimizers will wrap their hook function around
PL_rpeepp
.As it would be rude to apply optimizations globally, any polite optimizing module should inspect the prevailing lexical hints-hash before applying their changes. An example of such can be seen in my
Faster::Maths
module at:https://metacpan.org/source/PEVANS/Faster-Maths-0.02/lib%2FFaster%2FMaths.xs#L253-257
This only works if the first op we encounter is an
OP_NEXTSTATE
, which while true of function bodies isn't always true in general. Perl core will take care to invokePL_rpeepp
for the mainop_next
chain of every function, but also in lots of special cases, such as theop_other
of LOGOPs likeOP_AND
. In such a case, the first op we see on the righthand side of anand
operator is not anOP_NEXTSTATE
. This means that we don't see the prevailing lexical hints (via the COP) when optimizing this branch.Faster::Maths
has to work around this by manually recursing into these cases, passing in values obtained from the prevailing COP itself:https://metacpan.org/source/PEVANS/Faster-Maths-0.02/lib%2FFaster%2FMaths.xs#L290