Re: Lightning Bindings

From:

Andy Wingo

Subject:

Re: Lightning Bindings

Date:

Tue, 01 Jun 2010 21:24:11 +0200

User-agent:

Gnus/5.13 (Gnus v5.13) Emacs/23.0.92 (gnu/linux)

Greets,
On Tue 01 Jun 2010 16:55, Noah Lavine <address@hidden> writes:
>> I tend to think that Ludovic's proposal, or something like it, is the
>> most practical means to get a portable JIT compiler going; though I
>> don't really know.
>
> You may be right; although I think actually with the FFI, it would be
> just as easy to get it going in Scheme.
To an extent, yes; but there are two problems that I see.
One is the performance difference between implementing JIT compilation
in Scheme versus implementing it in C. To an extent we're able to be
somewhat wasteful in the compiler because it's all pre-computation, and
it's not necessary to load up the compiler at runtime. But having to
load a Scheme compiler at runtime for programs that don't invoke the
compiler has a space-and-time penalty. Furthermore, one would be jitting
the /compiler/ too, which is a needless timesink when you want to make
your /program/ faster.
Secondly, foreign functions are not called in tail context relative to
the VM. Tail-calling a foreign function that tail-calls a Scheme
function that tail-calls a foreign function consumes stack space. You
need architecture-specific hooks within the VM itself to be able to
tail-call a foreign function; and necessarily so, as they have different
calling conventions. As long as you're mucking about on that level, it's
almost easier to implement in C directly.
I could be wrong of course; let me know if I'm not understanding you
correctly :)
> According to the docs, right now Scheme code can access any function
> in the Guile binary - including the functions that implement the VM
> instructions.
Many VM ops are implemented inline; and especially, the ops that handle
control flow (function calls, prompts, etc).
> I think we might ultimately not want to be generating machine code for
> each procedure, because that would make it impossible to do tracing
> optimizations like current JavaScript engines (if I understand the
> proposal right)
This is true. However I think that compiling Scheme and compiling JS are
a bit different; Scheme is much more amenable to ahead-of-time
compilation, and less polymorphic. A proper inliner can catch many
"trace trees" at compile time, and function calls are typically
implemented much more efficiently than in JS (I hear SpiderMonkey has
activation records that use ~30 words!). So I would not expect trace
trees in Scheme to be as beneficial as it is in JS.
> and also because that might lead to generating a lot
> of machine code for non-bottleneck points just to get at one
> bottleneck.
Hm, I'm not sure what you mean here; can you explain?
> I don't think this is something we should try to implement
> now, but it'd be nice if the code generation infrastructure was
> flexible enough that it could be added on later.
Flexibility is very important, yes!
> Your earlier thread asked how to get native code generation for Guile
> in such a way that it didn't make Guile too big to understand. I think
> a good choice would be to *not* put code generation in the core of
> Guile.
I agree with you in the ahead-of-time case. The "languages" in the
compiler are modules that are lazily loaded; a native-code compiler
would be a module with a "language" interface, and as such would only be
loaded when the user requests native compilation (through various
means).
For the JIT case, the argument is almost convincing enough for me not to
want a JIT at all! But if it can be done minimally and cleanly in C, the
mental costs might be worth it.
> [Native compilation only via a loadable module] has two advantages -
> first, it makes core Guile small. Perhaps people who do embedded
> systems would appreciate that, or who want to embed Guile in their
> programs and care more about small code size than incredible speed.
Embedded people are a strange crowd ;) On the one hand there's my N900
with 64GB of storage, which is practically a desktop to itself. On the
other there's 12-bit microprocessors that only PicoBIT is appropriate
for. We should certainly be able to disable the jit as a compile option,
if it's implemented in C; for some people the small code-size of
bytecode is really paramount. For some people they still want speed, so
cross-compiled AOT native code is best, while omitting the native-code
compiler on the target.
For people with severe constraints, sometimes other Scheme systems will
serve them best. Chibi seems fine, for example.
Given all the constraints though, from a performance and size
perspective I'm still inclined to do a stupid-but-fast-and-small JIT in
C, and a smarter AOT compiler in Scheme. YMMV, of course :)
> When I was looking at options earlier, I thought that GCC would be the
> ideal, but it would be too hard to use their stuff. If they're willing
> to work on this, then probably that would be best.
Yeah agreed. I think we'll have to do a lot of social hacking to get
what we want, but socially and technically this would be the best
solution.
>> I would be very interested in your observations, yes :)
>
> Well, here are some thoughts on existing work that we might be able to
> reuse:
Thanks for these observations! I'll chew on them over time :)
Cheers,
Andy
--
http://wingolog.org/