On 18 Sep 2015, at 05:55, Ryan Macnak <rmacnak@gmail.com> wrote:

On Tue, Sep 15, 2015 at 8:29 AM, Esteban Lorenzano <estebanlm@gmail.com> wrote:

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?

The elements of your FFIExternalArray should be in malloc's heap, not in the Smalltalk heap, so the check should pass. 

it doesn’t, that’s the point. 
also IMO that’s incorrect: if I want to read some structure in smalltalk memory who will be passed as a ByteArray (bah, a byte*) to FFI, that check will fail too… and that’s incorrect.
and since that check was removed in IA32ABIPlugin, I think this has been taken into account.

Esteban