最新版のJRuby 1.0.0RC2では、RubyのスクリプトをJavaのクラスへとコンパイルするようになりました。このメカニズムはJITと呼ばれていて、デフォルトで有効になっています。では、JRubyのJITは、どのような実装になっているのでしょうか。
JRubyを起動すると、コマンドラインからファイルがパースされ、構文木がつくられます。それが、Mainの221行目からrunInterpreterメソッドです。
67 public class Main {
...
221 private void runInterpreter(Ruby runtime, Reader reader, String filename) {
...
227 Node parsedScript = getParsedScript(runtime, reader, filename);
...
232 } else {
233 runtime.compileOrFallbackAndRun(parsedScript);
234 }
さらに、この構文木をJavaのクラスへと変換します。バイトコードを操作するためのライブラリとして、ASMを利用しています。
112 public final class Ruby {
...
290 public IRubyObject compileOrFallbackAndRun(Node node) {
291 try {
292 // do the compile if JIT is enabled
293 if (config.isJitEnabled() && getTraceFunction() == null) {
294 Script script = null;
295 try {
296 StandardASMCompiler compiler = new StandardASMCompiler(node);
297 NodeCompilerFactory.getCompiler(node).compile(node, compiler);
298
299 Class scriptClass = compiler.loadClass(this.getJRubyClassLoader());
300
301 script = (Script)scriptClass.newInstance();
...
307 return script.run(getCurrentContext(), getTopSelf(), IRubyObject.NULL_ARRAY, Block.NULL_BLOCK);
Hello, World.を表示するだけ簡単なRubyスクリプトをJavaのクラスへコンパイルしてみましょう。
% cat tmp.rb
puts "Hello, World!"
% jrubyc tmp.rb
% javap tmp
Compiled from "tmp.rb"
public class tmp extends java.lang.Object implements org.jruby.ast.executable.Script{
public {};
public tmp();
public static org.jruby.runtime.builtin.IRubyObject __file__(org.jruby.runtime.ThreadContext, org.jruby.runtime.builtin.IRubyObject, org.jruby.runtime.builtin.IRubyObject[], org.jruby.runtime.Block);
public org.jruby.runtime.builtin.IRubyObject run(org.jruby.runtime.ThreadContext, org.jruby.runtime.builtin.IRubyObject, org.jruby.runtime.builtin.IRubyObject[], org.jruby.runtime.Block);
public static void main(java.lang.String[]);
}
org.jruby.ast.executable.Scriptを実装するクラスが生成されていることがわかります。また、ここからわかるように、このクラスの実行にあたってはJRubyのライブラリが必要となり、単体実行できるようになるわけではありません。

コメントする