I've been playing with an "uncommitted" op version of invoke
that takes a method or sub by name like below:

invoke "foo", 0

The 0 is irrelevant to the eye, but it is a placeholder for the self-modifying
instruction. Upon call, invoke by name does:

op invoke(STR, INT)
PMC sub
if($2 == 0) {
   sub = lookup $1
   $2 = sub     # store the ref in the immediate data of the instruction
}
else {
   sub = (PMC*)$2
}
sub->vtable->invoke()
}

Basically it is just caching the lookup into the immediate data portion
of the bytecode instruction.

It isn't really anything new, this has been done before in VMs, but
the problem becomes the PMC that is stored in the bytecode is unknown
to the GC/DOD. Easy enough to fix, rather than store the PMC * itself,
simply keep a method_cache[] that the DOD can traverse, and store
only the array slot in the bytecode.

Maybe this is only syntactic sugar, I don't know.

The case is a win for loops that call the same method.

P0 = find_method "foo"     # Lookup by name
LOOP:
   invoke P0
   if something goto LOOP

becomes:

LOOP
   invoke "foo"             # Lookup by name only the 1st execution
   if something goto LOOP


There is no register usage for the method PMC.


Already, we are going to have a method_cache[] structure, so it follows
that we could allow for this shortcut simply to hide the cache for some
cases. This shortcut has the same challenges as the non-shortcut with
notifiying/invalidating PMC method references, so the same solutions apply.

The other question is: does this little trick apply to other things that do
lookups by name with constant strings?

-Melvin




Reply via email to