<br><br><div class="gmail_quote">On Thu, Aug 6, 2009 at 10:29 AM, Igor Stasenko <span dir="ltr">&lt;<a href="mailto:siguctua@gmail.com">siguctua@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<br>
2009/8/6 Eliot Miranda &lt;<a href="mailto:eliot.miranda@gmail.com">eliot.miranda@gmail.com</a>&gt;:<br>
<div><div></div><div class="h5">&gt;<br>
&gt;<br>
&gt;<br>
&gt; 2009/8/6 Göran Krampe &lt;<a href="mailto:goran@krampe.se">goran@krampe.se</a>&gt;<br>
&gt;&gt;<br>
&gt;&gt; Hi Eliot and all!<br>
&gt;&gt;<br>
&gt;&gt; Eliot Miranda wrote:<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Hi All,<br>
&gt;&gt;&gt;    I&#39;m looking at making the Squeak FFI reentrant to support nested calls<br>
&gt;&gt;&gt; and possibly threading.  The current FFI has a couple of issues which render<br>
&gt;&gt;&gt; it non-reentrant.<br>
&gt;&gt;<br>
&gt;&gt; The tech stuff is over my head, but I do have three questions related to this:<br>
&gt;&gt;<br>
&gt;&gt; 1. What about Alien? Shouldn&#39;t we try to move towards Alien instead of current FFI? Or is that too much work at this point?<br>
&gt;<br>
&gt; I intend to merge Alien into the current FFI to allow the current FFI to marshal Aliens.  Aliens are fine for modelling external data but the Alien FFI call-out mechanism is a little too naive for general use  It works well on x86 but has issues on anything with an exotic calling convention (passes arguments in integer and/or floating-point registers).  And see the next point about callbacks.<br>

&gt;&gt;<br>
&gt;&gt; 2. Callbacks has been a sore point in Squeak for a long time. AFAIK there is a patch available on <a href="http://www.squeakgtk.org/wiki/download.html" target="_blank">www.squeakgtk.org/wiki/download.html</a>, not sure what it does or if it is the original patch from Andreas when wxSqueak was being built. wxSqueak had a patched VM I recall. Perhaps that stuff is not related.<br>

&gt;<br>
&gt; One thing that IMO is much better about Alien is the callback mechanism which allows one effectively to pass function pointers to blocks.  The current FFI&#39;s callback mechanism is weak.  It simply does a process switch away form the process calling out and requires further work in the image, e.g. a process waiting on a semaphore that is signalled by external code, to then collect information for performing the callback. So adding in the Alien callback mechanism is also something I intend to do.<br>

&gt;<br>
&gt;&gt;<br>
&gt;&gt; 3. Could we possibly ask for a status update on Cog and related activities? We are itching for news! :) Also curious about your interest in Factor and its lower bowels (definitely cool stuff going on there).<br>

&gt;<br>
&gt; The status is as follows.<br>
&gt; The Cog stack VM os being reviewed for release to the community.  We hope to have this done soon, certainly before the end of September, but we&#39;re busy and this isn&#39;t on the critical path.  Once it is released there will have to be some integration and merge activities before it is part of the standard VMs because we have effectively forked (although not a lot).<br>

&gt; The first incarnation of the Cog JIT is complete (for x86 only) and in use at Qwaq.  We are gearing up for a new server release and the Cog VM is the Vm beneath it.  The next client release will include it also.  This VM has a naive code generator (every push or pop in the bytecode results in a push or pop in machine code) but good inline cacheing.  Performance is as high as 5x the current interpreter for certain computer-language-shootout benchmarks.  The naive code generator means there is poor loop performance (1 to: n do: ... style code can be 4 times slower than VisualWorks) and the object model means there is no machine code instance creation and no machine code at:put: primitive.  But send performance is good and block activation almost as fast as VisualWorks.  In our real-world experience we were last week able to run almost three times as many Qwaq Forums clients against a QF server running on the Cog VM than we were able to above the interpreters.  So the Cog JIT is providing significant speedups in real-world use.<br>

