Okay, here the small snippet of code, which does the trick! :) Compile it with: gcc calltest.c callgate.s -o calltest Here, a fn1() and fn2() is equal functions (almost), which imitating the native code, which moved during the VM call. And fnCallGate() is a special function, which needs to be called instead of actual function, which potentially could move our code. extern void fnCallGate(void* fn, ...); it take a first argument - a function which needs to be called, and then rest of arguments (if any), which belong to that function. This gate function using another function, which returns a current value of a method oop. In terms of Squeak VM, this is a method oop, which it retrieving before calling a VM function and after calling it (interpreterProxy->primitiveMethod). So, in case if method oop is moved during GC, it will change the return address by the same offset as a difference between old method oop value and new one. And so, with this trick, a native code could safely call any VM function (through a gate function) without the risk that if native code is moved during GC, it will return to wrong address and cause a system crash. On 6 April 2010 23:49, Igor Stasenko <siguctua@gmail.com> wrote:
On 6 April 2010 14:46, Marcus Denker <marcus.denker@inria.fr> wrote:
Hi,
I always liked how Smalltalk X did it... they have
    -> an ivar in CompiledMethod that is the "native code pointer".     -> Primitive methods are just methods that have this pointer set       to the primitive in the vm.     -> Methods with embedded C-code are compiled and linked with       the Smtk->C cross-compiler, the pointer than points to that function     -> the JIT just put a pointer to the code it generates.
So they merge primitives / static compiling(+embedded c-code) *and* the JIT into one not that ugly mechanism. In STX, the memory is managed by the VM, though (the code is not allocated in the GCed object memory by the JIT).
So: Yes, I like this :-) and your mechanism is a nice way to get it easily integrated into the current system.
Q: what happens when code is moved by the GC?
Yeah, it will break the whole thing :) To avoid that, a native code should not issue any memory allocation, which may cause GC.
Perhaps, there is a way to counter this , while still being able to move the code. A primitive could set a flag that its going to call a native code, embedded into compiled method, so, then, after GC, if this flag is set, VM knows, that memory allocation is issued from native code, and should fix the return address (1) on stack, before returning to native code, which moved to the new code location:
primitive -> native code --(1)-> VM allocation procedure -> GC
(1) - a return address , which should be fixed.
-- Marcus Denker  -- http://www.marcusdenker.de INRIA Lille -- Nord Europe. Team RMoD.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Best regards, Igor Stasenko AKA sig.
-- Best regards, Igor Stasenko AKA sig.