Re: PMC flags

1 view
Skip to first unread message

Leopold Toetsch

unread,
May 2, 2005, 2:58:43 AM5/2/05
to Nicholas Clark, perl6-i...@perl.org, poni...@perl.org
Nicholas Clark <ni...@ccl4.org> wrote:
> Parrot gives each PMC class 8 private flag bits. I was wondering how to use
> these most efficiently for ponie. My thoughts so far are

> 1 bit for SVf_IOK
> 1 bit for SVf_NOK
> 1 bit for SVf_POK
> 1 bit for SVf_ROK

I'd not mess around with (or introduce) flag bits. The more that this
would only cover perl5 PMCs. Presuming that the Perl5 PMCs are subtypes
of Parrot core PMCs, I'd do ...

// init
STRING* Integer_string = const_string(interpreter, "Integer");
STRING* scalar_string = const_string(interpreter, "scalar");
...

i_ok = VTABLE_isa(interp, pmc, Integer_string);
scalarish_ok = VTABLE_does(interp, pmc, scalar_string);
...

... *if* you really want to know what the PMC is. Usually you just call
the vtable (or MMD) on the PMC and, if it can do the operation, it will
do it.

The vtable functions C<isa> and C<does>, which take now a string, are a
bit heavy-weighted and might get an extension in the log run that take
an integer flag. Keeping these functions in one place will not harm.

> The PMC has a union that can store an integer or a floating point value or
> a reference (or a string - now sure whether to store a parrot string or a
> char * for SvPVX)

This is the currently layout. As mentioned several times, I'd rather
like to have more specialized, *variable-sized* PMCs. E.g.

+--------------+ +--------------+
| VTABLE *vt | | VTABLE *vt |
+--------------+ +--------------+
| void *data |---+ | void *data |--->+--------------+
+--------------+ | +--------------+ | FLOATVAL |
| INTVAL int_v | <-+ | | | num_val |
+--------------+ +--------------+ | |
+--------------+

Integer Integer upgraded to a Float

Another (half cooked) idea is to have and additional indirection on PMC
access and just resize or move the PMC memory.

> 2 bits to say what we're storing in the union

The vtable is that information:

INTVAL i = VTABLE_get_integer(interpreter, pmc);
FLOATVAL n = VTABLE_get_number(interpreter, pmc);

and

VTABLE_set_integer_native(interpreter, pmc, i);
VTABLE_set_number_native(interpreter, pmc, n);

just do the right thing. Usually there is no need to query the PMC what
it is.

> Nicholas Clark

leo

Aaron Sherman

unread,
May 3, 2005, 9:54:40 PM5/3/05
to Perl6 Internals List, poni...@perl.org
On Mon, 2005-05-02 at 08:58 +0200, Leopold Toetsch wrote:
> Nicholas Clark <ni...@ccl4.org> wrote:

> > 1 bit for SVf_IOK
> > 1 bit for SVf_NOK
> > 1 bit for SVf_POK
> > 1 bit for SVf_ROK
>
> I'd not mess around with (or introduce) flag bits. The more that this
> would only cover perl5 PMCs. Presuming that the Perl5 PMCs are subtypes
> of Parrot core PMCs, I'd do ...

[... code doing a string "isa" check on the type ...]

> The vtable functions C<isa> and C<does>, which take now a string, are a
> bit heavy-weighted and might get an extension in the log run that take
> an integer flag.

Unless this happens, this would be a HUGE performance hit. After all,
Sv*OK is called all over the place in the Perl 5 code, including many
places where performance is an issue.

[...]


> > 2 bits to say what we're storing in the union
>
> The vtable is that information:
>
> INTVAL i = VTABLE_get_integer(interpreter, pmc);
> FLOATVAL n = VTABLE_get_number(interpreter, pmc);

Here is some example P5 source from pp_pow in pp.c:

