[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Patch] Integrating Jitter as a sub-package in Poke: first iteration

From: Jose E. Marchesi
Subject: Re: [Patch] Integrating Jitter as a sub-package in Poke: first iteration
Date: Mon, 23 Sep 2019 18:52:41 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/26.1 (gnu/linux)

Hi Luca!

[Sorry for this long delay in replying, but as you know I'm travelling
 for conferences, and last week has been complicated, in many ways.]

    I am taking the liberty of also including some background which will be
    obvious to you in this response, in the hope that others will be
    On 2019-09-16 at 03:28 +0200, Jose E. Marchesi wrote:
    > Hm, so now you have routines and "executable routines" as separated
    > concepts.  You can go from the first to the second, and there is a link
    > back:
    >         routine  >>> executable routine
    >             ^               |
    >             |               |
    >             +---------------+
    Right.  The circular structure is for easy freeing; it can also makes
    data structures such as closures simpler, by letting you only include
    one pointer instead of two.
    > Something doesn't feel right here... isn't being executable (and
    > therefore not editable) a property of a routine?  If so, why not
    > exposing it as a property, instead of adding a new separated (but
    > coupled, the weird "link back") abstraction?
    Non-executable routines are good for code generation -- and they will
    support some optimization as well; for example it is easy to eliminate
    some jumps.  Non-executable routines need data structures handling, for
    example, labels.  There are dynamically growing buffers, and hash
    tables.  Moreover, rewriting happens on non-executable routines: the
    last few generated VM instructions may be transparently replaced by
    alternatives, while the user keeps generating more.  This involves a few
    complications and some memory overhead.

Allright, all that are internal details.
    Executable routines are purely for executing, and much simpler.  In
    direct-threaded code you have an array containing pointers to native
    code and residual VM instruction arguments; in no-threading an
    executable routine is even simpler: one contiguous block of executable
    memory containing hardware instructions.

    I also toy with more radical optimizations in my mind, such as using an
    obstack style of allocation for all the data structures in
    non-executable routines, to make them easy to destroy in an instant and
    more cache-friendly, and to allocate the structs for executable routines
    directly in mmapped memory.

    I decided to separate non-executable routines from executable routines
    essentially to be able to free one without the other: at execution you
    do not need non-executable routines, unless you want to debug.  The
    printing of VM code works with non-executable routines only, while
    disassembly relies on executable routines but works in a more precise
    way when the companion non-executable routine exists as well: for each
    VM instruction you get its name and precise boundaries, so that you see
    which hardware instructions implement which VM instruction.

That can be achieved by having a "strip" operation on jitter routines.
    > This way you don't need to expose two different types, and I don't need
    > to mess with that weird one-directional link from "executable routine"
    > to "routine" like in:
    > -        pvm_destroy_program (argv[i].val.prog);
    > +        {
    > +          pvm_routine rout = argv[i].val.erout->routine;
    > +          if (rout != NULL)
    > +            pvm_destroy_routine (rout);
    > +          pvm_destroy_executable_routine (argv[i].val.erout);
    > +        }
    > Having both pvm_destroy_routine and pvm_destroy_executable_routine,
    > why??  I want to destroy a routine, period.
    I believe I addressed the point above, but I am perfectly willing to add
    helper functions for your use case.

Thanks.  From the client interface perspective, I really would like to
see only one kind of Jitter routine, and being able to alter their
properties using suitable functions.
    So, to repeat the conversation on IRC of which you may have missed the
    last past:
    You want to only ever work with non-executable routines.  For this you
    would like:
    1) a way of executing a non-executable routine;
    2) a way of destroying both routines, given only the non-executable one.
    This is essentially all that you require, and it can be achieved with
    simple wrapper functions.  Apart from the ugly name I anticipate for 2)
    I see no problem.

No.  What I want is to work with just _one_ kind of jitter routine,
which starts as non-executable and becomes executable at some point.
Much like the present-day specialized vs non-specialized jitter program.
Once the routine becomes executable, you cannot edit it unless you turn
it back into a non-executable routine.  If an executable routine is
stripped, then it can't be made non-executable anymore.

I don't really care how this is implemented internally: with two
different data types, or three or four.

But I really think that the interface should offer a single routine
abstraction.  You don't want to expose things like the circular
structure: it complicates the interface for no benefit.

    I would even give you two versions of 1), one automatically making an
    executable version on the fly if none is present; and another, unsafe,
    avoiding the check.
    Would this be a satisfactory solution?
    From the point of view of the API, it should be indistinguishable from
    your proposal, with the advantage of allowing more efficient solutions
    as well.
    > I'm not sure what you mean with "the build system code selecting a
    > Jitter dispatch".  Do you mean --with-debug?
    Yes.  The Automake conditional POKE_DEBUG used in src/Makefile.am does
    what now you can do by passing options to Jitter's configure through
    Poke's configure:
      [poke]$ ./configure --enable-dispatch-no-threading
    will just work, relaying the option to jitter/configure .
    Minimal-threading and no-threading are disabled by default now.

I prefer to abstract the poke user from jitter's execution models.
Also, --enable-debug may imply more things, not just selecting a
specific jitter configuration.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]