[erlang-patches] customized ERL_NIF_TERM type support

Sverker Eriksson sverker.eriksson@REDACTED
Thu Feb 13 17:19:44 CET 2014


As I remember, it was the convention of *returning* int vs struct{int} 
that differed (at least).
int was returned in a register while struct{int} was stored on stack and 
returning
pointer to it in register.

Maybe there is a difference between C and C++ conventions also.

The top commit on this branch was my attempt with a struct:

git fetch https://github.com/sverker/otp.git ERL_NIF_TERM_as_struct


Just did a little test myself now:

struct X {
     int b;
};

struct X bar(struct X);
int foo(int x);


int main()
{
     struct X a = {0x77};
     struct X x = bar(a);
     int y = foo(0x88);

     return x.b + y;
}

And gcc 4.6.3 uses the same calling conventions for foo and bar (arg in 
edi and return value in eax)
on my x86_64 Linux machine.

I don't remember if it was some other architecture that I saw the 
difference on.


/Sverker




On 02/13/2014 04:37 PM, Daniel Goertzen wrote:
> Hi Sverker.
>
> I want to look at the bad performance issue you observed with respect to
> passing "struct{int}" as a parameter vs just passing "int".  I wrote a tiny
> test program to observe the assembly generated by gcc and the code for the
> two cases looked identical.  Also, some research into calling conventions
> hasn't offered me any explanations yet.
>
> Do you have any details you can share that will help me understand when and
> why performance degrades?
>
> I want to understand because I am looking at a struct{int} approach as part
> of a C++ nif solution, and I am very sensitive about adding bloat.
>
> Thanks,
> Dan.
>
>
>
>
> On Fri, Feb 7, 2014 at 12:46 PM, Sverker Eriksson <
> sverker.eriksson@REDACTED> wrote:
>
>>   Thanks for the patch.
>>
>> I got one objection/question though. My C++ knowledge is a bit rusty but
>> as I understand it
>> the "enum class" construct demands that Type is an integer type.
>>
>> This is currently true for ERL_NIF_TERM but it might not be in the future.
>> I earlier tried to define ERL_NIF_TERM as
>>
>> typedef struct { int x; } ERL_NIF_TERM;
>>
>> to get stronger type checking even for C. I reverted that due to bad
>> performance
>> as gcc has different calling conventions for int and struct {int}.
>> However, future compilers
>> might be better at passing struct{int} by value in which case we might
>> want to change
>> the definition of ERL_NIF_TERM.
>>
>> What then? Do we ignore CUSTOM_NIF_TERM_TYPE in such a scenario?
>>
>>
>> /Sverker, Erlang/OTP
>>
>>
>>
>> On 02/07/2014 06:34 PM, Daniel Goertzen wrote:
>>
>> When writing NIFs in C++, it is impossible to employ C++ function
>> overloading because the underlying type of ERL_NIF_TERM is "unsigned int".
>> For example:
>>
>> // won't compile :(
>> #include <erl_nif.h>
>> void my_func(ERL_NIF_TERM a)  {...}
>> void my_func(unsigned int a)  {...}
>>
>>
>> This patch allows NIF authors to mutate the type of ERL_NIF_TERM by
>> defining the macro CUSTOM_NIF_TERM_TYPE().  In the example below, the
>> underlying unsigned integer type gets wrapped as a C++11 typed
>> enumeration.  The type of ERL_NIF_TERM is now unique and can be used in
>> overloaded functions.
>>
>> // compiles!  :)
>> #define CUSTOM_NIF_TERM_TYPE(Type) enum class ERL_NIF_TERM : Type {};
>> #include <erl_nif.h>
>> void my_func(ERL_NIF_TERM a)  {...}
>> void my_func(unsigned int a)  {...}
>>
>>
>> The patch has no impact on erl_nif.h if CUSTOM_NIF_TERM_TYPE is not defined
>> (other than flipping the definition order of ERL_NIF_TERM and ERL_NIF_UINT).
>>
>> A similar approach has been used on my C++11 NIF wrapper (https://github.com/goertzenator/nifpp).  The wrapper requires manual
>> installation of a similar patch, and I would love to remove that
>> requirement.
>>
>> Regards,
>> Dan.
>>
>>
>>
>>
>> _______________________________________________
>> erlang-patches mailing listerlang-patches@REDACTED://erlang.org/mailman/listinfo/erlang-patches
>>
>>
>>




More information about the erlang-patches mailing list