<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Talk Like A Duck: Tag rubinius</title>
    <link>http://talklikeaduck.denhaven2.com/articles/tag/rubinius</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>In Ruby, it's not the dog, it's the tricks!</description>
    <item>
      <title>Ruby Extensions vs. Smalltalk Primitives</title>
      <description>&lt;p&gt;One of the ways in which Ruby differs from Smalltalk is in how much of the implementation is buried in C, which forms a barrier for deep understanding.&lt;/p&gt;
&lt;p&gt;For the purposes of this article, I&amp;#8217;m going to use the term extension a little loosely to refer to both core library and extension code written in C.&lt;/p&gt;
&lt;p&gt;For example, in Ruby, much of the code which implements core classes like Array, is implemented by C code.  This is good for performance, but for those with a need or desire to grok the code, not so much. In contrast, Smalltalk has a large brigade of Collection classes which are written in Smalltalk.&lt;/p&gt;
&lt;p&gt;This is not to say that Smalltalk doesn&amp;#8217;t use the equivalent of extensions. Smalltalk calls them primitives.&lt;p&gt;There are some interesting differences which might be interesting for the Ruby Core team to ponder, if they haven&amp;#8217;t already.&lt;/p&gt;

&lt;h2&gt;Smalltalk primitives&lt;/h2&gt;
&lt;p&gt;In Smalltalk-80 and it&amp;#8217;s descendants, primitive methods are implemented in a low-level languages like C or Assembler. They are attached to normal Smalltalk methods by a special syntax.  For example, here&amp;#8217;s a simppet from the Smalltalk-80 Blue Book, this is a method definition for the + method in SmallInteger (Smalltalks analogue to Fixnum in Ruby:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_smalltalk "&gt;1: + addend
2:   &amp;lt;primitive: 1&amp;gt;
3:   ^ super + addend&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The Smalltalk compiler turns method code into CompiledMethod objects which contain the bytecodes implementing the smalltalk code along with other information such as where to find temporary variables.  In the case of a method such as the bytecodes would be something like:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_asm "&gt;   push self
   push addend
   send_super #+, 1  // invoke the inherited + method with 1 argument 
   return_top_of_stack&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;These are the bytecodes to implement line 3.&lt;/p&gt;
&lt;p&gt;The effect of line 2 is to mark the compiled method as being associated with a numbered primitive.  A Ruby implementation of a Smalltalk VM might have code like this.
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="constant"&gt;Module&lt;/span&gt; &lt;span class="constant"&gt;VM&lt;/span&gt;

  &lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;CompiledMethod&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;execute&lt;/span&gt;
      &lt;span class="keyword"&gt;begin&lt;/span&gt;
        &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="ident"&gt;exec_prim&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;has_prim?&lt;/span&gt;
      &lt;span class="keyword"&gt;rescue&lt;/span&gt; &lt;span class="constant"&gt;PrimitiveFailed&lt;/span&gt;
      &lt;span class="keyword"&gt;end&lt;/span&gt;
      &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="constant"&gt;VM&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;interpret&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;byte_codes&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;    &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So the idea is that, if a compiled method has an associated primitive method the VM executes it. If it succeeds then that&amp;#8217;s the end of this method invocation. If it fails then execution falls through to interpret the byte codes.&lt;/p&gt;
