The patches for RT#67838 are is found in:
5.13.4+ 5.14.0+
I ran your test program with ActivePerl 5.14.0 (32 bit) on Windows, and noticed NO memory increase. (Steady at 99MB.) In fact, I saw in increases only up to that version of Perl.
perl -E"$x=x; $x x= 100e6; <>; $r = \substr $x, 50e6; <>; ord $$r; <>" AP 5.12.4 32-bit 99M 148M 148M AP 5.14.0 32-bit 99M 99M 148M AP 5.14.2 32-bit 99M 99M 148M
There will be a memory increase if you read the string $$r, but that's how magic works in Perl.
I looked at the source code at the time of the patch. There is no intentional "prefetching", and testing shows no accidental prefetching:
>\progs\perl5142-ap1402\bin\perl -MDevel::Peek -E"$x=chr(0); $x x= 100 +; Dump substr $x, 50;" SV = PVLV(0x4de51c) at 0x497b04 REFCNT = 1 FLAGS = (TEMP,GMG,SMG) IV = 0 NV = 0 PV = 0 <----- No buffer MAGIC = 0x4cc694 MG_VIRTUAL = &PL_vtbl_substr MG_TYPE = PERL_MAGIC_substr(x) TYPE = x TARGOFF = 50 TARGLEN = 50 TARG = 0x4a932c SV = PV(0x25603c) at 0x4a932c REFCNT = 2 FLAGS = (POK,pPOK) PV = 0x4b36cc "\0\0\0...\0\0\0"\0 CUR = 100 LEN = 104
In contrast with a version that does grow as soon as substr is called:
>\progs\perl5124-ap1205\bin\perl -MDevel::Peek -E"$x=chr(0); $x x= 100 +; Dump substr $x, 50;" SV = PVLV(0x319e4c) at 0x3bf54 REFCNT = 1 FLAGS = (PADMY,GMG,SMG,pPOK) IV = 0 NV = 0 PV = 0x2f42dc "\0\0\0...\0\0\0"\0 <----- CUR = 50 LEN = 52 MAGIC = 0x327f94 MG_VIRTUAL = &PL_vtbl_substr MG_TYPE = PERL_MAGIC_substr(x) TYPE = x TARGOFF = 50 TARGLEN = 50 TARG = 0x2f875c SV = PV(0x36034) at 0x2f875c REFCNT = 2 FLAGS = (POK,pPOK) PV = 0x330f6c "\0\0\0...\0\0\0"\0 CUR = 100 LEN = 104
$ref continues to refer (directly) to the memory allocate to $string.
Neither $ref nor $$ref ever refer directly to $string's PV. They can't because the address of $string's buffer can change as $string changes.
This would require retaining a pointer back to 'parent' string with the lvalue ref
$$ref does have a reference to $string.
Probably difficult to orchestrate.
Actually, that's easy. Just weaken $$ref's reference to $string.
At which point the extraneous (pre and/or post fix) bits of $string are GC'd leaving $ref pointing at just that which it references.
One can't free the start of a memory block. I don't think one can even free the end of a memory block. The string would have to be copied to a new buffer in order to shrink the buffer. Doable, but it would require a temporary "doubling" of memory.
It would also be uncharacteristic of Perl. Perl intentially avoids freeing memory left and right. Shrinking a buffer would be a first!
In reply to Re^7: Tracking down an Lvalue bug?
by ikegami
in thread Tracking down an Lvalue bug?
by BrowserUk
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |