> here is an idea. if we use a pure stack design but you can access the
> stack values with an index, then the index number can get large. so a
> fixed register set would allow us to limit the index to 8 bits. so the
> byte code could look something like this:
>
> 16 bit op (plenty of room for growth)
> 8 bit register index of arg 1
> 8 bit register index of arg 2
> ...
>
> next op code ...
>
> literal data support is needed (read only)
> either each op code knows how many args it has,
I like to do so, otherwise we will lose most of the performance gain.
> or we have an end marker (e.g 0xff which is never used as a register
index).
If we have to use variable arguments, I strongly recommend to add one "argc"
byte immediately following the opcode. Linear scan bytecode will be very
slow.
> the op code is stored in network endian order and the interpreter will
> always build a 16 bit int from the 2 bytes.
The 16-bit op has both endian issue and alignment issue. Most of RISC
machine can not access byte-aligned opcode, so we have to add a lot
of padding. Anyway, it will be fatter and slower than 8-bit opcode.
I prefer to using escape opcode.
> we have a simple set of load literal, push/pop (multiple) registers op
> codes.
There should be no push/pop opcodes. They are simply register moves.
> each thread has its own register set.
>
> all registers point to PMC's
>
> passing lists to/from subs is via an array ref. the data list
> is on the
> stack and the array ref is in @_ or passed by return().
>
> special registers ($_, @_, events, etc.) are indexed with a starting
> offset of 64, so general registers are 0-63.
>
> this can be mmapped in, executed with NO changes, fairly easily
> generated by the compiler front end, optimizable on or offline,
> (dis)assembler can be simply written, etc.
>
> simple to translate to TIL code by converting each op code to a call to
> the the op function itself and passing in the register indexes or even
> the PMC pointers themselves.
Agreed.
Hong