&lt;p&gt;In the case of the method we are considering the primitive suceeds if the argument is also a SmallInteger, and the result doesn&amp;#8217;t overflow othewise it fails.  This allows primitives to quickly handle the 80% cases, and fall back on high-level smalltalk code for the more complicated cases.&lt;/p&gt;
&lt;h2&gt;User Primitives&lt;/h2&gt;
&lt;p&gt;Later Smalltalk implementations such as Smalltalk/V and &lt;span class="caps"&gt;IBM&lt;/span&gt;/Smalltalk allowed user written primitives. These were usually referenced by namerather than a number.  The same flow allowed fallback to Smalltalk code on failure of a user primitive, either for error recovery, or for balancing implementation complexity against performance.&lt;/p&gt;
&lt;h2&gt;Ruby Extensions&lt;/h2&gt;
&lt;p&gt;In contrast, Ruby methods are either wholly normal Ruby code, or wholly extension methods written in C functions registered using ruby api calls like rb_define_method. These methods are somewhat invisible to the ruby programmer.  This can be confusing, particularly when you are trying to read code which is partially implemented in C and partially in Ruby.  Just this morning I was trying to debug somebody else&amp;#8217;s code which was using the eventmachine gem.  Looking at the source for eventmachine showed methods being invoked with no definition visible in the ruby source.  These methods actually live in a C extension to the class.  
&lt;h2&gt;Could Ruby Use Something like Smalltalk&amp;#8217;s Primitive Methods?&lt;/h2&gt;
&lt;p&gt;It might be nice if this could be made visible using a mechanism like Smalltalk&amp;#8217;s primitive not only to document such cases, but as a way to do th ekind of complexity/performance balancing I&amp;#8217;ve described.&lt;/p&gt;
&lt;p&gt;It might be interesting to think about combining this with the ideas behind &lt;a href="http://www.zenspider.com/ZSS/Products/RubyInline/"&gt;ruby-inline&lt;/a&gt;, and to allow the primitives to be written in-line as well.  The difference I would see would be the introduction of the idea of failure/recovery and better support for usage of the ruby.h api inside the inlined primitives.&lt;p&gt;
&lt;p&gt;Just a thought.&lt;/p&gt;
&lt;h2&gt;Postscript &amp;#8211; Related Technology&lt;/h2&gt;
&lt;p&gt;Although I consider the Smalltalk primitive idea as something which might be added to Ruby, Smalltalk and related languages have added more modern techniques for moving the implementation of the core up into the higher-level language.
&lt;p&gt;&lt;a href="http://www.squeak.org"&gt;Squeak smalltalk&lt;/a&gt;Uses a language called slang (not tobe confused with s-lang), as the source language for the Squeak VM.  Slang has a Smalltalk-like syntax but it is easily translated to C. Squeak user primitives are written in slang as plug-ins.&lt;/p&gt;
&lt;p&gt;Evan Phoenix&amp;#8217;, &lt;a href="http://rubini.us/"&gt;Rubinius&lt;/a&gt; started out as a Ruby VM being written in Ruby or a slang-like language with a ruby-like syntax, but it seems to have changed tack to use a handcoded port of Evan&amp;#8217;s earlier Ruby code to C.  This ported VM is called Shotgun.  Shotgun seems to be taking an &lt;a href="http://rubini.us/pages/library"&gt;approach quite similar to the original Smalltalk-80 numbered primitives&lt;/a&gt; to implement the functions of the ruby standard library. I don&amp;#8217;t beleive that they are using the primitive failure with fallback idea though.&lt;/p&gt;
&lt;p&gt;Java has the Java Native Interface (or &lt;span class="caps"&gt;JNI&lt;/span&gt;) which is similar to ruby&amp;#8217;s extensions in that it provides a c-API to the &lt;span class="caps"&gt;JVM&lt;/span&gt;.  It differs from Ruby in that Java classes must have declarations of any native functions they provide and are responsibole for loading the load library containing the binary. &lt;/p&gt;
&lt;p&gt;I must confess that it&amp;#8217;s been a few years since I stopped keeping up with Java evolution, so there may be new things in Java in this area.&lt;/p&gt; 
&lt;p&gt;An interesting historical sidenote is that the original VisualAge for Java which was written before the advent of &lt;span class="caps"&gt;JNI&lt;/span&gt; used what was called the &amp;#8220;UVM&amp;#8221; or Universal Virtual Machine.  This was a version of the &lt;span class="caps"&gt;IBM&lt;/span&gt; Smalltalk VM extended to support both Smalltalk and Java bytecodes.  The &lt;span class="caps"&gt;UVM&lt;/span&gt; used Smalltalk as the language in which Java native methods were written.  When Sun came out with the &lt;span class="caps"&gt;JNI&lt;/span&gt;, with requirements for C language primitives, VA/Java moved from a Smalltalk VM to either the Sun or &lt;span class="caps"&gt;IBM&lt;/span&gt; JVMs.
&lt;/p&gt;
&lt;p&gt;After Dave Ungar cut his teeth (and earned his PhD) working on the &lt;span class="caps"&gt;UCB&lt;/span&gt; implementation of Smalltalk-80, he took on the challenge of implementing a dynamic language completely in itself in the aptly named self language.  The philosophy behind self abhored statically optimized techniques, including prmitives written in a low-level language, in favor of dynamically optimizing code at run-time.  This was the genesis of the &lt;span class="caps"&gt;JIT&lt;/span&gt; and HotSpot approaches commonly used in Java.  It was also the basis of the Strongtalk project which saw members of Dave&amp;#8217;s self team taking some of the ideas from Self back to a Smalltalk implementation.</description>
      <pubDate>Mon, 04 Jun 2007 10:16:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:00b2fa56-26ef-458d-b4c1-1de6a7f62e8b</guid>
      <author>Rick DeNatale</author>
      <link>http://talklikeaduck.denhaven2.com/articles/2007/06/04/ruby-extensions-vs-smalltalk-primitives</link>
      <category>ruby</category>
      <category>smalltalk</category>
      <category>smalltalkideas</category>
      <category>self</category>
      <category>rubinius</category>
      <category>squeak</category>
    </item>
  </channel>
</rss>