&gt; I am (clearly) looking at FFI issues right now.  In the Autumn I intend to start work on a less naive code generator, a better object model and a faster garbage collector, the three of which should raise performance levels to VisualWorks levels, i.e. a further 2x to 3x increase over the 4x - 5x already achieved for pure Smalltalk execution.<br>

<br>
</div></div>Yes, an FFI is heavily used in Croquet (and Qwaq Forums, i suppose) to<br>
render graphics using OpenGL. So it is critical for high performance.<br>
Btw, do you plan to use JIT for generating a callout code?</blockquote><div><br></div><div>Eventually yes.  IMO this is the best way to go to get a correct and portable FFI.  ABIs like x86-64 sysV are too complicated to interpret efficiently and very complicated to implement in a low-level language.  I think the right architecture is one where the FFI compiler is written in Smalltalk and lives in the image.  When the image starts up on a different platform all the FFI callout methods have their generated code flushed.  The first time an FFI method is invoked the invocation will fail because there is no generated code.  e.g. one writes call-outys thusly:</div>
<div><br></div><div><span class="Apple-style-span" style="font-family: Times; font-size: medium; "><font color="#000000">ffiPrintString: </font><font color="#000080">aString</font><font color="#000000"> <br>        &lt;</font><font color="#008000"><b>cdecl:</b></font><font color="#000000"> char* </font><font color="#800080"><font size="0.9" face="&#39;Accuny&#39;">&#39;ffiPrintString&#39;</font></font><font color="#000000"> (char *) </font><font color="#008000"><b>error:</b></font><font color="#000000"> </font><font color="#6B6767">errorCode</font><font color="#000000">&gt; <br>
        </font><font color="#800000">^self</font><font color="#000000"> </font><font color="#000080">externalCallFailedWith:</font><font color="#000000"> </font><font color="#6B6767">errorCode</font></span></div><div><br>
</div><div>A call failing due to no code will return e.g. #&#39;need to compile code&#39; or perhaps simply #&#39;not yet linked&#39;.  externalCallFailedWith: then invokes the ABI compiler to compile the FFI spec to some sort of abstract register transfer language, looks up the function name, stores the info in the ExternalFunction which, as it is now, is the method&#39;s first literal, and retries the invocation.  The JIT then translates the RTL into actual machine code and executes it.</div>
<div><br></div><div>One may need an additional layer which is Smalltalk code that exists to coerce arguments, raising errors for arguments that can&#39;t be coerced.  e.g.</div><div><span class="Apple-style-span" style="font-family: Times; font-size: medium; "><font color="#000000">ffiPrintString: </font><font color="#000080">aString <br>
</font><font color="#000000">        </font><font color="#800000">^self</font><font color="#000000"> </font><font color="#000080">ffiPrintStringInner:</font><font color="#000000"> </font><font color="#000080">aString</font><font color="#000000"> </font><font color="#000080">asNullTerminatedCString</font><font color="#000000"> <br>
<br>ffiPrintStringInner: </font><font color="#000080">aString</font><font color="#000000"> <br>        &lt;</font><font color="#008000"><b>cdecl:</b></font><font color="#000000"> char* </font><font color="#800080"><font size="0.9" face="&#39;Accuny&#39;">&#39;ffiPrintString&#39;</font></font><font color="#000000"> (char *) </font><font color="#008000"><b>error:</b></font><font color="#000000"> </font><font color="#6B6767">errorCode</font><font color="#000000">&gt; <br>
        </font><font color="#800000">^self</font><font color="#000000"> </font><font color="#000080">externalCallFailedWith:</font><font color="#000000"> </font><font color="#6B6767">errorCode</font></span></div><div class="gmail_quote">
