<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
		>
<channel>
	<title>Comments on: Simple VM JIT with LLVM</title>
	<atom:link href="http://blog.fallingsnow.net/2008/05/23/simple-vm-jit-with-llvm/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.fallingsnow.net/2008/05/23/simple-vm-jit-with-llvm/</link>
	<description>life and tech stuff by Evan Phoenix</description>
	<lastBuildDate>Tue, 24 Aug 2010 02:53:22 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
	<item>
		<title>By: Kirill Kononenko</title>
		<link>http://blog.fallingsnow.net/2008/05/23/simple-vm-jit-with-llvm/#comment-16223</link>
		<dc:creator>Kirill Kononenko</dc:creator>
		<pubDate>Sat, 02 May 2009 21:16:49 +0000</pubDate>
		<guid isPermaLink="false">http://evanphx.wordpress.com/?p=46#comment-16223</guid>
		<description>Hi

Did you consider use libJIT? I am interested about your opinion, if you compare both LLVM and libJIT for your work. Because as our experiments show for ECMA-335 Microsoft Common Intermediate Language Infrastructure, Common Intermediate Runtime, and Common Intermediate Language, libJIT is both much faster, platform independent, and remarkably easier to use than LLVM (or GNU Lightning). It was one of the reason we actually started developement of libJIT. The other libraries were not suitable for our needs, when we started libJIT, to implement an advanced Just-In-Time compiler, which would run much faster than Mono Just-In-Time compiler. And as of today which we actually archieved as seen in following results in end of text.

Also LLVM is not suitable for Just-In-Time compilation at all in real projects, because of huge compilation time. Moreover, it does not support a large range of features needed to implement ECMA-335. These are just a couple of them:

* the whole spectrum of ECMA 335 for CLR types and operations

* async exception handling

* precise stack marking

* multiple custom call conventions

* fast Just-In-Time compilation

libJIT from end of 2008 runs 26% faster in PNETMARK than the commercial Mono 2.0 from August 2008, and faster 12.5% than Mono 2.2 from January 2009, and Mono 2.4 from March 2009.

You can try this:

http://code.google.com/p/libjit-linear-scan-register-allocator/

This is my research experimental branch of libJIT.

There is a tutorial with libJIT here:

