Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

pdd06_pasm, pdd08_keys: _keyed ops

12 views
Skip to first unread message

Leopold Toetsch

unread,
Sep 18, 2002, 4:40:09 AM9/18/02
to P6I
Above docs state, that a gernal parrot op looks like this

op dest[dkey], src1[skey1], src2[skey2]

e.g.

add P0[P1], P2, P3[P4]

where P1 and P4 are keys and P0 and P3 are aggregates and P2 is a scalar.

Several questions arise from these pdd's:

1) Are above pdd's valid, WRT this 3 key opcodes?

2) What PASM ops should above statement generate:
a) add_p_k_p_p_k (i.e. all variations of /p(_k)?/ )
b) add_p_k_p_k_p_k
if b) how to create a NULL key and how does it look like in PBC?

Thanks,
leo

Tom Hughes

unread,
Sep 18, 2002, 5:16:46 AM9/18/02
to Leopold Toetsch, perl6-i...@perl.org
In message <3D883BE9...@toetsch.at>
Leopold Toetsch <l...@toetsch.at> wrote:

> Above docs state, that a gernal parrot op looks like this
>
> op dest[dkey], src1[skey1], src2[skey2]
>
> e.g.
>
> add P0[P1], P2, P3[P4]
>
> where P1 and P4 are keys and P0 and P3 are aggregates and P2 is a scalar.
>
> Several questions arise from these pdd's:
>
> 1) Are above pdd's valid, WRT this 3 key opcodes?

As far as I know PDD 08 is up to date, at least if you ignore the lack
of detail on how to generate keys dynamically, which I have a patch
for that I need to finish off.

There was however some discussion as to whether we wanted to limit
keyed access to just the set/assign opcodes in order to avoid the
explosion of ops that would occur if we supported keyed access
directly on every op.

> 2) What PASM ops should above statement generate:
> a) add_p_k_p_p_k (i.e. all variations of /p(_k)?/ )
> b) add_p_k_p_k_p_k
> if b) how to create a NULL key and how does it look like in PBC?

As things stand it would have to be option a, or at least that is what
the current assembler would generate. There isn't much else it can do
really - how would it know when to generate a null key for an operand
and when not to?

I believe you could encode a key constant with zero components in the
byte code if you wanted - the first word of the constant is the
component count after all.

Tom

--
Tom Hughes (t...@compton.nu)
http://www.compton.nu

Tom Hughes

unread,
Sep 18, 2002, 7:47:22 AM9/18/02
to Leopold Toetsch, perl6-i...@perl.org
In message <3D88659D...@toetsch.at>
Leopold Toetsch <l...@toetsch.at> wrote:

> >>2) What PASM ops should above statement generate:
> >>a) add_p_k_p_p_k (i.e. all variations of /p(_k)?/ )
> >>b) add_p_k_p_k_p_k
> >> if b) how to create a NULL key and how does it look like in PBC?
> >>
> > As things stand it would have to be option a, or at least that is
> > what
>
> > the current assembler would generate. There isn't much else it can do
> > really - how would it know when to generate a null key for an operand
> > and when not to?
>

> If there is a plain P0 without [], the assembler hat to insert a NULL
> key instead.

In other words we assume all PMC arguments have a key, so you can
never have a p in a opcode name with one of k/kc/ki/kic following it?

You will still get horrible op explosion for a three argument op as
even if you assume that all PMCs are keyed, there are four key types
which, with three operands, gives you 64 ops in total.

Leopold Toetsch

unread,
Sep 18, 2002, 7:38:05 AM9/18/02
to Tom Hughes, perl6-i...@perl.org
Tom Hughes wrote:

> In message <3D883BE9...@toetsch.at>
> Leopold Toetsch <l...@toetsch.at> wrote:
>
>
>>op dest[dkey], src1[skey1], src2[skey2]
>>
>>e.g.
>>
>>add P0[P1], P2, P3[P4]

> There was however some discussion as to whether we wanted to limit


> keyed access to just the set/assign opcodes in order to avoid the
> explosion of ops that would occur if we supported keyed access
> directly on every op.


The first question is, does a HL need such operations? Or better,
does/will it produce such operations?