<br></div>This kind of approach can move much of the complexity up into Smalltalk where it can be mastered, and the system extended on the fly, leaving the lower-level VM the simpler task of generating platform-specifics.  In particular, lifting the dll/module searching machinery up into the image is a good idea.</div>
<div class="gmail_quote"><br></div><div class="gmail_quote">I also like the following idea for accessing platform-specific constants.  I implemented a prototype of this for VisualWorks but it hasn&#39;t been deployed yet.</div>
<div class="gmail_quote"><br></div><div class="gmail_quote">&quot;For example, we want to move the socket layer out of the VM almost entirely.  To do this the VI must be able to reference the correct values for defines such as O_NONBLOCK which have an annoying habit of having different values on different unix variants.  One way to do this is to have the VI spit out a C file containing a table of all the constants it needs, name to value.  This gets compiled into a dll on each platform and loaded to retrieve the relevant values.  When developing the VI will need to get hold of new values, and so new versions of the dll will need to get spat out, compiled and reloaded.  Again providing recompilation as a service would enable users to deploy across platforms for which they have no C compiler.&quot;</div>
<div class="gmail_quote"><br></div><div class="gmail_quote">My VW prototype generated a C file from a shared pool.  e.g. here&#39;s a snippet of an autogenerated socketconstants.c</div><div class="gmail_quote"><div class="gmail_quote">
<font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><b>#include &lt;sys/types.h&gt;</b></font></div><div class="gmail_quote"><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><b>#include &lt;sys/socket.h&gt;</b></font></div>
<div class="gmail_quote"><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><b>#include &lt;netinet/in.h&gt;</b></font></div><div class="gmail_quote"><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><b>#include &lt;netinet/tcp.h&gt;</b></font></div>
<div class="gmail_quote"><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><b>typedef struct {</b></font></div><div class="gmail_quote"><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><b>            char * name;</b></font></div>
<div class="gmail_quote"><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><b>            int value, flags;</b></font></div><div class="gmail_quote"><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><b>        } constantTable;</b></font></div>
<div class="gmail_quote"><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><b>constantTable constants[] = {</b></font></div><div class="gmail_quote"><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><b>{&quot;AF_DECnet&quot;, (int)</b></font></div>
<div class="gmail_quote"><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><b>#ifdef AF_DECnet</b></font></div><div class="gmail_quote"><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><b>AF_DECnet, 1},</b></font></div>
<div class="gmail_quote"><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><b>#else</b></font></div><div class="gmail_quote"><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><b>0, 0},</b></font></div>
<div class="gmail_quote"><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><b>#endif</b></font></div><div class="gmail_quote"><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><b>{&quot;AF_FILE&quot;, (int)</b></font></div>
<div class="gmail_quote"><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><b>#ifdef AF_FILE</b></font></div><div class="gmail_quote"><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><b>AF_FILE, 1},</b></font></div>
<div class="gmail_quote"><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><b>#else</b></font></div><div class="gmail_quote"><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><b>0, 0},</b></font></div>
<div class="gmail_quote"><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><b>#endif</b></font></div><div class="gmail_quote"><br></div><div class="gmail_quote">where flags indicated the size of the field amongst other things.</div>
<div class="gmail_quote"><br></div><div class="gmail_quote">These files get compiled to dlls which can be loaded and inspected by the image.  To do a portable distribution of an application one needs to deploy a dlls  for each platform.  But one only needs to compile it when the set of constants changes.  The image therefore only loads the constants dlls when it finds it is starting up on a different operating system than that it was saved upon.  So a shrink-wrap application for a specific platform need not be deployed with the constants dll.</div>
<div class="gmail_quote"><br></div><div class="gmail_quote">My VW prototype automagically generated and compiled the dll when constants were added to the shared pool.  The C compiler was invoked automatically using VW&#39;s equivalent of OSProcess.  One could imagine providing compilation-as-a-service or a central library of these constant dlls so that developers and application deployers didn&#39;t need to have the C compiler for all platforms upon which they wish to deploy.</div>
<div class="gmail_quote"><br></div><div class="gmail_quote"><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<div><div></div><div class="h5"><br>
&gt; I expect we&#39;ll be in a position to release some version of the Cog JIT to the community by Christmas.<br>
&gt; I&#39;ll be giving a guided tour of the current Cog JIT VM at SqueakFest LA on Monday.<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt; regards, Göran<br>
&gt;<br>
&gt; Best<br>
&gt; Eliot<br>
&gt;<br>
&gt;<br>
<br>
<br>
<br>
</div></div><font color="#888888">--<br>
Best regards,<br>
Igor Stasenko AKA sig.<br>
</font></blockquote></div><br>