if (SvIOK(TOPm1s)) {
bool baseuok = SvUOK(TOPm1s);
UV baseuv;

if (baseuok) {
baseuv = SvUVX(TOPm1s);
} else {
IV iv = SvIVX(TOPm1s);

and here that is, run through the C pre-processor: pre-processor:

if ((((*(sp-1)))->sv_flags & 0x00010000)) {
char baseuok = ((((*(sp-1)))->sv_flags & (0x00010000|0x80000000)) == (0x00010000|0x80000000));
UV baseuv;

if (baseuok) {
baseuv = ((XPVUV*) ((*(sp-1)))->sv_any)->xuv_uv;
} else {
IV iv = ((XPVIV*) ((*(sp-1)))->sv_any)->xiv_iv;

Notice that there is exactly no function calling going on there. To
change that to (pseudocode):

if (isa_int_test(TOPm1s)) {
bool baseuok = isa_uint_test(TOPm1s);
UV baseuv;

if (baseuok) {
baseuv = invoke_uint_vtable_get(TOPm1s);
} else {
IV iv = invoke_int_vtable_get(TOPm1s);

Well... even after JIT compilation, function call overhead is function
call overhead, no?

> just do the right thing. Usually there is no need to query the PMC what
> it is.

If you're writing a compiler from scratch, I can see that being mostly
true. However, in trying to port Perl 5 guts over to Parrot, there's a
lot of code that relies on knowing what's going on (e.g. if a value has
ever been a number, etc.)


Leopold Toetsch

unread,
May 4, 2005, 1:51:26 AM5/4/05
to Aaron Sherman, Perl6 Internals List, poni...@perl.org
Aaron Sherman wrote:
> On Mon, 2005-05-02 at 08:58 +0200, Leopold Toetsch wrote:

>>The vtable functions C<isa> and C<does>, which take now a string, are a
>>bit heavy-weighted and might get an extension in the log run that take
>>an integer flag.
>
>
> Unless this happens, this would be a HUGE performance hit. After all,
> Sv*OK is called all over the place in the Perl 5 code, including many
> places where performance is an issue.

> Here is some example P5 source from pp_pow in pp.c:

I presume that Ponie eventually will run Parrot opcodes. pp_pow() is
like all these functions part of the perl runloop. Therefore it'll be

infix .MMD_POW, P1, P2, P3

which will do a MM dispatch depending on (P1, P2). That's all. No flags
needed.

> If you're writing a compiler from scratch, I can see that being mostly
> true. However, in trying to port Perl 5 guts over to Parrot, there's a
> lot of code that relies on knowing what's going on (e.g. if a value has
> ever been a number, etc.)

Most of the guts are called from the runloop. But there is of course XS
code that messes with SV internals.

leo

Nicholas Clark

unread,
May 4, 2005, 12:26:25 PM5/4/05
to perl6-i...@perl.org, poni...@perl.org
On Mon, May 02, 2005 at 08:58:43AM +0200, Leopold Toetsch wrote:
> Nicholas Clark <ni...@ccl4.org> wrote:
> > Parrot gives each PMC class 8 private flag bits. I was wondering how to use
> > these most efficiently for ponie. My thoughts so far are
>
> > 1 bit for SVf_IOK
> > 1 bit for SVf_NOK
> > 1 bit for SVf_POK
> > 1 bit for SVf_ROK
>
> I'd not mess around with (or introduce) flag bits. The more that this
> would only cover perl5 PMCs. Presuming that the Perl5 PMCs are subtypes

Yes, this is the bit I'd not fully thought through. At some point when
ponie gets mature the innards are going to be presented with SVs that are
actually PMCs which aren't Perl 5 types.

Nicholas Clark

Nicholas Clark

unread,
May 4, 2005, 12:50:25 PM5/4/05
to Dave Mitchell, Aaron Sherman, Leopold Toetsch, poni...@perl.org, Perl6 Internals List
On Mon, May 02, 2005 at 12:24:04AM +0100, Dave Mitchell wrote:
> On Sun, May 01, 2005 at 11:36:02PM +0100, Nicholas Clark wrote:
> > in the common cases be able to access the PObj structure members directly.
>
> I may be speaking here like someone at the back who hasn't been paying
> attention, but..
>
> isn't the whole point of PMCs to provide encaspulation, so isn't the
> ponie core directly checking flags and accessing PMCs internals just a
> tad naughty?

The problem is as Aaron describes it - there's a heck of a lot of code in
the perl code that is busy doing flag tests, and I doubt that all of it is
going to get re-written.

I'm assuming that non-Perl5 PMCs are going to behave like some sort of variant
of a tied-thing to Perl 5 code, but the native scalars created in Perl 5
space are going to need to continue behaving the way they currently do.
Somehow.

I was still thinking that there would be encapsulation - this was more an
optimisation thought for the existing Sv*() flag test macros. Currently
they're all calling Parrot_PMC_get_intval_intkey() to ask the PMC for a
flag's value, but that PMC method is really for getting array elements, as
I understand it, and therefore isn't going to be viable once Perl 5 AVs
need to start presenting an array like interface to the world, and quack the
way any other Parrot PMC array type quacks.

On Tue, May 03, 2005 at 09:54:40PM -0400, Aaron Sherman wrote:
> On Mon, 2005-05-02 at 08:58 +0200, Leopold Toetsch wrote:
> > Nicholas Clark <ni...@ccl4.org> wrote:
>
> > > 1 bit for SVf_IOK
> > > 1 bit for SVf_NOK
> > > 1 bit for SVf_POK
> > > 1 bit for SVf_ROK
> >
> > I'd not mess around with (or introduce) flag bits. The more that this
> > would only cover perl5 PMCs. Presuming that the Perl5 PMCs are subtypes
> > of Parrot core PMCs, I'd do ...
> [... code doing a string "isa" check on the type ...]
>
> > The vtable functions C<isa> and C<does>, which take now a string, are a
> > bit heavy-weighted and might get an extension in the log run that take
> > an integer flag.
>
> Unless this happens, this would be a HUGE performance hit. After all,
> Sv*OK is called all over the place in the Perl 5 code, including many
> places where performance is an issue.

This was my fear.


On Wed, May 04, 2005 at 07:51:26AM +0200, Leopold Toetsch wrote:
> Aaron Sherman wrote:
> >On Mon, 2005-05-02 at 08:58 +0200, Leopold Toetsch wrote:
>
> >>The vtable functions C<isa> and C<does>, which take now a string, are a
> >>bit heavy-weighted and might get an extension in the log run that take
> >>an integer flag.
> >
> >
> >Unless this happens, this would be a HUGE performance hit. After all,
> >Sv*OK is called all over the place in the Perl 5 code, including many
> >places where performance is an issue.
>

> >Here is some example P5 source from pp_pow in pp.c:
>

> I presume that Ponie eventually will run Parrot opcodes. pp_pow() is
> like all these functions part of the perl runloop. Therefore it'll be
>
> infix .MMD_POW, P1, P2, P3
>
> which will do a MM dispatch depending on (P1, P2). That's all. No flags
> needed.

Yes, I think that the plan is that eventually all the PP code gets
converted into the PMCs. However there's a lot of source outside pp*.c and
the SV/AV/HV/CV/GV manipulation code.

> >If you're writing a compiler from scratch, I can see that being mostly
> >true. However, in trying to port Perl 5 guts over to Parrot, there's a
> >lot of code that relies on knowing what's going on (e.g. if a value has
> >ever been a number, etc.)
>

> Most of the guts are called from the runloop. But there is of course XS
> code that messes with SV internals.

Which is the stuff we're trying to keep working unchanged.

Speed-wise, I think the problem I *think* I was trying to address here was
that there's a lot of XS and core code that assumes that SV flag checking is
a fast operation. And as "Flag" checking isn't standard parrot vtable
operation it's not going to be fast on any scalar, and as it's not a standard
parrot vtable operation, all the alien types passed into the perl code aren't
automatically going to report back the correct flags to say "treat me roughly
like a string" or "roughly like a number" or "a reference to something else"

Nicholas Clark

Dave Mitchell

unread,
May 4, 2005, 1:01:32 PM5/4/05
to perl6-i...@perl.org, poni...@perl.org


How about a vtable method that returns an integer of some common flags that
are meaningful to both p5 and parrot?

then pp_pow() would just need to call it once at the start, then do
various checks on the returned value?

So pseduo-code like

if (pmc->vtable->is_IOK())
...
else if (pmc->vtable->is_NOK())
...

becomes

status = pmc->vtable->status();
if (status & IOK)
...
else if (status & NOK)
...

#include <std disclaimer about me knowing almost zilch about parrot>

Dave

--
My get-up-and-go just got up and went.

Leopold Toetsch

unread,
May 4, 2005, 3:34:16 PM5/4/05
to Dave Mitchell, perl6-i...@perl.org, poni...@perl.org
Dave Mitchell wrote:

> So pseduo-code like
>
> if (pmc->vtable->is_IOK())
> ...
> else if (pmc->vtable->is_NOK())
> ...
>
> becomes
>
> status = pmc->vtable->status();
> if (status & IOK)
> ...
> else if (status & NOK)

That would still need to rewrite all but 1% of perl5 code and doesn't
help XS.

> #include <std disclaimer about me knowing almost zilch about parrot>

> Dave

the zilch .. perl5 .. leo

Leopold Toetsch

unread,
May 4, 2005, 3:27:32 PM5/4/05
to poni...@perl.org, Perl6 Internals List
Nicholas Clark wrote:

[ CCs cleared by some ]

> ... However there's a lot of source outside pp*.c and
> the SV/AV/HV/CV/GV manipulation code.

A lot of that are helper functions for pp code, but anyway yes, the code
exists and is an API.

> Which is the stuff we're trying to keep working unchanged.

If its not much called it doesn't matter, but see below.

> Speed-wise, I think the problem I *think* I was trying to address here was
> that there's a lot of XS and core code that assumes that SV flag checking is
> a fast operation

Yes XS is the big problem here. The huge difference between perl5 and
parrot/perl6 is the handling of (scalar) types. In perl5 everything is
flags based with cascades of switch statements. In parrot there is
either a vtable or a MMD sub. For scalar types we basically don't need
any flag bits in parrot.

I've (with not much success) already presented a plan to get both worlds
together:

* PMCs become variable sized
* upgrading is similar to perl5

A perl5 IV PMC could therefore inherit vtable, MMD and layout from a
core Integer PMC and have an additional flag word. Interoperbility would
work at the opcode level.

leo

Aaron Sherman

unread,
May 4, 2005, 7:08:53 PM5/4/05
to Leopold Toetsch, Perl6 Internals List, poni...@perl.org
On Wed, 2005-05-04 at 01:51, Leopold Toetsch wrote:
> Aaron Sherman wrote:
> > On Mon, 2005-05-02 at 08:58 +0200, Leopold Toetsch wrote:

> > Here is some example P5 source from pp_pow in pp.c:
>
> I presume that Ponie eventually will run Parrot opcodes. pp_pow() is
> like all these functions part of the perl runloop. Therefore it'll be
>
> infix .MMD_POW, P1, P2, P3

Sorry, I wasn't being clear with my example and the fact that it was
just that.

Yes, I understand that the opcode "pow" will become Parrot... well, at
least I think I understand that, but I'm not 100% sure. There's some
very hairy magic in pp.c and pp_hot.c that Perl code relies on, and in
some places (e.g. pp_add), its behavior is not compatible with Parrot in
some very fundamental ways (e.g. all addition is done as unsigned
integers if/when possible to gain the overflow semantics of C8X uint,
check the novella-length comments in pp.c for details).


ALL THAT ASIDE, however, I did understand that the goal was not
explicitly to leave pp_pow as it is. I was using it as an example of the
kind of code that uses the Perl 5 core. XS, the Perl 5 runtime (e.g. the
regexp engine), parser, etc. all rely on the same sort of constructs
that I used pp_pow to outline.

> > If you're writing a compiler from scratch, I can see that being mostly
> > true. However, in trying to port Perl 5 guts over to Parrot, there's a
> > lot of code that relies on knowing what's going on (e.g. if a value has
> > ever been a number, etc.)
>
> Most of the guts are called from the runloop. But there is of course XS
> code that messes with SV internals.

Ignore code that "messes with SV internals". Code in many parts of the
runtime that almost certainly won't be re-written use the SV interface
provided by sv.h correctly, doing tons of flag tests all the time.
Literally every operation requires several flag tests!

--
Aaron Sherman <a...@ajs.com>
Senior Systems Engineer and Toolsmith
"It's the sound of a satellite saying, 'get me down!'" -Shriekback


Reply all
Reply to author
Forward
0 new messages