On Tue, Jul 1, 2008 at 1:34 PM, tim Rowledge <tim@rowledge.org> wrote:

On 1-Jul-08, at 1:20 PM, Eliot Miranda wrote:

One doesn't have to *use* the FFI.   If the FFI isn't exposed via a primitive then no FFI.  One can still have named primitives supported by the image and not by the VM and not use the FFI.  To call a named primitive in a primitive plugin the following sequence occurs:

the method containing a named primitive spec is activated and the primitive call fails because its function pointer is null.
the failure code extracts the plugin name and invokes a primitive to load the plugin library
the failure code extracts the primitive name and uses the lookup primitive to find the function in the loaded plugin library
the failure code uses a primitive to slam the function pointer into the method
the failure code uses the executeMethodWithArgs primitive to retry the bound named primitive method

So the FFI is an optional extra.  One needs four primitives, load library, lookup name in library, insert primitive function pointer. and executemethodWithArgs (thanks Tim!).  Slamming the function into the method could also be done using, say, objectAt:.

So one can still have a nice small safe VM and have no direct support for named primitives in the VM.

Leaving aside my like of all-named-prims, I *like* this enhancement to the support for named prims.

It would slightly complicate the post-prim-call code in each method because you would need to handle the failed-to-find-prim case as well as all the prim-failed cases. It would be helped by an old idea that I'm pretty sure eliot has plans for anyway (as indeed I have written about a few times) to add primitive error return values. For those that haven't heard of them, this is just a way of having the first temp in a context involved in a prim call be a slot for a return value from the prim if any error occurs. This means you can actually know wtf went wrong instead of guessing - "ooh, was the first arg a SmallInteger? Um, if not, was it a Float that might round nicley? Err, was the second arg a ByteArray with the first byte = 255?" etc. Instead you get "ah, errorValue was 1, so we have to explode the reactor core in order to stop the Dreen from eating the children". Much nicer.

I did primitive error codes at Cadence and they'll very probably b making it into Cog real soon now.  They're simpler than VisualWorks', being only symbols.  So extracting more information, such as a related error code requires a subsequent call.  But I think the work I'm doing right now on eliminating pushRemappableOop:/popRemappableOop will enable me to have a structured object with a name and parameters, which is more generally useful.

A nice thing is that the code is forwards and backewards compatible.  One can use the VM to run older images.  One can run images that contain the primitive error code on older VMs, where one simply gets a nil error code on primitive failure.