NAME ^

src/interpreter.c - Parrot Interpreter

DESCRIPTION ^

The interpreter API handles running the operations.

The predereferenced code chunk is pre-initialized with the opcode function pointers, addresses, or opnumbers of the prederef__ opcode. This opcode then calls the do_prederef() function, which then fills in the real function, address or op number.

Since the prederef__ opcode returns the same pc_prederef it was passed, the runops loop will re-execute the same location, which will then have the pointer to the real prederef opfunc and prederef args.

Pointer arithmetic is used to determine the index into the bytecode corresponding to the currect opcode. The bytecode and prederef arrays have the same number of elements since there is a one-to-one mapping.

Functions ^

static void prederef_args(void **pc_prederef, Interp *interpreter, opcode_t *pc, op_info_t *opinfo)

Called from do_prederef() to deal with any arguments.

pc_prederef is the current opcode.

void do_prederef(void **pc_prederef, Parrot_Interp interpreter, int type)

This is called from within the run cores to predereference the current opcode.

pc_prederef is the current opcode, and type is the run core type.

static void turn_ev_check(Parrot_Interp interpreter, int on)

Turn on or off event checking for prederefed cores.

Fills in the event_checker opcode, or restores original op in all branch locations of the opcode stream.

Note that when on is true, this is being called from the event handler thread.

static oplib_init_f get_op_lib_init(int core_op, int which, PMC *lib)

Returns an opcode's library op_lib init function.

core_op indicates whether the opcode represents a core Parrot operation.

which is the run core type.

For dynamic oplibs core_op will be 0 and lib will be a ParrotLibrary PMC.

static void load_prederef(Interp *interpreter, int which)

interpreter->op_lib = prederefed oplib.

static void init_prederef(Interp *interpreter, int which)

Initialize: load prederef func_table, file prederef.code.

static void stop_prederef(Interp *interpreter)

Restore the interpreter's op function tables to their initial state.

void exec_init_prederef(Interp *interpreter, void *prederef_arena)

interpreter->op_lib = prederefed oplib

The "normal" op_lib has a copy in the interpreter structure - but get the op_code lookup function from standard core prederef has no op_info_table

void *init_jit(Interp *interpreter, opcode_t *pc)

Initializes JIT function for the specified opcode and returns it.

void prepare_for_run(Parrot_Interp interpreter)

Prepares to run the interpreter's run core.

static opcode_t *runops_jit(Interp *interpreter, opcode_t *pc)

Runs the JIT code for the specified opcode.

static opcode_t *runops_exec(Interp *interpreter, opcode_t *pc)

Runs the native executable version of the specified opcode.

static opcode_t *runops_prederef(Interp *interpreter, opcode_t *pc)

This runops core is used when we are in prederef mode. It works just like the basic fast core, except it uses pc_prederef instead of pc, and calls prederef opfuncs instead of regular opfuncs.

There is code after the main while loop to resynchronize pc with pc_prederef in case we have exited the loop under restart conditions (such as with interpreter flag changing ops).

TODO: The calls to init_prederef() and stop_prederef() would be best placed elsewhere, since we would re-pay the costs of loading the prederef oplib every time we dropped out of and back into this core. For now, however, this implementation should do fine. Since dropping out of and back into cores is expected to be rare (at the time of implementation that only occurs for interpreter flag changing ops).

static opcode_t *runops_cgp(Interp *interpreter, opcode_t *pc)

Runs the C goto, predereferenced core.

static opcode_t *runops_switch(Interp *interpreter, opcode_t *pc)

Runs the switch core.

void runops_int(Interp *interpreter, size_t offset)

Run parrot operations of loaded code segment until an end opcode is reached run core is selected depending on the Interp_flags when a restart opcode is encountered a different core my be selected and evaluation of opcode continues.

static void setup_event_func_ptrs(Parrot_Interp interpreter)

Setup a func_table containing pointers (or addresses) of the check_event__ opcode.

TODO: Free it at destroy. Handle run-core changes.

Dynamic Loading Functions ^

void dynop_register(Parrot_Interp interpreter, PMC *lib_pmc)

Register a dynamic oplib.

static void dynop_register_xx(Parrot_Interp interpreter, PMC *lib_pmc, size_t n_old, size_t n_new, oplib_init_f init_func)

Register op_lib with other cores.

static void dynop_register_switch(Parrot_Interp interpreter, PMC *lib_pmc, size_t n_old, size_t n_new)

Description.

static void notify_func_table(Parrot_Interp interpreter, void *table, int on)

Tell the interpreter's running core about the new function table.

void disable_event_checking(Parrot_Interp interpreter)

Restore old function table.

XXX This is only implemented for the function core at present.

void enable_event_checking(Parrot_Interp interpreter)

Replace func table with one that does event checking for all opcodes.

NOTE: enable_event_checking() is called async by the event handler thread. All action done from here has to be async safe.

XXX This is only implemented for the function core at present.

SEE ALSO ^

include/parrot/interpreter.h, src/inter_cb.c, src/inter_create.c, src/inter_misc.c, src/inter_run.c.


parrot