Gregor N. Purdy <[EMAIL PROTECTED]> wrote:

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

> The easiest way to intercept this flow with minimal cost is to
> have the mechanism that wants to take over replace the interpreter's
> op_func_table with a block of pointers to some Parrot_hijack()
> function that conforms to the opfunc prototype. Enqueueing an
> event would set the appropriate interpreter's op_func_table to
> hijack_op_func_table.

Thinking more about this: Switching the whole op_func_table() or
ops_addr[] (for CG cores) is simpler, then e.g. replacing backward branch
ops. Only the switched core doesn't play nicely here. Having neither a
op_func_table nor an ops_addr[], it would need an explicit
CHECK_EVENTS() in the loop.

Now I have done a very similar thing some time ago:
  Subject: [RfC] a scheme for core.ops extending
  Date: Wed, 05 Feb 2003 12:28:21 +0100

On the enqueueing of an event, the op_lib is told to switch the
jump_table/ops_addr via a special op_lib->init call. (If the event check
func_table doesn't exist yet, its constructed on the fly, by filling the
check_event opcode into the func_table.

The check_event opcode now restores the func_table/ops_addr, saves the
context (generates a return continuation) and branches to the event
handler (if any) or handles the event internally. Then it executes the
same opcode again, like its done in the prederef function, which resumes
normal opcode flow.

leo


Reply via email to