E.g. @a[$i] = $j + @b[$k] + 1 produces a sequence of PerlUndef's to hold
the intermediate operands of Binop('+'). Of course clever code
generation or an optimizer could take advantage of these _keyed operations.

If we really want _keyed operations for all ops (and even when not) I
would flag the _keyed ops and preprocess them in the run loop:

- op and op_keyed have the same (opcode & OP_FLAG_MASK)

if (op & OP_KEY1_FLAG)
arg1p = get_entry(arg1,key)
else
arg1p = P(arg1)
...
DO_OP(op & OP_FLAG_MASK, argp1...)
if (op & OP_KEY1_FLAG)
store_entry...

Very similar to predereferencing.
Actually, it could prederefernce all operands.

This would save a lot of opcodes and provide a smaller and more compact
core. Predereferncing is faster then other runmodes.

>>2) What PASM ops should above statement generate:
>>a) add_p_k_p_p_k (i.e. all variations of /p(_k)?/ )
>>b) add_p_k_p_k_p_k
>> if b) how to create a NULL key and how does it look like in PBC?
>>
>
> As things stand it would have to be option a, or at least that is what
> the current assembler would generate. There isn't much else it can do
> really - how would it know when to generate a null key for an operand
> and when not to?

If there is a plain P0 without [], the assembler hat to insert a NULL
key instead.

> I believe you could encode a key constant with zero components in the
> byte code if you wanted - the first word of the constant is the
> component count after all.


Yes, that seems to be working.


> Tom


leo


Leopold Toetsch

unread,
Sep 18, 2002, 9:40:41 AM9/18/02
to Tom Hughes, perl6-i...@perl.org
Tom Hughes wrote:


>>If there is a plain P0 without [], the assembler hat to insert a NULL
>>key instead.
>>
>
> In other words we assume all PMC arguments have a key, so you can
> never have a p in a opcode name with one of k/kc/ki/kic following it?


No - only if there is any "p_k" not for _kc/_ki_kic.


> You will still get horrible op explosion for a three argument op as
> even if you assume that all PMCs are keyed, there are four key types
> which, with three operands, gives you 64 ops in total.


No. We would have
set_p_kc
set_p_ki
set_p_kic ... special shortcut set/get, only one key per op allowed
and
op_p_k_p_k ... unary keyed, all k are KEYs
op_p_k_p_k_p_k ... 3 keys bin op, all k are KEYs

All 64 combinations would be a horror.

But I really vote for a predereferencing like solution.


> Tom


leo

Sean O'Rourke

unread,
Sep 18, 2002, 9:44:54 AM9/18/02
to Tom Hughes, Leopold Toetsch, perl6-i...@perl.org
On 18 Sep 2002, Tom Hughes wrote:
> In message <3D883BE9...@toetsch.at>
> Leopold Toetsch <l...@toetsch.at> wrote:
>
> > [ add Px[Ix], Py, Pz[Iz]

> >
> > 2) What PASM ops should above statement generate:
> > a) add_p_k_p_p_k (i.e. all variations of /p(_k)?/ )
> > b) add_p_k_p_k_p_k
> > if b) how to create a NULL key and how does it look like in PBC?
>
> As things stand it would have to be option a, or at least that is what
> the current assembler would generate. There isn't much else it can do
> really - how would it know when to generate a null key for an operand
> and when not to?

Another possible option would be to extend the number of vtable methods
that might end up taking NULL keys -- some of them do already. Then
anything that had any keyed arguments could generate (possibly empty) keys
for _all_ arguments.

/s

Tom Hughes

unread,
Sep 18, 2002, 9:55:42 AM9/18/02
to Leopold Toetsch, perl6-i...@perl.org
In message <3D888259...@toetsch.at>
Leopold Toetsch <l...@toetsch.at> wrote:

> Tom Hughes wrote:
>
> > You will still get horrible op explosion for a three argument op as
> > even if you assume that all PMCs are keyed, there are four key types
> > which, with three operands, gives you 64 ops in total.
>
> No. We would have
> set_p_kc
> set_p_ki
> set_p_kic ... special shortcut set/get, only one key per op allowed
> and
> op_p_k_p_k ... unary keyed, all k are KEYs
> op_p_k_p_k_p_k ... 3 keys bin op, all k are KEYs

