This is quite an interesting idea about dynamic recompiling and caching of method lookups. And it smells like more MOPS and generally just a faster Parrot VM. So I've hacked together an initial version for testing, only MMD lookups currently.
PMC MOPS (examples/benchmarks/mops.pasm)
parrot -C CVS 13.6 parrot -j 13.4 parrot -C PIC 16.7
This is a 22% speedup for MOPS and very likely more for method lookups. With JIT_CGP the JIT core could also use this optimization. (Numbers with -O3 build, AMD 800)
Below is a (very) preliminary pod generated from src/pic.c.
Before spending more time on that, I'd like to hear some comments about possible hidden drawbacks or whatever. I can provide a patch too.
Thanks, leo
[1] http://citeseer.ist.psu.edu/hlzle91optimizing.html
PIC.C(1) User Contributed Perl Documentation PIC.C(1) NNNNAAAAMMMMEEEE src/pic.c - Polymorphic Inline Cache DDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN The PIC supports inline caching for MMD and object method lookups in the CGP (direct threaded run core). · During predereferencing the bytecode, Parrot_PIC_prederef() is called. If it's a MMD function, the prederefed code pointer is replaced with a stub that caches MMD lookups. For callmethod opcodes another stub is created that caches classes or does a method lookup. · This stub inside pic_cgp_core checks the PMC types. If a match with the cache is found the MMD function is called directly. If no match is found the MMD function is looked up, and function pointer and types are stored in the cache. · For objects, the cache holds entries per class/method_name. TODO - create a circular LRU buffer for a few types. - cache all MMD functions - cache method lookups - provide an API to invalidate the cache per class or all. FFFFuuuunnnnccccttttiiiioooonnnnssss static opcode_t *pic_cgp_core(opcode_t *cur_op, Interp*) This has the same signature and usage as the cgp_core. Actually this function is just used to return the address of the CGoto jump table. The code is executed by just jumping inside the labels (from and to the CGP core). static void pic_create_mmd(Interp *, opcode_t *pc, void **pc_pred, INTVAL func_nr) Create a PIC structure for the given MMD func_nr. The *pc is the plain bytecode pointer, pc_pred points into the prederefed code. The first argument of the opcode gets the pic structure, which has as slot first_arg, where this argument is preserved. A typical opcode with a PIC looks like: [opcode] [pic] [left] [right] 20/Nov/2004 perl 5.008 1 PIC.C(1) User Contributed Perl Documentation PIC.C(1) The [dest] argument is in the PIC struture. void Parrot_PIC_prederef(Interp *, opcode_t *pc, void **pc_pred) Define either the normal prederef function or the PIC stub, if PIC for this opcode function is available. Called from do_prederef. AAAAUUUUTTTTHHHHOOOORRRR Leopold Toetsch with many hints from Ken Fox. SSSSEEEEEEEE AAAALLLLSSSSOOOO _s_r_c_/_m_m_d_._c, _s_r_c_/_o_b_j_e_c_t_._c, _s_r_c_/_i_n_t_e_r_p_r_e_t_e_r_._c, _o_p_s_/_c_o_r_e___o_p_s___c_g_p_._c 20/Nov/2004 perl 5.008 2