Dan Sugalski <[EMAIL PROTECTED]> wrote
> Subject: Re: vtbl-based SVs and sv_setsv()
>
> At 06:42 PM 1/13/01 -0800, Benjamin Stuhl wrote:
> >How is setting one SV from another going to be implemented?
> >My (admittedly vague) recollection was that it would be
> >something like
> >
> >void sv_setsv(SV* dest, SV* src)
> >{
> > dest->sv_vtbl->delete(dest); /* clear the old value */
> > dest->sv_vtbl = src->sv_vtbl;
> > dest->sv_vtbl->dupfrom(dest, src); /* and copy in the
> >new */
> >}
> >
> >That is, in $a = $b, $a would get a new vtbl, the one from
> >$b. My question is how does this work with the need for
> >assign-by-value, which is required for things like ties and
> >overloads?
>
> The assignment will look like this in bytecode:
>
> sassign dest_scalar, source_scalar;
>
> and proably like this in C:
>
> dest_scalar->vtable[ASSIGN](source_scalar);
>
> or, more directly, the destination scalar is responsible for handling the
> assignment. Passive scalars will generally toss their contents, reassign
> their vtables, and copy the data, possibly after doing some type checking.
> (If, for example, a variable was a locked type it wouldn't necessarily do
this)
>
> The vtable method for active data will extract what it needs from the
> source scalar and Do Magic with it.
If the destination is passive but the src is complicated, then it might
cause problems if the *dst* is responsible for copying the 'husk'
of the src var. Eg the src may maintain pointers to some complex internal
ref-counted structure which needs updating on copy.
In which case I'd suggest that Benjamin's pseudocode
> > dest->sv_vtbl->delete(dest); /* clear the old value */
> > dest->sv_vtbl = src->sv_vtbl;
> > dest->sv_vtbl->dupfrom(dest, src); /* and copy in the
is the correct implementation for ASSIGN method for a 'simple' scalar
type, in that the dupfrom() method called is that actually associated with
the src rather than dest.
This makes me think of another thing - methods that return a new tmp SV
(eg add): would it be better for them instead to be passed an SV to
assign to?
ie instead of
SV *tmpsv = sv1->add(sv1,sv2); // using C rather C++ arg conventions
we have
tmpsv = new_tmp_sv();
sv1->add(tmpsv,sv1,sv2);
If we are going for a register-based system (ie an array of tmp SVs
for use by the compiler/optimiser), then this could cut down on unnecessary
tmp SV creation, copying and destruction.
This is analagous to a generic 3-address CPU architecure with an
add instruction like add "r1,r2,r3".
The code $a = $b + $c * $d would then appear in bytecode as
mult c, d, r1 # r1 is a "register" SV that the compiler has determined is free
add b, r1, r2 # ditto r2
sassign r2, a
Note that in this scheme, a method has to assume that it's destination
arg is 'simple' and can have any existing contents blown away -
or possibly even that it is the callers' responsiblity to have already
blown away any previous contents.
Becuase of this, was can't optimise
add b, r1, r2
sassign r2, a
into
add b, r1, a
unless we know at compile time that $a is a 'simple' scalar.