-
Notifications
You must be signed in to change notification settings - Fork 589
Description
Description
Many arithmetic or comparison operators change the SV type of their operands when the operands are of different type.
For example, when adding an IV and an NV, the NV will always be upgraded:
perl -MDevel::Peek -e '$nv = 1.33; Dump($nv); $res = 2 + $nv; Dump($res); Dump($nv);'
SV = NV(0x561243b9ee90) at 0x561243b9eea8
REFCNT = 1
FLAGS = (NOK,pNOK)
NV = 1.33
SV = NV(0x561243b9ef38) at 0x561243b9ef50
REFCNT = 1
FLAGS = (NOK,pNOK)
NV = 3.33
SV = PVNV(0x561243b6e040) at 0x561243b9eea8
REFCNT = 1
FLAGS = (NOK,pIOK,pNOK)
IV = 1
NV = 1.33
PV = 0
When the operands are only SvIOK(sv) and SvNOK(sv) like this, it's not clear what the benefits are of changing the SV type, rather than just fetching the actual value and converting it within the op, and not altering the SV at all. (Conversion could be done either directly in the likes of the SvIV_nomg and SvNV_nomg macros, or by calling a new inline.h function from the likes of those macros.)
Changing the SV type comes with performance costs associated with:
- allocating a different body type (if required) - this also uses additional memory and changes memory locality
- updating the type/flags in the SV head
- calling non-inline functions (e.g. S_sv_2iuv_common or Perl_sv_2iv_flags) in sv.c
The interpreter doesn't take account of how the SV is going to be used elsewhere, so:
- a cascade of potentially-unnecessary SV upgrades could occur
- the SV may repeatedly flip-flop between SvIOK(sv) and SvNOK(sv) - perhaps in different ops - triggering repeated calls to sv.c functions, updates to SV head flags, and probably still a I/UV <-> NV value conversion every time
- the SV may immediately be destroyed, so the upgrade cost were incurred for naught
In comparison, while not upgrading an IV or NV that will repeatedly be used in the same one operation (e.g. as a constant) would also cause repeated value conversion, doing this inline should (hopefully) be much cheaper, especially with modern CPUs.
Questions
- Is there actually a very good reason - in core - for the current behaviour and it should be left as-is?
- Would changes likely cause much/any breakage on CPAN?
- If changes are viable, should new macros/functions be introduced or the existing ones modified?