2. Proposal for _keyed opcodes
------------------------------

The thread with subject "pdd06_pasm, pdd08_keys: _keyed ops" clearly
showes the shortcomings of the current _keyed opcodes and the
implementation of these.[1]

My first proposal WRT a solution (modifying the run loop) did not earn
much consent and when looking closer at JIT, I have to admit, that it
seems rather impractical, or, when implemented might have bad
influence on JIT execution times.

So here is another possible solution:

The current opcode:

        set_n_p_ki

will translate into 2 opcodes:

        key_p_p_ki      [2]
        set_n_p

The 3 operand keyed add @a[$i] = @b[3] + %h{"k"}:

        add_p_ki_p_kic_p_kc

(which we don't have)

would be 4 ops

        key_p_p_ki      [3]
        key_p_p_kic
        key_p_p_kc
        add_p_p_p

So a keyed access would have a "key_" opcode, fetching a value pointer
out of the aggregate, and a plain operation working on these values.


Some thoughts on implementation
-------------------------------

The assembler respectively imcc would generate this op sequence for
the current bracketed keyed syntax. assembler.pl could reserve e.g.
P29-P31 for the usage in one key sequence, imcc does dynamic register
allocation anyway.

[2]
PerlHash stores a HASH_ENTRY (a "UnionVal", with a type), a PerlArray
uses a "PMC *" entry for its data, MultiArray uses a different UnionVal
based store.

The UnionVal allowes for a compact storage of primitive types, while a
PMC is more efficient for PMC types and a universal pointer.

As a HASH_ENTRY stores the data type of the value, it would be
possible to optimize above keyed set to:

        key_n_p_ki
        set_n_n

... with the drawback of some more opcodes. If the used types are
known at compile time, imcc could optimize Binops too, to use native
types.

For LHS usage, we need a pointer into the aggregates storage, so
we use a PMC anyway.


[3]
For LHS usage of compound keys (@a[$b][1] = ..), we might need a
special opcode, if we should autovivify the intermediate aggregate.

And finally: the stores must not move, while we are operating on the
value PMCs.


Comments welcome,
leo


[1] Current state and restrictions
----------------------------------

Looking from HL (perl6;-) down to the inyards of parrot, we have e.g.:

        $n = @a[$i];    # assuming native types

which translates to PASM:

        set N0, P0[I0]

giving an opcode:

        set_n_p_ki

which calls

        get_number_keyed_int(...)

on the perlarray PMC, returning directly the stored "num" from array.

Now we have functions returning STRING, number, int and additionally
two versions of these, one taking a KEY and the second (optimized)
version taking directly an integer array index.

Implementing e.g.

        @æ[$i] = $j + @b[$k]

would need a "add_keyed_int()" function for perlint, swapping
arguments would imply for perlarray to have such a function and so on.

Now pdd06_pasm states, that all operations might have 3 keys, so we
would end up with basically 64 times the opcodes, we have now, because
each keyed access in the 3 operands has 4 possible types of keys
(_k,_ki,_kic,_kc).


Reply via email to