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.







Reply via email to