Dan Sugalski wrote:
> Okay, now I'm confused. I was under the impression that doing a TIL really
> required getting down 'n dirty with assembly-level jmps and jsrs, the
> alternative being the op-loop we've got now, more or less.

I think that's true if we're threading Perl functions. TIL assumes native
code, right? (Threading a VM seems pointless to me.) Threading op codes seems
a lot easier.

> Or are you thinking of having the op functions just goto the start of the
> next one on the list? I'd think you'd blow your stack reasonably soon that
> way.

GCC has the scary computed goto: goto (*addr). It can work like this:

OP1: do something ...
     goto (*pc++);

OP2: do something else ...
     goto (*pc++);

JUMP: pc = code[*pc++];
     goto (*pc++);

You build up an array of void * and pc skips around in it. The void *
has the addresses of the code labels stored in it. Works really nice and
it's unbelievably fast. (Even puts the ++ in the delay slot and pc in
a register.)

To call a Perl sub all you have to do is push the current pc and code
values on a call stack (or not if it's a tail call) and then

  code = sub[*pc++]->code;
  pc = code;
  goto (*pc++);

Opcodes can do all the environment intialization. It makes function
calls simpler and allows the optimizer to eliminate expensive things
like environment re-construction when we're calling a top-level sub.

Of course this can't be the only interpreter implementation because
it's non-portable. We can approximate the structure with a switch
statement and macros. Or if our pre-processor is really smart it should
be able to generate whatever structure is fast on a particular arch.

- Ken

Reply via email to