http://www.gnu.org/software/dotgnu/libjit-doc/libjit.html</description>
		<content:encoded><![CDATA[<p>Hi</p>
<p>Did you consider use libJIT? I am interested about your opinion, if you compare both LLVM and libJIT for your work. Because as our experiments show for ECMA-335 Microsoft Common Intermediate Language Infrastructure, Common Intermediate Runtime, and Common Intermediate Language, libJIT is both much faster, platform independent, and remarkably easier to use than LLVM (or GNU Lightning). It was one of the reason we actually started developement of libJIT. The other libraries were not suitable for our needs, when we started libJIT, to implement an advanced Just-In-Time compiler, which would run much faster than Mono Just-In-Time compiler. And as of today which we actually archieved as seen in following results in end of text.</p>
<p>Also LLVM is not suitable for Just-In-Time compilation at all in real projects, because of huge compilation time. Moreover, it does not support a large range of features needed to implement ECMA-335. These are just a couple of them:</p>
<p>* the whole spectrum of ECMA 335 for CLR types and operations</p>
<p>* async exception handling</p>
<p>* precise stack marking</p>
<p>* multiple custom call conventions</p>
<p>* fast Just-In-Time compilation</p>
<p>libJIT from end of 2008 runs 26% faster in PNETMARK than the commercial Mono 2.0 from August 2008, and faster 12.5% than Mono 2.2 from January 2009, and Mono 2.4 from March 2009.</p>
<p>You can try this:</p>
<p><a href="http://code.google.com/p/libjit-linear-scan-register-allocator/" rel="nofollow">http://code.google.com/p/libjit-linear-scan-register-allocator/</a></p>
<p>This is my research experimental branch of libJIT.</p>
<p>There is a tutorial with libJIT here:</p>
<p><a href="http://www.gnu.org/software/dotgnu/libjit-doc/libjit.html" rel="nofollow">http://www.gnu.org/software/dotgnu/libjit-doc/libjit.html</a></p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Lin Jen-Shin (godfat 真常)</title>
		<link>http://blog.fallingsnow.net/2008/05/23/simple-vm-jit-with-llvm/#comment-11532</link>
		<dc:creator>Lin Jen-Shin (godfat 真常)</dc:creator>
		<pubDate>Fri, 31 Oct 2008 15:30:57 +0000</pubDate>
		<guid isPermaLink="false">http://evanphx.wordpress.com/?p=46#comment-11532</guid>
		<description>Greetings Evan,

I am very, very surprised that you have left a message for me.
Although I was talking about your examples and LLVM and Rubinius,
most of contents were written in Chinese. I didn&#039;t expect there
would be any reader who&#039;s first language wasn&#039;t Chinese.

So, I am very surprised and glad to see your message.
If you were interested in some content of that blog post,
I could translate some of them to English for you,
if you don&#039;t mind my poor, strange English sentence.

*

Let&#039;s get back to your examples. At first, I couldn&#039;t find a way to
compile the examples. After searching header files and llvm-config,
the examples ran fine. I was glad to reach here.

But I thought it&#039;s a bit strange that your &quot;create&quot; function which
creates JIT module, was skipping &quot;function label&quot;, lacking a switch
case to find out which function it should call this time.

By talking about &quot;function label&quot;, I mean the 0, 1, 2 in our source
program. 0 stands for set, 1 stands for add, and 2 stands for show.

Then I started to add the switch case in your create function,
thinking it should let me rewrite our source program to such as:

int program[] = {
0, 0, 5,    // res[0] = 5
2, 0,       // puts res[0]
1, 0, 0, 4, // res[0] = res[0] + 4
2, 0,       // puts res[0]
1, 1, 0, 7, // res[1] = res[0] + 7
2, 1        // puts res[1]
};

Problems occurred here.
Segmentation fault, or strange result, e.g. -2153546.

blah blah blah... time passed.

I started to think perhaps there would be a bug in your examples.
The body bytecode (or bitcode?) emitted by llvm, i.e.,

define void @body(i32* %ops, i32* %registers) {
entry:
  call void @set( i32* %ops, i32* %registers )
  %tmp3 = getelementptr i32* %ops, i32 3        ;  [#uses=1]
  call void @add( i32* %tmp3, i32* %registers )
  %tmp31 = getelementptr i32* %ops, i32 4       ;  [#uses=1]
  call void @show( i32* %tmp31, i32* %registers )
  ret void
}

I thought it&#039;s very strange that the second getelementptr told
%ops to step 4, just like &quot;ops + 4&quot; in C. Then it passed %tmp31,
i.e. &quot;ops + 4&quot; to show. Shouldn&#039;t it be &quot;ops + 3 + 4&quot; ?

Then I took out the line:

GetElementPtrInst* ptr2 = GetElementPtrInst::Create(ops, const_4, &quot;tmp3&quot;, bb);

and changed it to:

GetElementPtrInst* ptr2 = GetElementPtrInst::Create(ptr1, const_4, &quot;tmp3&quot;, bb);

save, compile, and it runs fine. Of course it&#039;s not the exactly
modification I made, because I built a loop and a switch case to
create many CallInst(s). The exactly lines were:

const_n = ConstantInt::get(APInt(32, lexical_cast&lt;std::string&gt;(step), 10));
ptr = GetElementPtrInst::Create(params.back(), const_n, &quot;tmp&quot;, bb);

You can find the source code at the bottom of previous post.
[&lt;a href=&quot;http://blogger.godfat.org/2008/10/llvm-rubinius.html&quot; rel=&quot;nofollow&quot;&gt;LLVM &amp; Rubinius&lt;/a&gt;]

Many thanks for your listening and kindness!

cheers,
Lin Jen-Shin (a.k.a. godfat 真常)

p.s. below is another copy of above message.
http://blogger.godfat.org/2008/10/llvm-rubinius-2.html</description>
		<content:encoded><![CDATA[<p>Greetings Evan,</p>
<p>I am very, very surprised that you have left a message for me.<br />
Although I was talking about your examples and LLVM and Rubinius,<br />
most of contents were written in Chinese. I didn&#8217;t expect there<br />
would be any reader who&#8217;s first language wasn&#8217;t Chinese.</p>
<p>So, I am very surprised and glad to see your message.<br />
If you were interested in some content of that blog post,<br />
I could translate some of them to English for you,<br />
if you don&#8217;t mind my poor, strange English sentence.</p>
<p>*</p>
<p>Let&#8217;s get back to your examples. At first, I couldn&#8217;t find a way to<br />
compile the examples. After searching header files and llvm-config,<br />
the examples ran fine. I was glad to reach here.</p>
<p>But I thought it&#8217;s a bit strange that your &#8220;create&#8221; function which<br />
creates JIT module, was skipping &#8220;function label&#8221;, lacking a switch<br />
case to find out which function it should call this time.</p>
<p>By talking about &#8220;function label&#8221;, I mean the 0, 1, 2 in our source<br />
program. 0 stands for set, 1 stands for add, and 2 stands for show.</p>
<p>Then I started to add the switch case in your create function,<br />
thinking it should let me rewrite our source program to such as:</p>
<p>int program[] = {<br />
0, 0, 5,    // res[0] = 5<br />
2, 0,       // puts res[0]<br />
1, 0, 0, 4, // res[0] = res[0] + 4<br />
2, 0,       // puts res[0]<br />
1, 1, 0, 7, // res[1] = res[0] + 7<br />
2, 1        // puts res[1]<br />
};</p>
<p>Problems occurred here.<br />
Segmentation fault, or strange result, e.g. -2153546.</p>
<p>blah blah blah&#8230; time passed.</p>
<p>I started to think perhaps there would be a bug in your examples.<br />
The body bytecode (or bitcode?) emitted by llvm, i.e.,</p>
<p>define void @body(i32* %ops, i32* %registers) {<br />
entry:<br />
  call void @set( i32* %ops, i32* %registers )<br />
  %tmp3 = getelementptr i32* %ops, i32 3        ;  [#uses=1]<br />
  call void @add( i32* %tmp3, i32* %registers )<br />
  %tmp31 = getelementptr i32* %ops, i32 4       ;  [#uses=1]<br />
  call void @show( i32* %tmp31, i32* %registers )<br />
  ret void<br />
}</p>
<p>I thought it&#8217;s very strange that the second getelementptr told<br />
%ops to step 4, just like &#8220;ops + 4&#8243; in C. Then it passed %tmp31,<br />
i.e. &#8220;ops + 4&#8243; to show. Shouldn&#8217;t it be &#8220;ops + 3 + 4&#8243; ?</p>
<p>Then I took out the line:</p>
<p>GetElementPtrInst* ptr2 = GetElementPtrInst::Create(ops, const_4, &#8220;tmp3&#8243;, bb);</p>
<p>and changed it to:</p>
<p>GetElementPtrInst* ptr2 = GetElementPtrInst::Create(ptr1, const_4, &#8220;tmp3&#8243;, bb);</p>
<p>save, compile, and it runs fine. Of course it&#8217;s not the exactly<br />
modification I made, because I built a loop and a switch case to<br />
create many CallInst(s). The exactly lines were:</p>
<p>const_n = ConstantInt::get(APInt(32, lexical_cast&lt;std::string&gt;(step), 10));<br />
ptr = GetElementPtrInst::Create(params.back(), const_n, &#8220;tmp&#8221;, bb);</p>
<p>You can find the source code at the bottom of previous post.<br />
[<a href="http://blogger.godfat.org/2008/10/llvm-rubinius.html" rel="nofollow">LLVM &amp; Rubinius</a>]</p>
<p>Many thanks for your listening and kindness!</p>
<p>cheers,<br />
Lin Jen-Shin (a.k.a. godfat 真常)</p>
<p>p.s. below is another copy of above message.<br />
<a href="http://blogger.godfat.org/2008/10/llvm-rubinius-2.html" rel="nofollow">http://blogger.godfat.org/2008/10/llvm-rubinius-2.html</a></p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Tom Bagby</title>
		<link>http://blog.fallingsnow.net/2008/05/23/simple-vm-jit-with-llvm/#comment-10914</link>
		<dc:creator>Tom Bagby</dc:creator>
		<pubDate>Mon, 08 Sep 2008 05:01:49 +0000</pubDate>
		<guid isPermaLink="false">http://evanphx.wordpress.com/?p=46#comment-10914</guid>
		<description>I put together Ruby LLVM bindings that make experimenting with this sort of thing faster/more fun. Certainly beats waiting for C++ build and link.  I&#039;ve blogged some examples of using the extension at http://llvmruby.org and the source lives at http://github.com/tombagby/llvmruby</description>
		<content:encoded><![CDATA[<p>I put together Ruby LLVM bindings that make experimenting with this sort of thing faster/more fun. Certainly beats waiting for C++ build and link.  I&#8217;ve blogged some examples of using the extension at <a href="http://llvmruby.org" rel="nofollow">http://llvmruby.org</a> and the source lives at <a href="http://github.com/tombagby/llvmruby" rel="nofollow">http://github.com/tombagby/llvmruby</a></p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Tomy</title>
		<link>http://blog.fallingsnow.net/2008/05/23/simple-vm-jit-with-llvm/#comment-10384</link>
		<dc:creator>Tomy</dc:creator>
		<pubDate>Mon, 09 Jun 2008 02:56:41 +0000</pubDate>
		<guid isPermaLink="false">http://evanphx.wordpress.com/?p=46#comment-10384</guid>
		<description>Evan, definitely check out what David Chisnall is doing with the Étoilé project. A unified Objective-C, Smalltalk, and Ruby runtime built on top of LLVM is pretty close to Nirvana (the state, not the band). Throw Javascript into the mix and we&#039;re pretty close to heaven.

My work on Ruby and LLVM got sidetracked when I read Ian Piumarta&#039;s papers about Cola (http://piumarta.com/software/cola/). Especially check out the minimal object model (http://piumarta.com/software/cola/). Now I&#039;m  spending my time on just enough icing on top of LLVM to build multiple dynamic object models.

How are you planning on implementing closures? Garbage collected stack frames and CPS? Also, the GC interface in LLVM is pretty sweet, you can tag roots with meta  info when you create them and have this passed to your GC at collection time.</description>
		<content:encoded><![CDATA[<p>Evan, definitely check out what David Chisnall is doing with the Étoilé project. A unified Objective-C, Smalltalk, and Ruby runtime built on top of LLVM is pretty close to Nirvana (the state, not the band). Throw Javascript into the mix and we&#8217;re pretty close to heaven.</p>
<p>My work on Ruby and LLVM got sidetracked when I read Ian Piumarta&#8217;s papers about Cola (<a href="http://piumarta.com/software/cola/" rel="nofollow">http://piumarta.com/software/cola/</a>). Especially check out the minimal object model (<a href="http://piumarta.com/software/cola/" rel="nofollow">http://piumarta.com/software/cola/</a>). Now I&#8217;m  spending my time on just enough icing on top of LLVM to build multiple dynamic object models.</p>
<p>How are you planning on implementing closures? Garbage collected stack frames and CPS? Also, the GC interface in LLVM is pretty sweet, you can tag roots with meta  info when you create them and have this passed to your GC at collection time.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: &#187; Basit bir sanal makine yonetim danışmanlığı ekonomi sermet sandıkcı</title>
		<link>http://blog.fallingsnow.net/2008/05/23/simple-vm-jit-with-llvm/#comment-10287</link>
		<dc:creator>&#187; Basit bir sanal makine yonetim danışmanlığı ekonomi sermet sandıkcı</dc:creator>
		<pubDate>Wed, 28 May 2008 20:23:36 +0000</pubDate>
		<guid isPermaLink="false">http://evanphx.wordpress.com/?p=46#comment-10287</guid>
		<description>[...] Buradan esinlenerek yazdigim basit bir sanal makine. Sanal makinenin kendisi C++ ile yazildi. Assembler&#8217;i ise python ile. [...]</description>
		<content:encoded><![CDATA[<p>[...] Buradan esinlenerek yazdigim basit bir sanal makine. Sanal makinenin kendisi C++ ile yazildi. Assembler&#8217;i ise python ile. [...]</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Top Posts &#171; WordPress.com</title>
		<link>http://blog.fallingsnow.net/2008/05/23/simple-vm-jit-with-llvm/#comment-10260</link>
		<dc:creator>Top Posts &#171; WordPress.com</dc:creator>
		<pubDate>Mon, 26 May 2008 00:03:18 +0000</pubDate>
		<guid isPermaLink="false">http://evanphx.wordpress.com/?p=46#comment-10260</guid>
		<description>[...]  Simple VM JIT with LLVM I&#8217;ve been investigating using LLVM for Rubinius, so I&#8217;ve been doing some very small scale experiments. I [...] [...]</description>
		<content:encoded><![CDATA[<p>[...]  Simple VM JIT with LLVM I&#8217;ve been investigating using LLVM for Rubinius, so I&#8217;ve been doing some very small scale experiments. I [...] [...]</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: anon</title>
		<link>http://blog.fallingsnow.net/2008/05/23/simple-vm-jit-with-llvm/#comment-10232</link>
		<dc:creator>anon</dc:creator>
		<pubDate>Sat, 24 May 2008 09:58:10 +0000</pubDate>
		<guid isPermaLink="false">http://evanphx.wordpress.com/?p=46#comment-10232</guid>
		<description>http://etoileos.com/news/archive/2008/05/12/1719/
Someone else is doing work with LLVM which will enable the use of Smalltalk as a first class citizen next to Objective C, a Smalltalk compiler that will be able to inherit Objective C classes. Maybe that work could be reused, if it ever gets done, for Ruby, as the Ruby object model is quite like the one in Smalltalk.</description>
		<content:encoded><![CDATA[<p><a href="http://etoileos.com/news/archive/2008/05/12/1719/" rel="nofollow">http://etoileos.com/news/archive/2008/05/12/1719/</a><br />
Someone else is doing work with LLVM which will enable the use of Smalltalk as a first class citizen next to Objective C, a Smalltalk compiler that will be able to inherit Objective C classes. Maybe that work could be reused, if it ever gets done, for Ruby, as the Ruby object model is quite like the one in Smalltalk.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Antony Blakey</title>
		<link>http://blog.fallingsnow.net/2008/05/23/simple-vm-jit-with-llvm/#comment-10229</link>
		<dc:creator>Antony Blakey</dc:creator>
		<pubDate>Sat, 24 May 2008 08:26:03 +0000</pubDate>
		<guid isPermaLink="false">http://evanphx.wordpress.com/?p=46#comment-10229</guid>
		<description>There are two parts to what I was doing.

1) Allowing methods to be written in C, inline. This used the clang project associated with LLVM, plus the LLVM jitter infrastructure. This would also be useful in Ruby. I published a WIP version of that work with VW but it&#039;s not useful in this forum.

2) Using LLVM as you have described, to replace the existing VW jitter and &#039;outsource&#039; most of the platform details to LLVM. Unfortunately you need to be a Cincom commercial customer to get the VM source (I am), and then there&#039;s the problem of how to distribute it. This problem contributed to me putting two of my projects on hold (the other was embedding WebKit with full GC integration). This work wasn&#039;t far enough along to produce results, although as you have seen, results can actually come very easily with LLVM.

You should post the x86 machine code generated from your exampl, because in my experience that&#039;s where the OMG kicks in because those getelementptr lines disappear.

Over the last month I have been looking to restart this work in a Ruby context, because as you&#039;ve discovered LLVM is absolutely the dogs bollocks, and it&#039;s beautifully written and architected. It really could be like standing of the shoulders of giants as far as what it could do for Ruby performance, particularly with, as I mentioned, partial specialisation keyed off something like multimethod dispatch signatures. 

One of the nice things that can be done is for nearly all of the work to be done in Ruby, rather than using C. Theoretically you can do the entire thing in LLVM + Ruby, although bootstrapping can be a curly problem.

I&#039;d love to work on this, I&#039;ve just got to get up to speed on the Rubinius architecture.</description>
		<content:encoded><![CDATA[<p>There are two parts to what I was doing.</p>
<p>1) Allowing methods to be written in C, inline. This used the clang project associated with LLVM, plus the LLVM jitter infrastructure. This would also be useful in Ruby. I published a WIP version of that work with VW but it&#8217;s not useful in this forum.</p>
<p>2) Using LLVM as you have described, to replace the existing VW jitter and &#8216;outsource&#8217; most of the platform details to LLVM. Unfortunately you need to be a Cincom commercial customer to get the VM source (I am), and then there&#8217;s the problem of how to distribute it. This problem contributed to me putting two of my projects on hold (the other was embedding WebKit with full GC integration). This work wasn&#8217;t far enough along to produce results, although as you have seen, results can actually come very easily with LLVM.</p>
<p>You should post the x86 machine code generated from your exampl, because in my experience that&#8217;s where the OMG kicks in because those getelementptr lines disappear.</p>
<p>Over the last month I have been looking to restart this work in a Ruby context, because as you&#8217;ve discovered LLVM is absolutely the dogs bollocks, and it&#8217;s beautifully written and architected. It really could be like standing of the shoulders of giants as far as what it could do for Ruby performance, particularly with, as I mentioned, partial specialisation keyed off something like multimethod dispatch signatures. </p>
<p>One of the nice things that can be done is for nearly all of the work to be done in Ruby, rather than using C. Theoretically you can do the entire thing in LLVM + Ruby, although bootstrapping can be a curly problem.</p>
<p>I&#8217;d love to work on this, I&#8217;ve just got to get up to speed on the Rubinius architecture.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: evanphx</title>
		<link>http://blog.fallingsnow.net/2008/05/23/simple-vm-jit-with-llvm/#comment-10223</link>
		<dc:creator>evanphx</dc:creator>
		<pubDate>Sat, 24 May 2008 07:12:37 +0000</pubDate>
		<guid isPermaLink="false">http://evanphx.wordpress.com/?p=46#comment-10223</guid>
		<description>Antony: Interesting! Is your work with VW available anywhere? Rubinius actually implements a MethodContext caching scheme I found described in a cincom paper on VW&#039;s  context cache.</description>
		<content:encoded><![CDATA[<p>Antony: Interesting! Is your work with VW available anywhere? Rubinius actually implements a MethodContext caching scheme I found described in a cincom paper on VW&#8217;s  context cache.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Antony Blakey</title>
		<link>http://blog.fallingsnow.net/2008/05/23/simple-vm-jit-with-llvm/#comment-10218</link>
		<dc:creator>Antony Blakey</dc:creator>
		<pubDate>Sat, 24 May 2008 02:47:44 +0000</pubDate>
		<guid isPermaLink="false">http://evanphx.wordpress.com/?p=46#comment-10218</guid>
		<description>I&#039;ve done some work on using LLVM with the VisualWorks Smalltalk VM, and I&#039;ve been looking at Rubinius with an eye to doing exactly what you are suggesting.

&quot;This doesn’t allow for inlining across things like the kind of method call that Ruby does&quot; - actually, you can if you implement partial specialisation, which I think could generate enormous wins, especially if you specialise code that dispatches to immediates. It&#039;s like a PIC, but with the code inlined at the call site rather than just caching the method lookup.</description>
		<content:encoded><![CDATA[<p>I&#8217;ve done some work on using LLVM with the VisualWorks Smalltalk VM, and I&#8217;ve been looking at Rubinius with an eye to doing exactly what you are suggesting.</p>
<p>&#8220;This doesn’t allow for inlining across things like the kind of method call that Ruby does&#8221; &#8211; actually, you can if you implement partial specialisation, which I think could generate enormous wins, especially if you specialise code that dispatches to immediates. It&#8217;s like a PIC, but with the code inlined at the call site rather than just caching the method lookup.</p>
]]></content:encoded>
	</item>
</channel>
</rss>
