Skip to content

Conversation

richardleach
Copy link
Contributor

This PR collects a hodge-podge of miscellany noticed while working on a separate branch.

Each commit (should) either cover a single theme or concern a single function.


  • This set of changes does not require a perldelta entry.

SV bodies are Zero()ed when allocated/uprooted from an arena for use.
This commit changes instances where a fresh body field is unnecessarily
assigned a zero/NULL value into an assertion that the field already
contains the desired value.
Prior to this commit, `newSVbool`, `newSV_true`, and `newSV_false` used
`newSVsv`, but that is less efficient than directly setting up the new
SV as it needs to be.
Perl_regexec_flags had these lines to first create a new SV, then assign
to it the value(s) of an existing SV:
```
        reginfo->sv = newSV_type(SVt_NULL);
        SvSetSV_nosteal(reginfo->sv, sv);
```
This is two calls into _sv.c_ and, if the existing SV is `SvOK`, will
incur an SV upgrade in the process. Those lines are preceded with the
comment:
`Not newSVsv, either, as it does not COW.`

However, the underpinnings of `newSVsv` and variants do support COW
nowadays, so we can now just do:
```
reginfo->sv = newSVsv_flags(sv, SV_GMAGIC|SV_NOSTEAL|SV_DO_COW_SVSETSV);
```
Rather than create an `SVt_NULL`, then immediately to `sv_upgrade` it
(within the `sv_usepvn` call) to an SVt_PV, just create the SVt_PV in
the first place.
Since `new_XPV()` was added, this function can handle both branches of
`if (len)` without needing to call any other function. This should be
slightly more efficient for both branches.
Although this appears in an UNLIKELY branch, this commit shaves off
some CPU instructions and may generally help the compiler to
optimise the more likely branches.
This commit:
* swaps `SvLEN_set(sv, 0)` for an assertion of this default value.
* Moves `SvCUR_set` and the (now-combined) flag assignment before the
  call to `sharepvn`, giving the compiler a better chance to combine
  them with the initialization (likely) inlined from `newSV_type(SVt_PV)`.
Existing comments highlighted the common case, confirmed by a _gcov_
build and run of the test harness.

For that workload:
* `(!hek)` is vanishingly rare
* `(flags & HVhek_NOTSHARED)` isn't hit by core at all.
* `(HEK_LEN(hek) == HEf_SVKEY)` was about 1% of calls.

The function was refactored in light of the existing comments and that
_gcov_ data. This also cut the number of resulting CPU instructions by
about half on a normal gcc build.
The compiler stands a better chance of optimising the function
this way around.

(e.g. A gcc build reduces from 20 instructions down to 15.)
@tonycoz
Copy link
Contributor

tonycoz commented Oct 13, 2025

  • (flags & HVhek_NOTSHARED) isn't hit by core at all.

The only place I see HVhek_NOTSHARED being set is when it's already set elsewhere.

assert(!GvCVu(gv));
GvCV_set(gv, cv);
GvCVGEN(gv) = 0;
assert(GvCVGEN(gv) ==0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: spacing around == inconsistent

@tonycoz
Copy link
Contributor

tonycoz commented Oct 13, 2025

Otherwise fine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants