Hi, there ,
i've been working last two weeks on reviewing the code in NB,
and update configuration & making tests green etc..
So, here the summary:
0. New stuff:
external structures (NBExternalStructure) now is normal objects (not
var-byte ones), and using 'data' ivar indirection like in
NBExternalArray, so you can allocate external struct on both external
heap and object memory, e.g.:
struct := MyStructClass externalNew.
or:
struct := MyStructClass new.
(so, it is similar to NBExternalArray).
- a function with signature
MyStruct * foo ()
which returns a pointer to struct, now will return an instance of
MyStruct with the address, so you can use it directly , e.g.:
struct := self callFoo.
value := struct field1.
struct field2: 10
etc..
Thanks to Ciprian for introducing the change. I just polished a bit
and fixed some mistakes.
1. NBExternalTypeValue>>address
should not exist.
You simply cannot use freely an address to object's internal field
because object can move in memory.
(the tests in
NBFFIExternalValueTests
testOutIntArg
testOutValueArg
testOutVoidArg
is changed accordingly)
2. In NBExternalEnumerationType: pushing a pointer to this type is not
allowed, since it makes no sense.
But the mistake there was to generate a code which fails primitive
with an error message,
instead of failing much much sooner - at code generation stage, since
it is already known that user specified wrong type.
3. I reverting generic pushAsPointer: to accept varbyte objects
instead of just ByteArray object.
- removing #specialPush:asPointer:endLabel:
because it will be not used (btw,
in NBExternalStructureType>>specialPush:asPointer:endLabel: , there
was same mistake that
it generates code to checking a pointer arity at runtime, while it is
already known during code generation time:
asm decorateWith: 'arity checking' during: [ |pointerArityOk|
pointerArityOk := asm uniqueLabelName: 'pointerArityOk'.
asm mov: pointerArity asImm32 to: asm EAX;
cmp: asm EAX with: 1 asImm32;
je: pointerArityOk.
gen failWithMessage: 'Arity ', pointerArity printString,' not
allowed for ', objectClass name, 'objects'.
asm label: pointerArityOk].
since pointerArity is known, the produced code will be something like:
mov: 1 to: EAX;
cmp: EAX with: 1;
je: pointerArityOk
and makes no sense, because again it can just throw the error at code
generation time.
4. Added code to capture argument names (CompiledMethod>>nbArgumentNames)
and 'NativeBoost prepareForProduction', to ensure NB can work without
source code accessible.
5. But the general expression, like in (1):
object address
gave me an interesting idea: what if we introduce a special type, say
NBObjectFieldAddress.
Consider the following problem:
imagine that you have a big array in object memory (byte array),
and you want to pass a pointer to n-th element of that array to some function.
Right now, there is no way how you can do it, and you can pass only a
pointer to array itself (which means it will always point to its first
element).
So, the idea is to introduce a special type, and special object which
represents the address-of-object's-field, so you can tell:
array := ByteArray new: 1000.
address := array nbAddressAt: 500. "create an address object which
points to 500th element of given array"
(and expression 'array nbAddress' is synonym to 'array nbAddressAt: 1').
self callSomeFunctionWith: address.
The signature of C function which takes a pointer like:
void foo (void * ptr)
then should be changed to:
void foo (NBObjectFieldAddress ptr)
the only question, which remains , shall it use strict type checking
(so you have to change the signature), or allow to use such objects
with any signatures which takes a pointer to something, e.g.
extend generic NBExternalType>>pushAsPointer: to additionally check if
incoming argument is instance of NBObjectFieldAddress class.
P.S. to try new config , load it:
Gofer new
smalltalkhubUser: 'Pharo' project: 'NativeBoost';
configuration;
load.
ConfigurationOfNativeBoost loadDevelopment. "which should load 2.2
version of it"
--
Best regards,
Igor Stasenko.