So now the assembler has to know that set is special and can have all
four sorts of keys while the other ops only support dynamic keys?

> All 64 combinations would be a horror.

Indeed.

> But I really vote for a predereferencing like solution.

I didn't really understand that part of your previous message, but I
don't see what relevance that has to how the assembler decides on the
op name to use (and hence how to encode the arguments).

Sean O'Rourke

unread,
Sep 18, 2002, 9:49:34 AM9/18/02
to Leopold Toetsch, Tom Hughes, perl6-i...@perl.org
On Wed, 18 Sep 2002, Leopold Toetsch wrote:
> Tom Hughes wrote:
>
> > In message <3D883BE9...@toetsch.at>
> > Leopold Toetsch <l...@toetsch.at> wrote:
> >
> >
> >>op dest[dkey], src1[skey1], src2[skey2]
> >>
> >>e.g.
> >>
> >>add P0[P1], P2, P3[P4]
>
> > There was however some discussion as to whether we wanted to limit
> > keyed access to just the set/assign opcodes in order to avoid the
> > explosion of ops that would occur if we supported keyed access
> > directly on every op.
>
> The first question is, does a HL need such operations? Or better,
> does/will it produce such operations?

Actually, if scratchpads become proper PMC's these ops would be incredibly
useful and common. For example, "@a[0] = %b{1} + $c" might become

add P0["@a";0], P0["%b";"1"], P0["$c"]

This is rather speculative, but if many operations will be on lexicals as
opposed to registers/temporaries, such hoariness might be worth it.

/s

Tom Hughes

unread,
Sep 18, 2002, 9:57:13 AM9/18/02
to Sean O'Rourke, perl6-i...@perl.org
In message <Pine.GSO.4.32.02091...@gradlab.ucsd.edu>

Sean O'Rourke <soro...@cs.ucsd.edu> wrote:

> Actually, if scratchpads become proper PMC's these ops would be incredibly
> useful and common. For example, "@a[0] = %b{1} + $c" might become
>
> add P0["@a";0], P0["%b";"1"], P0["$c"]
>
> This is rather speculative, but if many operations will be on lexicals as
> opposed to registers/temporaries, such hoariness might be worth it.

Except those indexes are key constants which are type kc but Leopold
only wants to allow dynamically created keys of type k on the other ops.

Sean O'Rourke

unread,
Sep 18, 2002, 10:04:09 AM9/18/02
to Tom Hughes, perl6-i...@perl.org
On 18 Sep 2002, Tom Hughes wrote:

Hm... maybe I'd rather have constant and run-time keys go through the same
op. An alternative would be to build up the lexical refs from constant
key-construction ops, then use the _k versions.

/s

Leopold Toetsch

unread,
Sep 18, 2002, 12:04:43 PM9/18/02
to Tom Hughes, perl6-i...@perl.org
Tom Hughes wrote:


> Indeed.


Predereferencing now generates changed bytecode on the fly by
1) putting the absolute address of operands into the opcode stream, so
2) e.g. set_i_ic and set_i_i have the same C-source, actually, since my
patch the former is omitted at all.

For _keyed operands I would propose:

The used keys are not coded into the opcode name (so no 64 variations),
but the opcode-number holds this information.

add_p_p_p (op #297)
app_p_k_p_p => #297 + (KEY1_FLAGS << 16)
add_p_p_k_p => #297 + (KEY2_FLAGS << 16)
....
where KEY1_FLAGS are e.g.
_k 0b0001
_ki 0b0011
_kic 0b0111
_kc 0b0101
KEY2_FLAGS same << 3 ...

Now the current run loop look's like this:
while (pc) {
DO_OP(pc, interpreter);
}

#define DO_OP(PC,INTERP) (PC = (INTERP->op_func_table)[*PC])(PC,INTERP))

I would change the run loop like so:

while (pc) {
argp1 = ...pmc_reg.registers[cur_opcode[1]];
if (*pc & KEY1_MASK) {
key1 = ...pmc_reg.registers[cur_opcode[2]]; /* for p_k */
argp1 = get_keyed_entry(argp1, key1, flags);
}
...
PC = (INTERP->op_func_table)[*PC & KEY_MASK]( ... );
PC += n_keys; /* account for additonal keys in bytecode */
}

which would call add_p_p_p(argp1, argp2, argp3).

"argp" points either directly to the PMC register, or for keys, into the
bucket, where the PMC is stored in the aggregate. Of course, argp
shouldn't move due to GC while processing one op.

This would allow all 64 variations of keyed ops w/o opcode bloat, if
I didn't ignore some essential part ;-)
LHS keys and autovivification, e.g. but this we don't have now either.

> Tom


leo


Tom Hughes

unread,
Sep 18, 2002, 12:14:22 PM9/18/02
to Leopold Toetsch, perl6-i...@perl.org
In message <3D88A41B...@toetsch.at>
Leopold Toetsch <l...@toetsch.at> wrote:

> For _keyed operands I would propose:
>
> The used keys are not coded into the opcode name (so no 64 variations),
> but the opcode-number holds this information.
>
> add_p_p_p (op #297)
> app_p_k_p_p => #297 + (KEY1_FLAGS << 16)
> add_p_p_k_p => #297 + (KEY2_FLAGS << 16)
> ...

> where KEY1_FLAGS are e.g.
> _k 0b0001
> _ki 0b0011
> _kic 0b0111
> _kc 0b0101
> KEY2_FLAGS same << 3 ...
>
> Now the current run loop look's like this:
> while (pc) {
> DO_OP(pc, interpreter);
> }
>
> #define DO_OP(PC,INTERP) (PC = (INTERP->op_func_table)[*PC])(PC,INTERP))
>
> I would change the run loop like so:
>
> while (pc) {
> argp1 = ...pmc_reg.registers[cur_opcode[1]];
> if (*pc & KEY1_MASK) {
> key1 = ...pmc_reg.registers[cur_opcode[2]]; /* for p_k */
> argp1 = get_keyed_entry(argp1, key1, flags);
> }
> ...
> PC = (INTERP->op_func_table)[*PC & KEY_MASK]( ... );
> PC += n_keys; /* account for additonal keys in bytecode */
> }
>
> which would call add_p_p_p(argp1, argp2, argp3).
>
> "argp" points either directly to the PMC register, or for keys, into
> the bucket, where the PMC is stored in the aggregate. Of course, argp
> shouldn't move due to GC while processing one op.

This may be all fine and dandy for the prederef case but it's going to
force the opcode functions to do a lot more work working out where to
get the key from in all the other cases.

It also prevents you using the optimised _int vtable methods for keyed
access using integer keys...

Leopold Toetsch

unread,
Sep 18, 2002, 1:44:58 PM9/18/02
to Tom Hughes, perl6-i...@perl.org
Tom Hughes wrote:

> In message <3D88A41B...@toetsch.at>
> Leopold Toetsch <l...@toetsch.at> wrote:

>> while (pc) {
>> argp1 = ...pmc_reg.registers[cur_opcode[1]];
>> if (*pc & KEY1_MASK) {
>> key1 = ...pmc_reg.registers[cur_opcode[2]]; /* for p_k */
>> argp1 = get_keyed_entry(argp1, key1, flags);
>> }
>> ...
>> PC = (INTERP->op_func_table)[*PC & KEY_MASK]( ... );
>> PC += n_keys; /* account for additonal keys in bytecode */
>> }
>>
>> which would call add_p_p_p(argp1, argp2, argp3).
>>
>>"argp" points either directly to the PMC register, or for keys, into
>>the bucket, where the PMC is stored in the aggregate. Of course, argp
>>shouldn't move due to GC while processing one op.
>>
>
> This may be all fine and dandy for the prederef case but it's going to
> force the opcode functions to do a lot more work working out where to
> get the key from in all the other cases.


No, this would be the run loop for _all_ cores. So _all_ keyed access is
taken out of the vtable function and done in the run loop.


> It also prevents you using the optimised _int vtable methods for keyed
> access using integer keys...


I don't see that. Were we now have op_keyed and op_keyed_int, we could
still use this optimization by calling op_p and op_i.


> Tom

leo

0 new messages