[gambit-list] Whole-program tree-shake & trampolinefreeness by amalgamating runtime&program, possible?

Adam adam.mlmb at gmail.com
Sat Oct 19 21:01:40 EDT 2019


Dear Marc,

Yes I think you read me right that this is a "whole-program compilation"
question.

On Sun, 20 Oct 2019 at 03:40, Marc Feeley <feeley at iro.umontreal.ca> wrote:

> I’m having a hard time parsing your question… so here is my best stab…
>
> > On Oct 19, 2019, at 3:03 PM, Adam <adam.mlmb at gmail.com> wrote:
> >
> > Dear Marc,
> >
> > An interesting question came up when discussing treeshaked Gerbil static
> builds:
> >
> > One could get a C-compiled program
> >
> >  * that is optimally and maximally tree-shaked hence omitting inclusion
> in the binary of evidently unused code, and
> >
> >  * with optimal performance in the respect of having no trampoline calls
> at all,
>
>
> Note that this means it will be impossible to load dynamically loadable
> object files (.oN files) because then there would be more than one host C
> function...
>

The question is how make one single gigangic Scheme module of Gambit
runtime + user code, yes.

This is a situation where there is not one single dynamically loadable
object file in the program, right, the whole program (Gambit runeitme and
user code) is one big statically linked object file yes.

And hence the whole program has only one single host C function, and so it
will never leave that host C function, which means there will never be any
overhead of host-to-host calls, and that means higher relative program
performance than if there would have been host-to-host calls.



> Gambit has a 2-level trampoline.  There’s a “global” trampoline in the
> ___trampoline function in lib/setup.c, but also a “local” trampoline in
> each host C function.  To completely do away with the local trampoline the
> implementation of the ___JUMP macro in include/gambit.h must be changed to
> not check if the destination of the jump is the same host C function.
>

Thanks for describing. Both these (___trampoline and ___JUMP) are involved
in a host-to-host call right, which you commonly altogether call a
"trampoline". It's fine that these still are in the code, they will just be
invoked a very small number of times through the program's execution - 1,
2, small number?, not once per runtime procedure call anyhow.

>
> > if one would just append together Gambit's runtime's .scm files with
> one's program's .scm files, into one gigantic total.scm file, which has
> (declare (optimize-dead-definitions)) and is built with
> --enable-single-host .
> >
> > To take this conversation one step further, I like to ask, is this
> practically possible?
> >
> > I'd really guess it is. If so, your hints about how I can actually do
> this would be much appreciated.
>
> Approach #1:
>
> - Combine all the lib/_*.scm files together, plus your application code.
> - Note that the lib/_kernel.scm file (which is where execution starts) has
> to be tweaked so that it doesn’t call ##load-vm at the end.
> - Then compile the combined code with gsc, telling gsc that there is an
> empty runtime library to link with.
>
> This is the rough picture of what has to be done.  YMWV… there are lots of
> details to get right.
>
> Approach #2:
>
> - Wait until I get around implementing the -whole-program gsc option (it
> has been on my TODO because whole program compilation becomes much easier
> with a module system and a modular RTS)…
>

I see, thank you for letting me know it's on your TODO.

This clarification may suffice.

Your "-whole-program" will do exactly this, amalgamate all Gambit runtime
Scheme and user code Scheme and |compile-to-target| all of it as one
module, with tree shaker enabled?

If it would be a very quick thing, feel free to clarify how you "tell gsc
that there is an empty runtime library to link with", do you mean that the
code will like to link in "libgambc" so that it's most straightforward to
provide a dummy?

> My program consists of the three vanilla Gambit .scm files a.scm b.scm
> c.scm .
> >
> > I guess very roughly this will be a tweak of
> >
> > echo "(declare (optimize-dead-definitions))"  > total.scm
> > cat gambit/lib/*.scm a.scm b.scm c.scm >> total.scm
> > gsc -e '(compile-file-to-target "total.scm")' (aka gsc -c total.scm)
> > cat gambit/lib/os_*.c total.c > c_total.c
> > gcc -o mystaticexe -Igambit/include/ c_total.c
> >
> > Here especially, any more C files than gambit/lib/os_*.c needed, and
> should the Gambit runtime .c and .scm files be appended in a particular
> order if so which?
>
> Yes the order matters.  Definitions of procedures usually have to come
> before the calls to those procedures (except when the block declaration is
> used).
>

(So just copy the link order of .c files from Gambit's makefile.)


Thanks for confirming it's straightforward. Subsequent steps are try it,
and performance benchmark.

The utility for doing this would lie in smaller binary footprint and, it
would need to be tested, maybe slightly higher performance which could be
useful on lowest-end devices like an Android phone.

Thanks again,
Adam

>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.iro.umontreal.ca/pipermail/gambit-list/attachments/20191020/101e7673/attachment.htm>


More information about the Gambit-list mailing list