InfoQ

News

Using JRuby to generate Code for the JVM

Posted by Mirko Stocker on Mar 26, 2008 05:00 PM

Community
Java,
Ruby
Topics
Dynamic Languages ,
Language Design ,
JRuby ,
Domain Specific Languages ,
Performance & Scalability
Tags
Code Generation ,
Metaprogramming ,
JRuby ,
Language Features

Even though JRuby has approached the performance of CRuby, sometimes that's still not fast enough. Users of CRuby can use Ryan Davis' RubyInline library with built-in support for C/C++ to easily generate Ruby C extensions. Charles Nutter from JRuby has now implemented a RubyInline builder for JRuby, allowing on the fly compilation of embedded Java code.

Ryan Davis' example of a factorial calculation method written in C:

class MyTest
 inline do |builder|
 builder.c "
  long factorial_c(int max) {
 int i=max, result=1;
while (i >= 2) { result *= i--; }
return result;
}
"
 end
end

 
And the equivalent JRuby implementation from Charles:

class FastMath
 inline :Java do |builder|
  builder.package "org.jruby.test"
builder.java "
  public static long factorial_java(int max) {
 int i=max, result=1;
 while (i >= 2) { result *= i--; }
return result;
}
 "
 end
end

 A drawback of the RubyInline for JRuby variant is the requirement of a Java 6 JDK (for the compiler), which might not yet be available on all systems.

Another way to get fast executing code is to generate the JVM bytecode directly. While this might sound like overkill for normal applications, code generating tools like compilers definitely benefit from a simple bytecode generation DSL, like the one Charles Nutter blogged about some time ago. But even with a DSL to write bytecode, this isn't a task for the faint of heart. An example from Charles' blog: the generation of a method called bar that adds the lower case version of the String-argument to the passed ArrayList.

def test_class_builder
 cb = Compiler::ClassBuilder.build("MyClass", "MyClass.java") do
 [...]
method(:bar, ArrayList, String, ArrayList) do
  aload 1
invokevirtual(String, :toLowerCase, String)
aload 2
swap
  invokevirtual(ArrayList, :add, [Boolean::TYPE, Object])
aload 2
areturn
end
[...]

 
A new addition to this field, also by Charles Nutter, is a new language called Duby that implements a subset of Ruby's syntax, enriched with some type inference logic (more on this on Charles' blog) that compiles to very fast bytecode. The same method to calculate the factorial, this time written for the Duby compiler:

class Fac
 def self.fac(max)
 {max => :int, :return => :int}
  i = max
  result = 1
 while i > 1
 result *= i
 i -= 1
end
  result
 end
end

 
It's a prototype that shows the possibilities of type inference in a Ruby-like language, rather than a new language for programmers to use. It could also be used as a way for JRuby programmers to avoid having to  fall back to Java for performance-critical paths, or to implement parts of JRuby itself, similar to Squeak Smalltalk's Slang, a subset of the Smalltalk language that can be easily translated to C. Rubinius has plans to use a similar approach called Garnet (InfoQ already talked to Evan Phoenix about Cuby/Garnet).

Now, which code generation method would you use with JRuby?

No comments

Watch Thread Reply

Educational Content

Bindings, Platforms, and Innovation

This presentation focuses on the Internet and separating myth from fact, history from the future, and the mundane from the imaginative. Bob Frankston presents a vision of what could and should be.

Orchestrating Long Running Activities with JBoss / JBPM

This article explores the use of JBoss and jBPM to implement design solutions that effectively address the issue of orchestrating long running activities.

Neo4j - The Benefits of Graph Databases

This presentation covers the use of graph databases as an optimal solution for data that is difficult to fit in static tables, rapidly evolving data or data that has a lot of optional attributes.

Realistic about Risk: Software development with Real Options

This session introduces Real Options and shows how it can help in running your project. Real Options is a decision-making process that can be used to manage risk.

Communication Flexibility Using Bindings

This article discusses the use of bindings on services and references (including the instance of non-configured bindings) as the means to implement SCA communications in a Web and SOA environment.

Writing DSLs in Groovy

After a short introduction to DSLs, Scott Davis plays with the keyboard showing how to approach the creation of a DSL by typing working snippets of Groovy code that get executed.

Scaling Agile with C/ALM (Collaborative Application Lifecycle Management)

IBM Rational and InfoQ present, Scaling Agile with C/ALM, an eBook showing organizations how to become “finely tuned software delivery machines” by enabling team integration and scaling.

Concurrent Programming with Microsoft F#

Amanda Laucher presents a real life enterprise application written in F#. She shows actual code snippets, explaining design decisions and suggesting how to use some of the F# constructs.