What I'd like to know is what experts think of this... like, will it break anything, like the garbage collector?
Yes, it will. The reason is here:
anArray at: i put: (interpreterProxy positive32BitIntegerFor: element)
This can cause an allocation and things go downhill from there. You can't just store "wild values" in the array - if it gets processed by the GC it will crash (GC trying to trace the references). Even if you fix that, you'll also have to remap the array to protect from being moved by the allocation (pushRemappableOop/popRemappableOop). Finally you'll have to mark the array as root if it's old (i.e., using storePointer:ofObject:withValue:).
As you can see, doing this kind of munging with existing structures is a pain. I would recommend you do what Eliot suggested - alloca() a copy of the array and operate on that.
Cheers, - Andreas
Gerardo Richarte wrote:
Hi all, I'm working on a plugin (for SqueakNOS), and I have a primitive for which I had coded a first version, and I wanted to hear comments from people with deeper Squeak VM and plugin knowledge. I think it's ugly, but I'm more worried on whether it's dangerous or not.
some context:
There's a native function I need to call (I called it 'aPrintf' in
the code below) with a specific calling convention:
It takes only one argument: an array the first entry in the array is apointer to a C string the other elements are determined by the first element. What I want is to provide a generic interface to this aPrintf. The code below will walk the array, converting every element in the
array to either an integer (integerValueOf) or a direct pointer (firstIndexableField).
And I want to be able to read the results left in the array.
I understand that I won't be able to read non-integer elements from the array after coming back from this primitive, but that's fine. I plan to keep a copy of all non-integer elements in Smalltalk variables, including strings and other buffers.
What I'd like to know is what experts think of this... like, will it break anything, like the garbage collector? is there any other simple way of doing this?
The primitive is: primitiveaPrintf: anArray | answer length element | self primitive: 'primitiveOFWCallout' parameters: #(Array).
length := interpreterProxy slotSizeOf: anArray cPtrAsOop. answer := 0. "convert everything to native format" 0 to: length-1 do: [:i | element := anArray at: i. (interpreterProxy isIntegerObject: element) ifTrue: [anArray at: i put: (interpreterProxy
integerValueOf: element)] ifFalse: [anArray at: i put: (interpreterProxy firstIndexableField: element)] ].
self cCode: 'printf(anArray)'. "convert everything to integers. oops will be lost, but that's fine.
The client should mantain a reference" 0 to: length-1 do: [:i | element := anArray at: i. anArray at: i put: (interpreterProxy positive32BitIntegerFor: element) ].
answer = 0 ifTrue: [^ self] ifFalse: [interpreterProxy primitiveFail]. thanks a lot! richie