[Vm-dev] external addresses and callbacks (FFI+Alien merge)
Esteban Lorenzano
estebanlm at gmail.com
Tue Sep 15 15:29:58 UTC 2015
Hi,
I’m working on merge FFI with Alien as a way to provide a single callback mechanism (I already talked with Eliot and he agrees this is the way to go in the future).
That means review certain stuff, a couple of them I already submitted in my last commit.
Now I have this problem. This is my example method:
exampleCqsort
| cb rand values orig sort |
rand := Random new.
values := FFIExternalArray newType: 'double' size: 100.
1 to: 100 do: [ :i| values at: i put: rand next ].
orig := (1 to: 100) collect: [:i| values at: i].
cb := Callback
signature: #(int (*)(const void *, const void *))
block: [ :arg1 :arg2 | ((arg1 doubleAt: 1) - (arg2 doubleAt: 1)) sign ].
[
self primQsort: values getHandle with: 100 with: values type typeSize with: cb thunk.
sort := values asArray ]
ensure: [ values free ].
^orig -> sort
primQsort: array with: count with: size with: compare
<cdecl: void 'qsort' (void* ulong ulong void*) module: 'libc’>
^ self primitiveFailed
… that basically works. But this depends on this method in Callback:
voidstarvoidstarRetint: callbackContext sp: spAlien
<signature: #(int (*)(const void *, const void *)) abi: 'IA32'>
| value |
value := block
value: (Alien forPointer: (spAlien unsignedLongAt: 1))
value: (Alien forPointer: (spAlien unsignedLongAt: 5)).
^ callbackContext wordResult: value
And I want to remove Alien from the equation (there will still be some… and there will be the primitives of course, but I want to reduce their use at the minimum for obvious reasons: hide the extra complexity to users).
So this function would be something like this instead:
voidstarvoidstarRetint: callbackContext sp: spAlien
<signature: #(int (*)(const void *, const void *)) abi: 'IA32'>
| value |
value := block
value: (spAlien pointerAt: 1) “It will answer an ExternalAddress”
value: ((spAlien pointerAt: 5). “It will answer an ExternalAddress”
^ callbackContext wordResult: value
So… this *should* work but it doesn’t because in primitiveFFIDoubleAt: I have a call to
ffiAddressOf: rcvr startingAt: byteOffset size: byteSize
who mades this check:
"don't you dare to read from object memory!"
(addr == 0 or:[interpreterProxy isInMemory: addr])
ifTrue:[^interpreterProxy primitiveFail].
and well… since I’m calling things from a callback the #isInMemory: method fails.
If I took out that method everything works ok and since the equivalent IA32ABIPlugin does not have that check I can suppose it is ok to remove the validation.
But! Since there was that comment ("don't you dare to read from object memory!”)… I’m afraid I can be making a mistake.
What do you think?
Esteban
More information about the Vm-dev
mailing list