← Back to team overview

ooc-dev team mailing list archive

Re: Member function pointers, closures, ffcall, JIT trick, more keywords, hi google search.

 

Hi again,

Looks like this issue is seldom understood by people and often
under-estimated.
In consequence I wrote a small presentation, which I hope, gives a pretty
clear explanation of the problem, and the solution I suggest.

http://ooc-lang.org/docs#design_documents

enjoy =)
Amos

2009/7/22 Amos Wenger <amoswenger@xxxxxxxxx>

> Hi everyone,
>
> Someone on #ooc-lang brought up the 'member function pointer' issue again,
> and so I have to summarize the situation here.
>
> so about member functions pointers / closures, as I see it we have 3
> alternatives now
>
>    1. use a struct with pointers to locals: no JIT, no extra memory, as
>    fast as it gets, but works only between ooc
>    2. use the JIT trick I suggested weeks ago
>    3. use ffcall:
>    http://www.haible.de/bruno/documentation/ffcall/trampoline/trampoline.html
>
>
> So here's my opinion:
>
>    - ffcall is a very fine piece of code but seemingly unnecessary since
>    we have JITs (and now's the moment you freak out and say to yourself "heck
>    he's gonne all JIT again", but no)
>    - Being non-compatible with C callback-registering fuctions seriously
>    suck
>
> So I was thinking implementing both solutions 1 and 2, and using 2 only
> when passing member function pointers/closures to C callback-registering
> functions, thus we'd have a nearly optimal case each time.
>
> About the solutions, some implementation details.
>
> Solution #1 requires 'function pointers' in ooc impl to become structs.
> This struct would be something like:
>
> struct FunctionPointer {
>   void *locals; // points to a struct containing the local variables (e.g.
> this for a member function, others for a full-blown closure)
>   void (*function)(); // points to the real function (which returns
> anything and takes anything as arguments, C doesn't care)
> };
>
> I think C++ guys call this kind of object a Functor.
> So this lightweight structure would allow a closure/membfuncpointer to be
> passed around easily in ooc code. A member function would be thought of as a
> closure with 'this' (or 'self', ie. the instance) in the locals pointer.
>
> Solution #2, I have already implemented months ago with GNU Lightning. It's
> a very lightweight AND lightning fast JIT. Best thing, it's all contained in
> a single C header file (all with macros, but done right), so it's really
> negligible overhead to an ooc application. How it works is, it creates at
> runtime a wrapper function per closure, e.g. taking no arguments, which
> calls the closure with all the right arguments.
>
> Example:
>
> class Window {
>
>   String title;
>
>   func display {
>     printf("Displaying window %s\n", this.title);
>   }
>
>   func new {
>     glutDisplayFunc(this.@display); // reminder: the '@' is necessary or
> display would be called.
>   }
>
> }
>
> Currently generates the following C (as pseudocode to leave out the
> details):
>
> void Window_display(struct Window* this) {
>   printf("Displaying window %s\n", this->title);
> }
>
> struct Window* Window_new() {
>   glutDisplayFunc(this->display); // apparently don't need an '&' in modern
> C
> }
>
> But it will crash in Window_display since 'this' will be a dangling pointer
> (e.g. glut doesn't pass any arguments to the function).
> So now the plan is to generate code like:
>
> void Window_display(struct Window* this) {
>   printf("Displaying window %s\n", this->title);
> }
>
> struct Window* Window_new() {
>   glutDisplayFunc(wrap_memberfunc(this->display, this));
> }
>
> Where wrap_memberfunc would return a freshly allocated function looking
> like (if it was disassembled and decompiled to C):
>
> void Window_display_wrapper() {
>   struct Window* this = 0x9108ff; // whatever was the address of this
>   Window_display(this); // simplified example, a real-life virtual function
> would be called with this->display(this);
> }
>
> I hope you now all understand the issue, and the solutions I suggest. I
> also hope you understand why a (very very small) JIT is needed for a very
> specific part of the code and for compatibility with C.
>
> Let me know your thoughts,
> Amos
>

Follow ups

References