unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
From: Noah Lavine <noah.b.lavine@gmail.com>
To: Andy Wingo <wingo@pobox.com>
Cc: guile-devel@gnu.org
Subject: Re: A Working (but Minimal) JIT
Date: Wed, 1 Dec 2010 22:58:47 -0500	[thread overview]
Message-ID: <AANLkTik4jnbqanYivaoJfwqD2u5oeiMcf1gWmF1hyqs+@mail.gmail.com> (raw)
In-Reply-To: <m3ipzfyg8w.fsf@unquote.localdomain>

Hello,

I need to apologize for some temporary insanity when I wrote that last
post. I do know a way to get JITed code working correctly with tail
calls. It's not quite as efficient as I would like, but it's decent.
We have the JITed code be a C function that returns an enum to
indicate what the VM should do next. One value means "return
normally", one means "signal error", one means "tail call". For tail
calls, the JIT-code function returns before the tail call is made, so
the stack doesn't get bigger.

About tail calls - it would be better to not even make that call, but
any way to do that that I can see would require non-portable compiler
extensions (probably inline assembler). As you say, the JIT library
knows how to make a tail call, but unfortunately it will only return
code in the form of a C function, and calling that function would push
a frame onto the stack. We could try to do tail calls with a goto, but
labels as values are a GCC extension.

I looked around a bit for a library of inline assembler that would let
us do tail calls on different C compilers and architectures, but I
didn't find one. So I suggest that I first make the JIT work in the
non-ideal way and then start work on that library :-). (I am not at
all attached to my hack if someone knows a better way, though.)

>> I've been poking around in the code, and noticed that procs.c has a
>> reference to "applicable structs".
>
> They aren't as efficient as they could be. Currently applicable structs
> are the only nonuniform case in procedure calls -- I was trying to get
> procedure calls to have no conditional branches, and they (and
> applicable smobs) are the only odd cases.
>
> I prefer the trampoline approach used by primitives, continuations,
> foreign functions, etc -- they are normal procedures, whose code is a
> stub that does the type-specific dispatch.
>
> This is also (and even more the case) what you want for native
> procedures -- a native procedure call should just be a jmp and arg
> shuffle. Objects which don't have native implementations should have a
> stub that does the right thing.

After looking at continuations and foreign functions, it looks like
they generate objcode that calls a special VM instruction which
actually implements what they do. When I think about this, I get to a
pretty weird inversion of how procedure calls currently work. I think
it's what you meant, but let me give my reasoning to be sure:

The trouble with doing it exactly like continuations and foreign
functions is that every procedure could potentially be JITed, so every
function would have to have the special VM instruction. So that leaves
three possibilities:

1. Make the regular 'call' instruction be the one that implements
JITing. But this would introduce a branch to procedure calls.
2. Add an instruction, to be put in the normal function preamble, that
decides whether or not to JIT the function that is currently
executing, and a second instruction that calls a JITed function. If
the first instruction decides to JIT, it would have to a) JIT the
current objcode and b) modify the objcode struct in use to contain
stub code that would include the second instruction, so future calls
would call the JITed code.
3. Change calls so that all procedure calls are actually calls to C
functions, presumably changing the struct that procedures live in as
well. Then JITed functions would just have their code there, and
un-JITed functions would have vm_debug_engine (or a wrapper) as their
native function.

It sounds like 2 is what you want. Is that right? (Currently I'm doing
option 1.)

Noah



  reply	other threads:[~2010-12-02  3:58 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-10-22  4:29 A Working (but Minimal) JIT Noah Lavine
2010-10-22 21:46 ` Phil
2010-10-27 21:17   ` Ludovic Courtès
2010-10-27 21:10 ` Ludovic Courtès
2010-10-27 22:53   ` Noah Lavine
2010-11-02 22:51     ` Ludovic Courtès
2010-11-20 13:37 ` Andy Wingo
2010-11-28 20:56   ` Noah Lavine
2010-11-29 21:25     ` Andy Wingo
2010-12-02  3:58       ` Noah Lavine [this message]
2010-12-06 22:06         ` Andy Wingo
2010-12-06 22:53           ` Noah Lavine
2010-11-28 20:58   ` Noah Lavine
2010-11-28 22:36     ` Ludovic Courtès
2010-11-29  7:18       ` Ken Raeburn

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/guile/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=AANLkTik4jnbqanYivaoJfwqD2u5oeiMcf1gWmF1hyqs+@mail.gmail.com \
    --to=noah.b.lavine@gmail.com \
    --cc=guile-devel@gnu.org \
    --cc=wingo@pobox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).