On Wed Feb 27 09:43:12 2013, RIBASUSHI wrote:
Show quoted text> On Wed Jan 16 02:04:20 2013, SMUELLER wrote:
> > Hmm, I have a fix (sv_mortalcopy), but it slows simple accessors down by
> > a bit more than 10%. Ouch. Will have to ponder.
>
> Would it be an option to flip the RO flag on scalars (and only scalars)
> returned by this?
Sorry for not replying to this earlier. It slipped through the net somehow.
No, it's not possible to do that since the scalars returned by the methods are the exact same scalars that are stored in the object. That is the root of the problem.
I have, however, spent more time thinking about this in the meantime. The original workaround/fix for the issue was to allocate a new SV, copy the original SV into it, then push the new SV on the mortal stack, then return it. That's slow. My money is on the allocation and mortalization being by far the slowest part usually.
This can most likely be improved on considerably by using a PADTMP entry like many other OPs do: It remains allocated, it doesn't need mortalization. Just an SV copy into it and push it on the stack. Downside: It'll be cozy with the core and chances are, it isn't doable with strictly API calls.
Secondly, we know it's certain operations where this is a problem at all.
my $x = $o->foo;
is safe because the SV will be copied into the PAD SV that is $x.
\$o->foo
is unsafe because the reference will refer to the actual same SV.
The latter case can be identified at OP-optimization time by looking at the entersub's op_next execution order pointer something like this:
if (OP_CLASS(o->op_next) == OP_REF) {
... do not optimize ...
}
I didn't bother looking up OP_REF, though.
This has a similar cozy-with-core downside, and additionally, it may yield false negatives: It'll be hard to catch all cases. Here's another example with aliasing semantics where I wouldn't know how to detect it statically (and efficiently so):
perl -e 'package F; use Class::XSAccessor getters => [qw(foo)]; $x = bless({foo => "bar"} => "F"); sub f {return \@_} $y=f($x->foo); $y->[0]++; warn $x->{foo};'
bas at -e line 1.
Best regards,
Steffen