On Thu, 19 Dec 2002, Leopold Toetsch wrote:

> David Robins wrote:
> >  This method is primarily used when the interpreter has need of
> >  coercing a PMC to a particular type, and isn't meant as a general
> >  purpose casting tool. Compilers should only emit valid
> >  transformations.
> > which doesn't seem to indicate that morph is the Right Thing,
>
> docs also say, "If the morphing
>             can't be reasonably done, for example if an integer is
>             asked to turn into a PerlArray, then the PMC is first
>             destroyed, then recreated as an empty PMC ..."
>
> which seems to indicate that morph is the Right Thing ;-)

Well, what I was getting at was that if dest is, say, a RomanNumeralInteger
whose value is "mcmlxxxiv", I don't want it to waste time converting that to
the integer 1984 when I morph it to a PerlInt, if my next step is to
unilaterally set its value to 5.

> Currently we are "morphing" perlscalars all over the place. We do this
> by replacing the vtable (and in case of strings) also changing flags.

Which is sort of evil, but it makes up for that by being fast, I guess :D.

> This is what morph would do anyway, w/o actually destroying the PMC but
> reusing the header (new vtable, new value, changed flags gives actually
> the same as a freshly allocated PMC of the desired type).

And without calling init()... but in the cases that it is done, it isn't
needed.  More knowledge of internals trading for efficiency.

> >       PMC* ret = SELF.clone();
>
> Cloning or making a new PMC for each LHS isn't that cheap. I think we
> should reuse existing headers where possible. The same holds for string
> headers, which are currently sparely reused.

One would hope it could be made as cheap as Perl's SV allocation, which with
the plant/uproot mechanism, is probably pretty darn fast.  Even allocating
memory isn't bad if it uses the fixed-size allocator.

Still, with the present "dest* PMC", how is a new PMC to be returned?  Since
the address is the same, the old one won't be GC'd, thus destroy won't be
called (so it will need to be called explicitly as I had in an earlier
message).  Then the new vtable/flags have to be set and init called (which
is often a no-op and can be skipped, especially if an assignment is to be
done right away).

Maybe a "placement pmc_new" would be a good idea (assuming that the PMC
header remains the same size for all types), i.e.

PMC*
pmc_new_placement(struct Parrot_Interp* interpreter, PMC* dest,
 INTVAL base_type)
{
  if(dest->flags & PMC_active_destroy_FLAG) {
    dest->vtable->destroy(interpreter,dest);
  }

  dest->vtable = Parrot_base_vtables+base_type;

  if(!dest->vtable || !dest->vtable->init) {
    PANIC("NULL vtable used");
    return NULL;
  }

  dest->vtable->init(interpreter, dest);

  return dest;
}

with appropriate variants (init/noinit).

> > The (or one of the) subjects of the op has a better idea of the result type
> > than the caller (for example, $b and $c could be floats, or integers, and
> > the target should match, but the HL doesn't know which they are at compile
> > time).
> The HL probably doesn't know, which scalar type, but should know e.g.
> aggregate yes/no or which aggregate.

I take it you mean for "no aggregate" it should set the dest type to be a
"generic scalar", but what about languages that don't have such a "base
class" (or that don't know at runtime even if they have an aggregate or
not, such as more "pure OO" languages)?

> leo

Dave
Isa. 40:31

Reply via email to