From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Noah Lavine Newsgroups: gmane.lisp.guile.devel Subject: Re: A Working (but Minimal) JIT Date: Wed, 1 Dec 2010 22:58:47 -0500 Message-ID: References: NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 X-Trace: dough.gmane.org 1291262344 22709 80.91.229.12 (2 Dec 2010 03:59:04 GMT) X-Complaints-To: usenet@dough.gmane.org NNTP-Posting-Date: Thu, 2 Dec 2010 03:59:04 +0000 (UTC) Cc: guile-devel@gnu.org To: Andy Wingo Original-X-From: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Thu Dec 02 04:59:00 2010 Return-path: Envelope-to: guile-devel@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1PO0Jt-00068n-HM for guile-devel@m.gmane.org; Thu, 02 Dec 2010 04:59:00 +0100 Original-Received: from localhost ([127.0.0.1]:58289 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PO0Js-0002kw-0V for guile-devel@m.gmane.org; Wed, 01 Dec 2010 22:58:56 -0500 Original-Received: from [140.186.70.92] (port=35502 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PO0Jn-0002i7-6N for guile-devel@gnu.org; Wed, 01 Dec 2010 22:58:52 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PO0Jl-0005uO-4b for guile-devel@gnu.org; Wed, 01 Dec 2010 22:58:50 -0500 Original-Received: from mail-ww0-f49.google.com ([74.125.82.49]:46264) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PO0Jk-0005ty-VJ for guile-devel@gnu.org; Wed, 01 Dec 2010 22:58:49 -0500 Original-Received: by wwb17 with SMTP id 17so844172wwb.30 for ; Wed, 01 Dec 2010 19:58:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:received:sender:received :in-reply-to:references:date:x-google-sender-auth:message-id:subject :from:to:cc:content-type; bh=VU9LqUneHiYya0y3nL7tr8pXDAfoBCgGVPsZf4YKND4=; b=yFZ6/zb3z7XIJnD2zku5WberwH4RiBeofvz+zOZG/xBvl3FeS449AFxmH129chcPoL eZB/HUaAgHwrxNtRSXjZ+0eYuCzu6sMmfuJYxi2HC2cLHYyKiAQKv+2DAidEOYUHgD+c M/+vuV7OayETp6l5jRTaVyynKZQSj01qEDUmI= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:sender:in-reply-to:references:date :x-google-sender-auth:message-id:subject:from:to:cc:content-type; b=QOVlHpk5WsSWiYsGCvwfzNZZ/7lpkVGtOLEZvC+dA88NyY8ITbTqlmXUO4zccB0W14 uDP4Th1q6dOdJ1BDYBZcw1oMZRMl/yn0KCMbcT2mnajxz+hsuikElGyO9lK91IRlFe5q Xd5kEsRTdgrSTkfpqY9TLwEIIQj6QGePR8gc4= Original-Received: by 10.216.0.7 with SMTP id 7mr8920458wea.22.1291262327605; Wed, 01 Dec 2010 19:58:47 -0800 (PST) Original-Received: by 10.216.237.34 with HTTP; Wed, 1 Dec 2010 19:58:47 -0800 (PST) In-Reply-To: X-Google-Sender-Auth: R9yx9zDJryk2i1f0BFfOOtonVgM X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2) X-BeenThere: guile-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Developers list for Guile, the GNU extensibility library" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Errors-To: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.lisp.guile.devel:11229 Archived-At: 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