Maintaining Perl 5 Core (Dave Mitchell): July 2022
Wed, 03-Aug-2022 by
Jason A. Crome
edit post
Dave writes:
This is my monthly report on work done during July covered by my TPF perl
core maintenance grant.
```
3:57 BBC: TODDR/YAML-Syck-1.34.tar.gz (Issue #19939)
3:28 Format in fill-mode has inconsistent behaviour (Issue #19985)
4:58 Goto xsub forces scalar context (#19188)
0:57 Returning undef returns a weird hash reference (Issue #19996)
0:37 Segmentation fault with use re 'eval' (Issue #19390)
0:20 fix build warning
39:28 make stack reference counted
6:11 process p5p mailbox
1:16 segfault on goto &xs_sub when calling sub is replaced (Issue #19936)
------
61:12 TOTAL (HH::MM)
```
I worked on quite a few tickets last month, but the most important thing I
did was to continue work on making the stack reference counted (work I
started near the end of June).
This is still very much a work in progress and I have nothing visible
(i.e. pushed) to show for it yet, but what I have done so far is:
1) Put wrappers around 254 pp functions.
This changes the definitions of pp function from e.g.:
```
PP(pp_subst)
{
...
}
```
to
```
PP_wrapped(pp_subst, ((PL_op->op_flags & OPf_STACKED) ? 2 : 1), 0)
{
...
}
```
which on normal builds has no effect, but on builds with `PERL_RC_STACK`
defined, it expands to something like:
```
OP*
Perl_pp_subst(aTHX) {
return
Perl_pp_wrap(my_perl, S_norcs_pp_subst,
((PL_op->op_flags & OPf_STACKED) ? 2 : 1), 0);
}
STATIC OP*
S_norcs_pp_subst(pTHX)
{
...
}
```
`pp_wrap()` is responsible for pushing a (non-reference-counted) copy
of the current stack frame onto the end of the stack, then calling the
original pp function `S_norcs_pp_subst()`, which doesn't know about
reference-counted arguments, then shifting down and bumping the reference
count of everything that it returns on the stack.
The two numeric arguments for `pp_wrap` are how many arguments that op
expects on the stack, or for list ops, how many (mark-delineated) lists it
expects. Often these are just constants, but for some, like `pp_subst`, it
varies depending on flags.
2) Of the remaining 56 pp functions, some didn't need wrapping (like
`pp_pushmark`), while others required special handling - like most of the
`pp_enterfoo` and `pp_leavefoo` functions. For example most leavefoo ops in
void context just abandon any arguments left on the stack:
```
PL_stack_sp = PL_stack_base + cx->blk_oldsp;
```
For a reference-counted stack, this means that all those SVs leak. So I've
replaced all such occurrences with an inline function call:
```
rpp_pop_to(PL_stack_base + cx->blk_oldsp);
```
which on normal builds just resets `PL_stack_sp`, while on `PERL_RC_STACK`
builds, it will decrement the reference count of all those abandoned stack
items first.
I have almost finished doing (2) - just a handful of ops still need going
over on a line-by-line basis (in particular `pp_goto()`, which I've been
leaving to absolutely last).
None of the changes I've done so far actually do reference-counting yet: `pp_wrap()`, `rpp_pop_to()` etc currently have any `SvREFCNT_dec()`s etc
commented out. The idea is that I can initially add all these
modifications to the core while perl still works, Then once all that work
is done I should be able to make changes in a small number of places - `pp_wrap()`, `rpp_pop_to()` etc - and the whole of the perl core should
become reference-count-aware at once. This means that initially the core
will be merely mostly broken rather than completely broken, and it should
be easier to fix up those remaining bits which need it.
Then later on, things can be made more efficient again, e.g. by removing
the wrapper functions from common ops and make them directly
reference-count aware instead.
PS - for the avoidance of doubt, even with all these changes, unless the
core is built with `PERL_RC_STACK` defined, none of these changes take
affect yet.
Comments (0)