GithubHelp home page GithubHelp logo

rubyomr-preview / ruby Goto Github PK

View Code? Open in Web Editor NEW

This project forked from ruby/ruby

67.0 10.0 9.0 135.32 MB

The Ruby+OMR Preview

License: Other

Ruby 57.54% Makefile 0.78% C 38.67% Perl 0.08% Python 0.01% Scheme 0.01% Perl 6 0.01% HTML 0.07% C++ 1.27% Shell 0.03% Assembly 0.01% CSS 0.05% JavaScript 0.06% Emacs Lisp 0.40% Yacc 0.85% XSLT 0.05% Scilab 0.01% ApacheConf 0.01% Batchfile 0.03% GDB 0.10%
ruby jit compiler

ruby's Introduction

Ruby+OMR

This branch contains a modified version of the Ruby VM that has been altered to interact with the Eclipse OMR compiler technolgy in order to add a Just-In-Time compiler to Ruby.

To read more about this project and its future, please see the following blog posts that introduce the tecnhnology and discuss its future.

Status:

As of today, this branch has only been tested on Linux x86-64. When run with

OMR_JIT_OPTIONS='-Xjit:count=0' 

Which attempts to compile methods before invoking them even once, in some sense a stress test mode, the current status is make test passes, however, make test-all fails.

Building Ruby + OMR

Simplified steps to build Ruby + OMR. See more detailed instructions below to modify the install location, etc.

$ git clone https://github.com/rubyomr-preview/ruby.git --branch ruby_2_4_omr --recursive 
$ cd ruby
$ autoconf
$ ./configure SPEC=<specname> --with-omr-jit
$ make
$ make install

Since the Ruby + OMR code has only been tested on Linux x86-64, Linux PPC-LE-64, Linux PPC-BE-64 and Linux 390-64 the acceptable values for <specname> are:

1. linux_x86-64
2. linux_ppc-64_le_gcc
3. linux_ppc-64
4. linux_390-64

Running with the JIT compiler

The ruby interpreter takes a new command like option -J to pass JIT options.

Use the environment variable OMR_JIT_OPTIONS to pass options;

Some options of interest:

option Description
count=N. How many times a method needs to be invoked before it is compiled.
verbose Outputs compilation decisions to stdout
vlog=file Redirect compilation decision output to file
tracefull,log=file Produce a compilation log at file, suffixed with PID

Running without installing

If you haven't run make install, the dynamic loader will complain. Tell it where to find librbjit by pointing LD_LIBRARY_PATH to this directory.

So, running make test without installing:

LD_LIBRARY_PATH=$PWD OMR_JIT_OPTIONS=count=0 make test

What's Ruby

Ruby is the interpreted scripting language for quick and easy object-oriented programming. It has many features to process text files and to do system management tasks (as in Perl). It is simple, straight-forward, and extensible.

Features of Ruby

  • Simple Syntax
  • Normal Object-oriented Features (e.g. class, method calls)
  • Advanced Object-oriented Features (e.g. Mix-in, Singleton-method)
  • Operator Overloading
  • Exception Handling
  • Iterators and Closures
  • Garbage Collection
  • Dynamic Loading of Object Files (on some architectures)
  • Highly Portable (works on many Unix-like/POSIX compatible platforms as well as Windows, Mac OS X, Haiku, etc.) cf. https://bugs.ruby-lang.org/projects/ruby-trunk/wiki/SupportedPlatforms

How to get Ruby

For a complete list of ways to install Ruby, including using third-party tools like rvm, see:

https://www.ruby-lang.org/en/downloads/

The Ruby distribution files can be found on the following FTP site:

ftp://ftp.ruby-lang.org/pub/ruby/

The trunk of the Ruby source tree can be checked out with the following command:

$ svn co https://svn.ruby-lang.org/repos/ruby/trunk/ ruby

Or if you are using git then use the following command:

$ git clone git://github.com/ruby/ruby.git

There are some other branches under development. Try the following command to see the list of branches:

$ svn ls https://svn.ruby-lang.org/repos/ruby/branches/

Or if you are using git then use the following command:

$ git ls-remote git://github.com/ruby/ruby.git

Ruby home page

The URL of the Ruby home page is:

https://www.ruby-lang.org/

Mailing list

There is a mailing list to talk about Ruby. To subscribe to this list, please send the following phrase:

subscribe

in the mail body (not subject) to the address mailto:[email protected].

How to compile and install

This is what you need to do to compile and install Ruby:

  1. If you want to use Microsoft Visual C++ to compile ruby, read win32/README.win32 instead of this document.

  2. If ./configure does not exist or is older than configure.in, run autoconf to (re)generate configure.

  3. Run ./configure, which will generate config.h and Makefile.

    Some C compiler flags may be added by default depending on your environment. Specify optflags=.. and warnflags=.. as necessary to override them.

  4. Edit defines.h if you need. Usually this step will not be needed.

  5. Remove comment mark(#) before the module names from ext/Setup (or add module names if not present), if you want to link modules statically.

    If you don't want to compile non static extension modules (probably on architectures which do not allow dynamic loading), remove comment mark from the line "#option nodynamic" in ext/Setup.

    Usually this step will not be needed.

  6. Run make.

  7. Optionally, run 'make check' to check whether the compiled Ruby interpreter works well. If you see the message "check succeeded", your ruby works as it should (hopefully).

  8. Run 'make install'

    This command will create the following directories and install files into them.

    • ${DESTDIR}${prefix}/bin
    • ${DESTDIR}${prefix}/include/ruby-${MAJOR}.${MINOR}.${TEENY}
    • ${DESTDIR}${prefix}/include/ruby-${MAJOR}.${MINOR}.${TEENY}/${PLATFORM}
    • ${DESTDIR}${prefix}/lib
    • ${DESTDIR}${prefix}/lib/ruby
    • ${DESTDIR}${prefix}/lib/ruby/${MAJOR}.${MINOR}.${TEENY}
    • ${DESTDIR}${prefix}/lib/ruby/${MAJOR}.${MINOR}.${TEENY}/${PLATFORM}
    • ${DESTDIR}${prefix}/lib/ruby/site_ruby
    • ${DESTDIR}${prefix}/lib/ruby/site_ruby/${MAJOR}.${MINOR}.${TEENY}
    • ${DESTDIR}${prefix}/lib/ruby/site_ruby/${MAJOR}.${MINOR}.${TEENY}/${PLATFORM}
    • ${DESTDIR}${prefix}/lib/ruby/vendor_ruby
    • ${DESTDIR}${prefix}/lib/ruby/vendor_ruby/${MAJOR}.${MINOR}.${TEENY}
    • ${DESTDIR}${prefix}/lib/ruby/vendor_ruby/${MAJOR}.${MINOR}.${TEENY}/${PLATFORM}
    • ${DESTDIR}${prefix}/lib/ruby/gems/${MAJOR}.${MINOR}.${TEENY}
    • ${DESTDIR}${prefix}/share/man/man1
    • ${DESTDIR}${prefix}/share/ri/${MAJOR}.${MINOR}.${TEENY}/system

    If Ruby's API version is 'x.y.z', the ${MAJOR} is 'x', the ${MINOR} is 'y', and the ${TEENY} is 'z'.

    NOTE: teeny of the API version may be different from one of Ruby's program version

    You may have to be a super user to install ruby.

If you fail to compile ruby, please send the detailed error report with the error log and machine/OS type, to help others.

Some extension libraries may not get compiled because of lack of necessary external libraries and/or headers, then you will need to run 'make distclean-ext' to remove old configuration after installing them in such case.

Copying

See the file COPYING.

Feedback

Questions about the Ruby language can be asked on the Ruby-Talk mailing list (https://www.ruby-lang.org/en/community/mailing-lists) or on websites like (https://stackoverflow.com).

Bug reports should be filed at https://bugs.ruby-lang.org. Read HowToReport for more information.

##Contributing

See the file CONTRIBUTING.md

The Author

Ruby was originally designed and developed by Yukihiro Matsumoto (Matz) in 1995.

mailto:[email protected]

ruby's People

Contributors

akr avatar authornari avatar ayumin avatar drbrain avatar duerst avatar eban avatar haileys avatar hsbt avatar k-tsj avatar knu avatar ko1 avatar kou avatar mame avatar marcandre avatar matzbot avatar mrkn avatar nagachika avatar nobu avatar nurse avatar rhenium avatar shugo avatar shyouhei avatar sorah avatar suketa avatar tarui avatar tenderlove avatar unak avatar yugui avatar znz avatar zzak avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ruby's Issues

Recompile code @ Warm

With the option -JenableRubyTieredCompilation we will recompile methods. However, it appears we recompile at the same default opt level.

Programatically compile a RubyVM::InstructionSequence

A script like this:

#!/usr/bin/ruby

puts RubyVM::InstructionSequence.compile_file(ARGV[0]).disasm

is able to dump all the bytecodes of functions defined in a file:

== catch table
| catch type: redo   st: 0002 ed: 0029 sp: 0000 cont: 0002
| catch type: next   st: 0002 ed: 0029 sp: 0000 cont: 0029
|------------------------------------------------------------------------
local table (size: 3, argc: 2 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1])
[ 3] k<Arg>     [ 2] v<Arg>     
0000 trace            256                                             (  64)
0002 trace            1
0004 putnil           
0005 getlocal_OP__WC__1 8
0007 getlocal_OP__WC__0 3
0009 getinstancevariable :@build_context, <is:0>
0012 opt_send_without_block <callinfo!mid:entities, argc:0, ARGS_SIMPLE>, <callcache>
0015 getlocal_OP__WC__0 3
0017 opt_aref         <callinfo!mid:[], argc:1, ARGS_SIMPLE>, <callcache>
0020 opt_send_without_block <callinfo!mid:value, argc:0, ARGS_SIMPLE>, <callcache>
0023 setn             3
0025 opt_aset         <callinfo!mid:[]=, argc:2, ARGS_SIMPLE>, <callcache>
0028 pop              
0029 trace            512
0031 leave            

It would be nice for problem determination purposes if we were able to also trigger compiles of all the bytecodes in a file (though, this would be devoid of profile information, so passes dependent on it such as inlining would be blind)

IMO, the way to do this would involve a couple of steps:

  • Create RubyVM::InstructionSequence#children that would use the same sort of logic as iseqw_disasm to return an array of all the child iseqs reachable from a given InstructionSequence.
  • Create RubyVM::JIT::compile_iseq that takes an iseq as the argument.

Proper On Stack Replacement

Currently we manage JIT to Interperter transitions by restoring all interpreter state. We do this because JIT frames exist on the C-stack, along side interpreter frames, which is a problem when Ruby's exception handling story is implemented partially through setjmp and longjmp

To improve performance, it would be nice if the JIT only had to restore interpreter state when it absolutely had to. In order to do this, we need to implement proper on-stack replacement and connect it together with the exception handling system.

Before longjmping past a JIT frame, it needs to be given an opportunity to restore state it may have privatized, or we need to get the JIT frames off of the regular C call stack, and manage them ourselves.

bundler tries to trap SIGABRT

Anything that runs through bundle exec fails with the following error ArgumentError: can't trap reserved signal: SIGABRT

As seen in here bundler considers only SEGV BUS ILL FPE VTALRM KILL STOP as reserved signals and then it traps all the signlas except those.

Additionaly, when I added ABRT to reserved signals it still continued to fail with the same error until I also added IOT to the same list. Only then it passed only to fail on nokogiri, but that is a thing for another issue

why is SIGABRT reserved in ruby-omr but not reserved in original ruby?

Unexpected object allocation

#
# test_AREF_fstring_key.rb  
# 
def assert_equal expected, actual, msg=""
   if expected == actual  
      puts caller_locations[0] 
   else 
      puts "error! #{caller_locations[0]}" 
      puts "#{expected} != #{actual}" 
      raise "error"
   end

end


def test_AREF_fstring_key
  h = {"abc" => 1}
  before = GC.stat(:total_allocated_objects)
  5.times{ h["abc"] }
  assert_equal before, GC.stat(:total_allocated_objects)
end

test_AREF_fstring_key
$ OMR_JIT_OPTIONS=-Xjit:count=0 LD_LIBRARY_PATH=$PWD ./ruby --disable-gems test_AREF_fstring_key.rb 
error! test_AREF_fstring_key.rb:17:in `test_AREF_fstring_key'
7313 != 7314
test_AREF_fstring_key.rb:7:in `assert_equal': error (RuntimeError)
	from test_AREF_fstring_key.rb:17:in `test_AREF_fstring_key'
	from test_AREF_fstring_key.rb:20:in `<main>'
$ ruby --disable-gems test_AREF_fstring_key.rb 
test_AREF_fstring_key.rb:17:in `test_AREF_fstring_key'

Restart work on the Ruby Inliner

We've got the bones of an inliner for Ruby, however, it's currently disabled because it needs updates for Ruby 2.4

I've got some of that work put together already.

Unsafe Ruby Code

What I'd love is to be able to write ruby implementations of core ruby methods, that can be used to replace C calls for the purposes of inlining.

One way would be to provide an 'unsafe' module similar to sun.misc.unsafe in Java, in order to allow the JIT compiler to generate high quality code for these functions.

Fiddle may provide a good base for this.

me->def != NULL, but not dereferenceable (@warm)

I'm seeing intermittent crashes in a number of scenarios when running with optLevel=warm regarding the method entry definition being non-null, but also not dereferenceable. The stack traces are always something like this:

/home/magaudet/.rbenv/versions/ruby_2_4_omr/bin/ruby(rb_vm_bugreport+0x53e) [0x55aa84ab19ce] vm_dump.c:685
/home/magaudet/.rbenv/versions/ruby_2_4_omr/bin/ruby(rb_bug_context+0xd1) [0x55aa84aa69d1] error.c:426
/home/magaudet/.rbenv/versions/ruby_2_4_omr/bin/ruby(sigsegv+0x3e) [0x55aa8499cffe] signal.c:907
/lib/x86_64-linux-gnu/libpthread.so.0 [0x7fc2d9f263d0]
/home/magaudet/.rbenv/versions/ruby_2_4_omr/lib/librbjit.so(TR_InlinerBase::checkInlineableWithoutInitialCalleeSymbol(TR_CallSite*, TR::Compilation*)+0x36d) [0x7fc2d82f66b5] /home/magaudet/open/ruby_Inliner/rbjitglue/ruby/optimizer/RubyInliner.cpp:260
/home/magaudet/.rbenv/versions/ruby_2_4_omr/lib/librbjit.so(TR_InlinerBase::getSymbolAndFindInlineTargets(TR_CallStack*, TR_CallSite*, bool)+0x2c8) [0x7fc2d832bcfc] /home/magaudet/open/ruby_Inliner/omr/compiler/optimizer/Inliner.cpp:3824
/home/magaudet/.rbenv/versions/ruby_2_4_omr/lib/librbjit.so(TR_DumbInliner::analyzeCallSite(TR_CallStack*, TR::TreeTop*, TR::Node*, TR::Node*)+0x11d) [0x7fc2d83210ad] /home/magaudet/open/ruby_Inliner/omr/compiler/optimizer/Inliner.cpp:1287
/home/magaudet/.rbenv/versions/ruby_2_4_omr/lib/librbjit.so(TR_DumbInliner::inlineCallTargets(TR::ResolvedMethodSymbol*, TR_CallStack*, TR_InnerPreexistenceInfo*)+0x551) [0x7fc2d8320df3] /home/magaudet/open/ruby_Inliner/omr/compiler/optimizer/Inliner.cpp:1249
/home/magaudet/.rbenv/versions/ruby_2_4_omr/lib/librbjit.so(TR_InlinerBase::performInlining(TR::ResolvedMethodSymbol*)+0xe4) [0x7fc2d831d8e0] /home/magaudet/open/ruby_Inliner/omr/compiler/optimizer/Inliner.cpp:419
/home/magaudet/.rbenv/versions/ruby_2_4_omr/lib/librbjit.so(Ruby::TrivialInliner::perform()+0x10f) [0x7fc2d82f7245] /home/magaudet/open/ruby_Inliner/rbjitglue/ruby/optimizer/RubyTrivialInliner.cpp:48
/home/magaudet/.rbenv/versions/ruby_2_4_omr/lib/librbjit.so(OMR::Optimizer::performOptimization(OptimizationStrategy const*, int, int, int)+0x2a2d) [0x7fc2d839244d] /home/magaudet/open/ruby_Inliner/omr/compiler/optimizer/OMROptimizer.cpp:2007
/home/magaudet/.rbenv/versions/ruby_2_4_omr/lib/librbjit.so(OMR::Optimizer::optimize()+0x88b) [0x7fc2d838f14d] /home/magaudet/open/ruby_Inliner/omr/compiler/optimizer/OMROptimizer.cpp:1106
/home/magaudet/.rbenv/versions/ruby_2_4_omr/lib/librbjit.so(OMR::Compilation::performOptimizations()+0x139) [0x7fc2d81f99ab] /home/magaudet/open/ruby_Inliner/omr/compiler/compile/OMRCompilation.cpp:1093
/home/magaudet/.rbenv/versions/ruby_2_4_omr/lib/librbjit.so(OMR::Compilation::compile()+0x92b) [0x7fc2d81f92bd] /home/magaudet/open/ruby_Inliner/omr/compiler/compile/OMRCompilation.cpp:882
/home/magaudet/.rbenv/versions/ruby_2_4_omr/lib/librbjit.so(compileMethodFromDetails(OMR_VMThread*, TR::IlGeneratorMethodDetails&, TR_Hotness, int&)+0x618) [0x7fc2d8185776] /home/magaudet/open/ruby_Inliner/omr/compiler/control/CompileMethod.cpp:340
/home/magaudet/.rbenv/versions/ruby_2_4_omr/lib/librbjit.so(compileMethod(OMR_VMThread*, TR_ResolvedMethod&, TR_Hotness, int&)+0x59) [0x7fc2d8185113] /home/magaudet/open/ruby_Inliner/omr/compiler/control/CompileMethod.cpp:235
/home/magaudet/.rbenv/versions/ruby_2_4_omr/lib/librbjit.so(compileRubyISeq(rb_iseq_struct*, char const*, TR_Hotness)+0x7a) [0x7fc2d81881fa] /home/magaudet/open/ruby_Inliner/rbjitglue/ruby/control/RubyJit.cpp:281
/home/magaudet/.rbenv/versions/ruby_2_4_omr/lib/librbjit.so(jit_compile+0x3f8) [0x7fc2d8188652] /home/magaudet/open/ruby_Inliner/rbjitglue/ruby/control/RubyJit.cpp:386
/home/magaudet/.rbenv/versions/ruby_2_4_omr/bin/ruby(vm_jit.isra.101+0x2d) [0x55aa84a07aed] vm_insnhelper.c:2851
/home/magaudet/.rbenv/versions/ruby_2_4_omr/bin/ruby(vm_exec+0x85e) [0x55aa84a18dfe] vm.c:1729
/home/magaudet/.rbenv/versions/ruby_2_4_omr/bin/ruby(vm_send_without_block+0x8e) [0x55aa84a1aeae] vm_insnhelper.c:2971
[0x7fc2cf8faa78]/home/magaudet/.rbenv/versions/ruby_2_4_omr/bin/ruby(rb_vm_bugreport+0x53e) [0x55aa84ab19ce] vm_dump.c:685
/home/magaudet/.rbenv/versions/ruby_2_4_omr/bin/ruby(rb_bug_context+0xd1) [0x55aa84aa69d1] error.c:426
/home/magaudet/.rbenv/versions/ruby_2_4_omr/bin/ruby(sigsegv+0x3e) [0x55aa8499cffe] signal.c:907
/lib/x86_64-linux-gnu/libpthread.so.0 [0x7fc2d9f263d0]
/home/magaudet/.rbenv/versions/ruby_2_4_omr/lib/librbjit.so(TR_InlinerBase::checkInlineableWithoutInitialCalleeSymbol(TR_CallSite*, TR::Compilation*)+0x36d) [0x7fc2d82f66b5] /home/magaudet/open/ruby_Inliner/rbjitglue/ruby/optimizer/RubyInliner.cpp:260
/home/magaudet/.rbenv/versions/ruby_2_4_omr/lib/librbjit.so(TR_InlinerBase::getSymbolAndFindInlineTargets(TR_CallStack*, TR_CallSite*, bool)+0x2c8) [0x7fc2d832bcfc] /home/magaudet/open/ruby_Inliner/omr/compiler/optimizer/Inliner.cpp:3824
/home/magaudet/.rbenv/versions/ruby_2_4_omr/lib/librbjit.so(TR_DumbInliner::analyzeCallSite(TR_CallStack*, TR::TreeTop*, TR::Node*, TR::Node*)+0x11d) [0x7fc2d83210ad] /home/magaudet/open/ruby_Inliner/omr/compiler/optimizer/Inliner.cpp:1287
/home/magaudet/.rbenv/versions/ruby_2_4_omr/lib/librbjit.so(TR_DumbInliner::inlineCallTargets(TR::ResolvedMethodSymbol*, TR_CallStack*, TR_InnerPreexistenceInfo*)+0x551) [0x7fc2d8320df3] /home/magaudet/open/ruby_Inliner/omr/compiler/optimizer/Inliner.cpp:1249
/home/magaudet/.rbenv/versions/ruby_2_4_omr/lib/librbjit.so(TR_InlinerBase::performInlining(TR::ResolvedMethodSymbol*)+0xe4) [0x7fc2d831d8e0] /home/magaudet/open/ruby_Inliner/omr/compiler/optimizer/Inliner.cpp:419
/home/magaudet/.rbenv/versions/ruby_2_4_omr/lib/librbjit.so(Ruby::TrivialInliner::perform()+0x10f) [0x7fc2d82f7245] /home/magaudet/open/ruby_Inliner/rbjitglue/ruby/optimizer/RubyTrivialInliner.cpp:48
/home/magaudet/.rbenv/versions/ruby_2_4_omr/lib/librbjit.so(OMR::Optimizer::performOptimization(OptimizationStrategy const*, int, int, int)+0x2a2d) [0x7fc2d839244d] /home/magaudet/open/ruby_Inliner/omr/compiler/optimizer/OMROptimizer.cpp:2007
/home/magaudet/.rbenv/versions/ruby_2_4_omr/lib/librbjit.so(OMR::Optimizer::optimize()+0x88b) [0x7fc2d838f14d] /home/magaudet/open/ruby_Inliner/omr/compiler/optimizer/OMROptimizer.cpp:1106
/home/magaudet/.rbenv/versions/ruby_2_4_omr/lib/librbjit.so(OMR::Compilation::performOptimizations()+0x139) [0x7fc2d81f99ab] /home/magaudet/open/ruby_Inliner/omr/compiler/compile/OMRCompilation.cpp:1093
/home/magaudet/.rbenv/versions/ruby_2_4_omr/lib/librbjit.so(OMR::Compilation::compile()+0x92b) [0x7fc2d81f92bd] /home/magaudet/open/ruby_Inliner/omr/compiler/compile/OMRCompilation.cpp:882
/home/magaudet/.rbenv/versions/ruby_2_4_omr/lib/librbjit.so(compileMethodFromDetails(OMR_VMThread*, TR::IlGeneratorMethodDetails&, TR_Hotness, int&)+0x618) [0x7fc2d8185776] /home/magaudet/open/ruby_Inliner/omr/compiler/control/CompileMethod.cpp:340
/home/magaudet/.rbenv/versions/ruby_2_4_omr/lib/librbjit.so(compileMethod(OMR_VMThread*, TR_ResolvedMethod&, TR_Hotness, int&)+0x59) [0x7fc2d8185113] /home/magaudet/open/ruby_Inliner/omr/compiler/control/CompileMethod.cpp:235
/home/magaudet/.rbenv/versions/ruby_2_4_omr/lib/librbjit.so(compileRubyISeq(rb_iseq_struct*, char const*, TR_Hotness)+0x7a) [0x7fc2d81881fa] /home/magaudet/open/ruby_Inliner/rbjitglue/ruby/control/RubyJit.cpp:281
/home/magaudet/.rbenv/versions/ruby_2_4_omr/lib/librbjit.so(jit_compile+0x3f8) [0x7fc2d8188652] /home/magaudet/open/ruby_Inliner/rbjitglue/ruby/control/RubyJit.cpp:386
/home/magaudet/.rbenv/versions/ruby_2_4_omr/bin/ruby(vm_jit.isra.101+0x2d) [0x55aa84a07aed] vm_insnhelper.c:2851
/home/magaudet/.rbenv/versions/ruby_2_4_omr/bin/ruby(vm_exec+0x85e) [0x55aa84a18dfe] vm.c:1729
/home/magaudet/.rbenv/versions/ruby_2_4_omr/bin/ruby(vm_send_without_block+0x8e) [0x55aa84a1aeae] vm_insnhelper.c:2971
[0x7fc2cf8faa78]

We are peeking inside the call cache at this point, to see if we can't find ourselves an inlinable target.

The rough outline of the code is something like this:

   CALL_CACHE cc = <load call cache>;
   const rb_callable_method_entry_t *me = cc->me;
   if(!me)
      {
      // abort 
      }

   if (!me->def)
      {
      // abort 
      }

   switch (METHOD_ENTRY_VISI(cc->me))
      {
      case METHOD_VISI_PUBLIC:
         break; // OK for inlining.
      case METHOD_VISI_PRIVATE:
         if (ci->flag & VM_CALL_FCALL)
            break; // Ok for inlining
      default:
         //abort 
      }

   switch(me->def->type) // Crashes here de-referencing me->def 
      {
      // ...
      }

So it seems there's something missing here.

One thing I'm considering is that I'm attempting to inline a collected method -- and so really, what I've been inspecting is garbage.

Implement smarter compilation control

Today the JIT uses invocation counts to decide when to compile a method. This can be a problem where a method consists of a long-running loop -- it would be beneficial to compile this early, but the counts will wait a long time.

There are other approaches for compilation control. One that might be worth considering is stack sampling.

function 'vm_opt_call_c_function_jit' should not return a value

The callback bodies in vm_jit.inc are automatically generated by VmJitBodyGenerator in tool/instruction.rb

Unfortunately, that generator doesn't handle exceptions. A previous pass has attempted to map THROW_EXCEPTION to assert(0); However, that line is commented out and I don't recall why at the moment.

Probably just should stop emitting callbacks with impossible semantics.

Rework Ruby Calls to look more like OMR calls.

Today, a Ruby call looks like this in trees:

n102n     astorei  sp[#614  sp +8] [flags 0x607 0x200 ]                                    
n101n       aloadi  cfp[#613  cfp +48] [flags 0x607 0x200 ]                                
n100n         aload  <parm 0 Lrb_thread_t;>[#611  Parm] [flags 0x40010107 0x0 ]            
n99n        aladd                                                                          
n98n          aload  <temp slot 2>[#623  Auto] [flags 0x7 0x0 ]                            
n97n          lconst 16                                                                    
n104n     lstorei  stackSlot[#627  stackSlot +8] [flags 0x604 0x200 ]                      
n103n       aload  <temp slot 2>[#623  Auto] [flags 0x7 0x0 ]                              
n61n        ==>lcall
n105n     lstorei  stackSlot[#628  stackSlot] [flags 0x604 0x200 ]                         
n103n       ==>aload
n23n        ==>lloadi
n113n     astorei  pc[#615  pc] [flags 0x607 0x200 ]                                       
n112n       aloadi  cfp[#613  cfp +48] [flags 0x607 0x200 ]                                
n111n         aload  <parm 0 Lrb_thread_t;>[#611  Parm] [flags 0x40010107 0x0 ]            
n110n       aconst 0x55ec92d80eb8                                                          
n287n     treetop                                                                          
n286n       lstore  <temp slot 3>[#629  Auto] [flags 0x4 0x0 ]                             
n23n          ==>lloadi
n114n     treetop                                                                          
n109n       lcall  vm_send_without_block[#286  helper Method] [flags 0x400 0x0 ] ()        
n108n         aload  <parm 0 Lrb_thread_t;>[#611  Parm] [flags 0x40010107 0x0 ]            
n107n         aconst 0x55ec92d7fe40                                                        
n106n         aconst 0x55ec92d810b0                                                        
n23n          ==>lloadi

There's a lot going on there!

  1. Rematerialization of the stack pointer to the appropriate height (n102n)
  2. Rematerialization of the YARV stack (n104n, n105n)
  3. Rematerialization of the program counter (n113n)
  4. Call out to the vm_send_without_block helper.

That's a lot of trees for a single bytecode:

0022: 30 opt_send_without_block      puts (mid:15329) <argc:1 flag:0x14 (VM_CALL_FCALL|VM_CALL_ARGS_SIMPLE|0x0)>, E:94474564276400

A lot of the OMR compiler machinery would be a lot happier if calls looked more like how they do in other languages (hypothetically like):

acall mid:15329 puts 
  aload <temp slot 2>

I'm not sure how hard this would be, nor what the right way to go about this would be. An initial thought would be to keep code-generation looking similar, but to have high-level calls until a (mandatory opt) lowering pass.

MemorySegment crash compiling lib/rexml/parsers/treeparser.rb:17:parse

Thread 1 "ruby" received signal SIGSEGV, Segmentation fault.
0x00007ffff64be07c in TR::MemorySegment::remaining (this=0x0) at /home/magaudet/open/ruby_24/omr/compiler/env/MemorySegment.hpp:76
76	      return _size - _allocated;
(gdb) where
#0  0x00007ffff64be07c in TR::MemorySegment::remaining (this=0x0) at /home/magaudet/open/ruby_24/omr/compiler/env/MemorySegment.hpp:76
#1  0x00007ffff64bde94 in TR::Region::allocate (this=0x7fffffff7700, size=0, hint=0x0) at /home/magaudet/open/ruby_24/omr/compiler/env/Region.cpp:61
#2  0x00007ffff6457d22 in TR_Memory::allocateHeapMemory (this=0x7fffffff74e0, requestedSize=0, ot=TR_MemoryBase::Array) at /home/magaudet/open/ruby_24/omr/compiler/env/TRMemory.cpp:333
#3  0x00007ffff6457ff2 in TR_Memory::allocateMemory (this=0x7fffffff74e0, size=0, kind=(unknown: 0), ot=TR_MemoryBase::Array) at /home/magaudet/open/ruby_24/omr/compiler/env/TRMemory.cpp:379
#4  0x00007ffff642726e in TR_Array<TR::Node*>::copy (this=0x7fffffff7e60, other=...) at /home/magaudet/open/ruby_24/omr/compiler/infra/Array.hpp:216
#5  0x00007ffff642711b in TR_Array<TR::Node*>::operator= (this=0x7fffffff7e60, other=...) at /home/magaudet/open/ruby_24/omr/compiler/infra/Array.hpp:85
#6  0x00007ffff64270cd in TR_Stack<TR::Node*>::operator= (this=0x7fffffff7e60, other=...) at /home/magaudet/open/ruby_24/omr/compiler/infra/Stack.hpp:34
#7  0x00007ffff6427024 in TR_ByteCodeIteratorWithState<unsigned long, 93ul, TR_RubyByteCodeIterator, TR::Node*>::setupBBStartContext (this=0x555556292218, index=650)
    at /home/magaudet/open/ruby_24/omr/compiler/ilgen/ByteCodeIteratorWithState.hpp:249
#8  0x00007ffff64330b3 in TR_ByteCodeIteratorWithState<unsigned long, 93ul, TR_RubyByteCodeIterator, TR::Node*>::findNextByteCodeToGen (this=0x555556292218)
    at /home/magaudet/open/ruby_24/omr/compiler/ilgen/ByteCodeIteratorWithState.hpp:274
#9  0x00007ffff642f8cb in RubyIlGenerator::getinlinecache (this=0x555556292210, offset=4, ic=0x555556009750) at /home/magaudet/open/ruby_24/rbjitglue/ruby/ilgen/RubyIlGenerator.cpp:2194
#10 0x00007ffff642bd29 in RubyIlGenerator::indexedWalker (this=0x555556292210, startIndex=0, firstIndex=@0x7fffffff7d98: 0, lastIndex=@0x7fffffff7d94: 783)
    at /home/magaudet/open/ruby_24/rbjitglue/ruby/ilgen/RubyIlGenerator.cpp:915
#11 0x00007ffff6429a18 in RubyIlGenerator::walker (this=0x555556292210) at /home/magaudet/open/ruby_24/rbjitglue/ruby/ilgen/RubyIlGenerator.cpp:705
#12 0x00007ffff64298f8 in RubyIlGenerator::genILInternal (this=0x555556292210) at /home/magaudet/open/ruby_24/rbjitglue/ruby/ilgen/RubyIlGenerator.cpp:668
#13 0x00007ffff6427fbf in RubyIlGenerator::genIL (this=0x555556292210) at /home/magaudet/open/ruby_24/rbjitglue/ruby/ilgen/RubyIlGenerator.cpp:198
#14 0x00007ffff644bd13 in OMR::ResolvedMethodSymbol::genIL (this=0x5555562752e0, fe=0x7ffff6b47720 <jitInit(rb_vm_struct*, char*)::fe>, comp=0x7fffffffa140, symRefTab=0x7fffffff9880, customRequest=...)
    at /home/magaudet/open/ruby_24/omr/compiler/il/symbol/OMRResolvedMethodSymbol.cpp:1215
#15 0x00007ffff64ad26d in OMR::Compilation::compile (this=0x7fffffffa140) at /home/magaudet/open/ruby_24/omr/compiler/compile/OMRCompilation.cpp:828
#16 0x00007ffff643b22c in compileMethodFromDetails (omrVMThread=0x0, details=..., hotness=cold, rc=@0x7fffffffb98c: 1) at /home/magaudet/open/ruby_24/omr/compiler/control/CompileMethod.cpp:328
#17 0x00007ffff643abc9 in compileMethod (omrVMThread=0x0, compilee=..., hotness=cold, rc=@0x7fffffffb98c: 1) at /home/magaudet/open/ruby_24/omr/compiler/control/CompileMethod.cpp:227
#18 0x00007ffff643dbd5 in compileRubyISeq (iseq=0x555555e36780, name=0x5555561894f0 "/home/magaudet/open/ruby_24/lib/rexml/parsers/treeparser.rb:17:parse", optLevel=cold)
    at /home/magaudet/open/ruby_24/rbjitglue/ruby/control/RubyJit.cpp:281
#19 0x00007ffff643e02d in jit_compile (iseq=0x555555e36780) at /home/magaudet/open/ruby_24/rbjitglue/ruby/control/RubyJit.cpp:386
#20 0x00005555556d138d in vm_jit_compile (iseq=0x555555e36780, vm=<optimized out>) at vm_insnhelper.c:2848

Reproduction:

OMR_JIT_OPTIONS='-Xjit:count=0,limit={/home/magaudet/open/ruby_24/lib/rexml/parsers/treeparser.rb:17:parse}' LD_LIBRARY_PATH=$PWD ./miniruby -I./lib -I. -I.ext/common ./tool/runruby.rb --extout=.ext -- --disable-gems "./test/runner.rb" --ruby="./miniruby -I./lib -I. -I.ext/common ./tool/runruby.rb --extout=.ext -- --disable-gems" test/rexml

no superclass method in REXML tests @ warm

94462bf

magaudet@ubuntu1604VM:~/open/ruby_Inliner (detached*)*$ OMR_JIT_OPTIONS=count=3,optLevel=warm LD_LIBRARY_PATH=$PWD make test-all TESTS=test/rexml
<snip>
Run options: "--ruby=./miniruby -I./lib -I. -I.ext/common  ./tool/runruby.rb --extout=.ext  -- --disable-gems" --excludes-dir=./test/excludes --name=!/memory_leak/

# Running tests:

[361/425] REXMLTests::Tester#test_element = 0.03 s                                                                                                                
  1) Error:
REXMLTests::Tester#test_element:
NoMethodError: super: no superclass method `parent=' for "1) He's a great guy!":REXML::Text
    /home/magaudet/open/ruby_Inliner/lib/rexml/text.rb:125:in `parent='
    /home/magaudet/open/ruby_Inliner/lib/rexml/parent.rb:142:in `replace_child'
    /home/magaudet/open/ruby_Inliner/lib/rexml/child.rb:30:in `replace_with'
    /home/magaudet/open/ruby_Inliner/lib/rexml/element.rb:506:in `text='
    /home/magaudet/open/ruby_Inliner/test/rexml/test_core.rb:519:in `test_element'

[365/425] REXMLTests::Tester#test_empty_doc = 0.00 s           
  2) Error:
REXMLTests::Tester#test_empty_doc:
NoMethodError: super: no superclass method `encoding_updated' for #<REXML::IOSource:0x0055a90e427340>

<snip>

Build Break

ruby_2_4_omr_preliminary won't build after 9729ad8

Only noticed this because my dirty work tree preserved rbjitglue/ruby/Makefile

Can fix this by moving ruby.mk to Makefile in that dir. Will submit PR in a bit :)

Intermittent failure in TestException#test_stackoverflow

So far, I've seen hangs, and segfaults occurring in TestException#test_stackoverflow running 94462bf with

LD_LIBRARY_PATH=$PWD OMR_JIT_OPTIONS=count=0 make test-all TESTS=test/ruby/test_exception.rb

In the hang case, I attached with GDB, and found SDR spewed out more than my termincal could take: Here's a snippet:

c:9844 p:0015 s:39426 E:001650 METHOD J /home/magaudet/open/ruby_Inliner/test/ruby/test_exception.rb:570 [FINISH]
c:9843 p:0015 s:39422 E:0015f0 METHOD J /home/magaudet/open/ruby_Inliner/test/ruby/test_exception.rb:570 [FINISH]
c:9842 p:0015 s:39418 E:001590 METHOD J /home/magaudet/open/ruby_Inliner/test/ruby/test_exception.rb:570 [FINISH]
c:9841 p:0015 s:39414 E:001530 METHOD J /home/magaudet/open/ruby_Inliner/test/ruby/test_exception.rb:570 [FINISH]
c:9840 p:0015 s:39410 E:0014d0 METHOD J /home/magaudet/open/ruby_Inliner/test/ruby/test_exception.rb:570 [FINISH]
c:9839 p:0015 s:39406 E:001470 METHOD J /home/magaudet/open/ruby_Inliner/test/ruby/test_exception.rb:570 [FINISH]

In the segfault case, the core file isn't providing a lot of information. ruby_current_thread is null, and the IP looks bogus.

Put ilgen trace under a trace option

While useful when things are going wrong, a trace log riddled with

        [48] writing pending to stack slot 0 (N = 0x55bfd99dae18)
Rematerializing SP, adding 1
RubyIlGenerator:: Generating bytecode 51 opt_gt into block 0x55bfd99c5890. Stack height is 2
RubyIlGenerator:: Generating bytecode 54 branchunless into block 0x55bfd99c5890. Stack height is 1

where you don't want it is frustrating ;) Should be under a more specific trace option just like traceInlining.

Optionally emit a warning when code cache is full

When running a large suite of tests, I always have a small pit in my stomach about half way through:

At this point, are we still testing the JITted code, or have we filled up the code cache, and are just bypassing compiles?

It would be nice to optionally emit a warning when methods stop getting compiled due to code-cache saturation.

lib/rss/parser.rb:163:parse being compiled causes a failure

magaudet@ubuntu1604VM:~/open/ruby_24 (ruby_2_4_omr_preliminary_contribution)*$ OMR_JIT_OPTIONS='-Xjit:count=0,limit={*parser.rb:163:parse*}' LD_LIBRARY_PATH=$PWD ./miniruby -I./lib -I. -I.ext/common  ./tool/runruby.rb --extout=.ext  -- --disable-gems "./test/runner.rb" --ruby="./miniruby -I./lib -I. -I.ext/common  ./tool/runruby.rb --extout=.ext  -- --disable-gems" --excludes-dir=./test/excludes test/rss
Run options: "--ruby=./miniruby -I./lib -I. -I.ext/common  ./tool/runruby.rb --extout=.ext  -- --disable-gems" --excludes-dir=./test/excludes

# Running tests:

[ 22/305] RSS::TestAtomCore#test_to_xml = 0.01 s                       
  1) Error:
RSS::TestAtomCore#test_to_xml:
LocalJumpError: no block given
    /home/magaudet/open/ruby_24/lib/rss/parser.rb:80:in `parse'
    /home/magaudet/open/ruby_24/test/rss/test_atom.rb:220:in `test_to_xml'

<further failures snipped> 
/home/magaudet/open/ruby_24/test/lib/minitest/unit.rb:934: [BUG] vm_call_cfunc - cfp consistency error
ruby 2.4.0dev (2016-11-17 ruby_2_4_omr_p.. 56821) [x86_64-linux]

-- Control frame information -----------------------------------------------
c:0019 p:---- s:0108 e:000107 CFUNC  - :map
c:0018 p:0129 s:0104 e:000103 METHOD - /home/magaudet/open/ruby_24/test/lib/minitest/unit.rb:934
c:0017 p:0054 s:0092 e:000091 METHOD - /home/magaudet/open/ruby_24/test/lib/test/unit.rb:914
c:0016 p:0016 s:0085 e:000083 BLOCK  - /home/magaudet/open/ruby_24/test/lib/test/unit.rb:494 [FINISH]
c:0015 p:---- s:0079 e:000078 CFUNC  - :each
c:0014 p:0073 s:0075 e:000074 METHOD - /home/magaudet/open/ruby_24/test/lib/test/unit.rb:492
c:0013 p:0014 s:0068 e:000067 METHOD - /home/magaudet/open/ruby_24/test/lib/test/unit.rb:530
c:0012 p:0144 s:0061 e:000060 METHOD - /home/magaudet/open/ruby_24/test/lib/minitest/unit.rb:885
c:0011 p:0010 s:0050 e:000049 METHOD - /home/magaudet/open/ruby_24/test/lib/minitest/unit.rb:1096
c:0010 p:0010 s:0046 e:000045 BLOCK  - /home/magaudet/open/ruby_24/test/lib/minitest/unit.rb:1083 [FINISH]
c:0009 p:---- s:0042 e:000041 CFUNC  - :each
c:0008 p:0057 s:0038 e:000037 METHOD - /home/magaudet/open/ruby_24/test/lib/minitest/unit.rb:1082
c:0007 p:0020 s:0033 e:000032 METHOD - /home/magaudet/open/ruby_24/test/lib/minitest/unit.rb:1070
c:0006 p:0012 s:0028 e:000027 METHOD - /home/magaudet/open/ruby_24/test/lib/test/unit.rb:682
c:0005 p:0022 s:0022 e:000021 METHOD - /home/magaudet/open/ruby_24/test/lib/test/unit.rb:33
c:0004 p:0045 s:0017 e:000016 METHOD - /home/magaudet/open/ruby_24/test/lib/test/unit.rb:991
c:0003 p:0015 s:0013 e:000012 METHOD - /home/magaudet/open/ruby_24/test/lib/test/unit.rb:995
c:0002 p:0304 s:0008 E:001d38 EVAL   - ./test/runner.rb:40 [FINISH]
c:0001 p:0000 s:0003 E:000d40 (none) - [FINISH]

Implement missing YARV bytecodes

Currently, a number of YARV bytecodes remain unimplemented in the Ruby JIT.

The list (as of dd6dae0) is:

  • getclassvariable
  • setclassvariable
  • putiseq
  • freezestring
  • reverse (see below)
  • checkkeyword
  • defineclass
  • opt_str_freeze
  • opt_newarray_max
  • opt_newarray_min
  • branchnil
  • getinlinecache
  • setinlinecache
  • once
  • opt_case_dispatch
  • opt_call_c_function
  • bitblt

Hook up preliminary Travis testing

This repo needs travis testing for the ruby_2_4_preliminary branch to avoid backsliding.

Currently, running make test should be the bar.

`gem install syck` fails to build native extensions

Reproduce via:

  • run the preview docker image
  • run gem install syck

Observe the following output:

Fetching: syck-1.2.0.gem (100%)
Building native extensions.  This could take a while...
ERROR:  Error installing syck:
	ERROR: Failed to build gem native extension.

Digging into the compile error the rb_omr_markstate_t definition is missing:

In file included from syck.h:20:0,
                 from gram.y:16:
/usr/local/include/ruby-2.2.0/ruby/st.h:180:27: error: unknown type name 'rb_omr_markstate_t'
 void rb_omr_mark_st_table(rb_omr_markstate_t ms, st_table *table);

Correctly (re)build the JIT object.

Currently, when you type make, the VM is built, but not the JIT object (librbjit.so).

Similarly, once the JIT is built, typing make librbjit.so never rebuilds the JIT, so what I've been doing is rm librbjit.so; make librbjit.so which is sort of exhausting ๐Ÿ˜ซ

Get an overview of status of 2.4 JIT

Currently, when running make test-all, due to #9, we fail relatively early.

It would be nice to trick test-all into continuing, to get a feeling for how many other crashers there are.

Play nice with tailcalls

We've known for some time that the JIT + tailcall optimization in the RubyVM do not get along. Historically, this hasn't been a big deal, as tail calls weren't a particularly common occurrence.

Until 6fd18ca at which point they became part of the implementation of forwardable.rb, which isn't exactly uncommon :)

So, better handling of tailcalls has jumped in priority.

TestProcess#test_deadlock_by_signal_at_forking

$ LD_LIBRARY_PATH=$PWD OMR_JIT_OPTIONS=-Xjit:count=0 make test-all TESTS=test/ruby/test_process.rb
...
[ 30/131] TestProcess#test_deadlock_by_signal_at_forking = 81.14 s                        
  1) Error:
TestProcess#test_deadlock_by_signal_at_forking:
Timeout::Error: execution of assert_separately expired
pid 645 killed by SIGTERM (signal 15)
...

Investigate unsetting VM_FRAME_FLAG_JITTED on fallback to VM path

In some circumstances, a JIT body may decide it cannot handle what the interpreter wishes it to do. In those cases, we fall back to the interpreter by invoking vm_exec.

When we do that, in 2.2 we would unset VM_FRAME_FLAG_JITTED, but in the course of a forward port to Ruby 2.4 this was disabled.

This actually needs to be investigated, and given some thought. The comment says that there is only a RAS ('Reliability, Availability, Servicability') impact... however, during the investigation of resuscitating the inliner it became clear that in some circumstances that flag changes other behaviour in the VM.

While I don't have an issue that I can directly point at this, we need to decide what to do about this flag.

Improve debuggability in trace logs

During ilgen, we know a lot about a call from the bytecode:

0021: 30 opt_send_without_block      end_with? (mid:6783) <argc:1 flag:0x10 (VM_CALL_ARGS_SIMPLE|0x0)>, E:93825003299064

By the time it becomes trees, we've obfuscated the information making it difficult to actually figure out what's happening:

n106n     treetop                                                                      
n101n       lcall  vm_send_without_block[#286  helper Method] [flags 0x400 0x0 ] ()    
n100n         aload  <parm 0 Lrb_thread_t;>[#611  Parm] [flags 0x40010107 0x0 ]        
n99n          aconst 0x555555fe2000                                                    
n98n          aconst 0x555555fe20f8                                                    
n80n          ==>lloadi

It would be really nice to know what that call is trying to resolve.

Move JIT Glue into the Ruby Repo?

When we initially pushed out the Ruby+OMR JIT compiler, I made the choice to keep the 'JIT Glue' in a separate repo in order to emphasize the relatively low impact of the JIT compiler on the Ruby interpreter when running -without- a JIT.

However, it's not clear to me that the distinction continues to hold: It may make more sense to pull the rbjitglue submodule code into the VM directly; The glue is tied to the VM fairly tightly, so it makes sense for them to live in the same repo.

Looking for feedback here.

If I did this, I would likely only do it for the ruby_2_4_omr branch.

make reconfig fails.

$ make -f common.mk BASERUBY=ruby MAKEDIRS='mkdir -p' srcdir=. update-config_files
common.mk:727: warning: overriding commands for target `/.timestamp/..time'
common.mk:717: warning: ignoring old commands for target `/.timestamp/..time'
downloading config.guess ... done
downloading config.sub ... done
$ autoconf
$ SPEC=linux_x86-64 ./configure -C --with-omr-jit --disable-install-doc --with-gcc=$CC 
$cp -pr config.status .ext/include config_1st
$ make reconfig
configure: loading cache config.cache
configure: error: `RBJITGLUE_DIR' was not set in the previous run
configure: error: `RELATIVE_OMR_DIR' was not set in the previous run
configure: error: in `/home/travis/build/mgaudet/ruby':
configure: error: changes in the environment can compromise the build
configure: error: run `make distclean' and/or `rm config.cache' and start over

Add JIT command line option

Today we pass options to the JIT using OMR_JIT_OPTIONS environment variable.

Would be really nice to have a command line option.

Missing output

# test_from_prime_division.rb
require 'prime'

def assert_equal expected, actual, msg=""
   if expected == actual  
      puts caller_locations[0] 
   else 
      puts "error! #{caller_locations[0]}" 
      puts "#{expected} != #{actual}" 
      raise "error"
   end
end

class Foo 
# The first 100 prime numbers
  PRIMES = [
    2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37,
    41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83,
    89, 97, 101, 103, 107, 109, 113, 127, 131,
    137, 139, 149, 151, 157, 163, 167, 173, 179,
    181, 191, 193, 197, 199, 211, 223, 227, 229,
    233, 239, 241, 251, 257, 263, 269, 271, 277,
    281, 283, 293, 307, 311, 313, 317, 331, 337,
    347, 349, 353, 359, 367, 373, 379, 383, 389,
    397, 401, 409, 419, 421, 431, 433, 439, 443,
    449, 457, 461, 463, 467, 479, 487, 491, 499,
    503, 509, 521, 523, 541,
  ]

  def test_from_prime_division
    assert_equal PRIMES.inject(&:*),  Integer.from_prime_division(PRIMES.map{|p| [p,1]})
    assert_equal(-PRIMES.inject(&:*), Integer.from_prime_division([[-1, 1]] + PRIMES.map{|p| [p,1]}))
  end

end

Foo.new.test_from_prime_division

We see that any output is lost here!

$ OMR_JIT_OPTIONS=-Xjit:count=0,limit={*prime.rb:172:int_from_prime_division*} LD_LIBRARY_PATH=$PWD  ./ruby --disable-gems -Ilib test_from_prime_division.rb
$ ./ruby --disable-gems -Ilib test_from_prime_division.rb 
test_from_prime_division.rb:30:in `test_from_prime_division'
test_from_prime_division.rb:31:in `test_from_prime_division'

Fix getLocalName

The function getLocalName seems to always return "?".

You can find the definition here;

Provide mechanism to override C methods with equivalent ruby versions

To experiment with inlining, it would be worth considering providing a uniform mechanism by which a pure-ruby implementation of a core C method could be picked up. I am imaging a special prelude module that would check a directory for 'bootstrap' overrides -- to borrow and abuse a term from Java.

Ensure better YARV bytecode test coverage

It would be fantastic if there was a test file that

  1. Created all the opcodes in the YARV bytecode set
  2. Ensured all branches are taken in the YARV bytecode set.

It would likely consist of a total opcode set, that then ran again after redefining a bunch of the basic operations.

Another extra bonus would be verifying that the tests actually do generate all bytecodes.

Improve aliasing of callbacks

Currently we assume a very conservative aliasing on pretty much all callbacks.

This is sufficient for correctness, but it would be nice to loosen this restriction to minimize rematerialization overhead where possible.

SEGV running test-all in rb_iseq_mark

[15938/17478] TestSyntax#test_keyword_rest/home/magaudet/open/ruby_Inliner/test/ruby/test_syntax.rb:120: [BUG] Segmentation fault at 0x000000000103e3
ruby 2.4.0p0 (2016-12-24 revision 57163) [x86_64-linux]

-- Control frame information -----------------------------------------------
c:0027 p:---- s:0156 e:000155 CFUNC  - :eval
c:0026 p:0010 s:0151 e:000150 BLOCK  - /home/magaudet/open/ruby_Inliner/test/ruby/test_syntax.rb:120 [FINISH]

/home/magaudet/open/ruby_Inliner/ruby(rb_vm_bugreport+0x53e) [0x5559befe88fe] vm_dump.c:685
/home/magaudet/open/ruby_Inliner/ruby(rb_bug_context+0xd1) [0x5559befdd901] error.c:426
/home/magaudet/open/ruby_Inliner/ruby(sigsegv+0x3e) [0x5559beed3ffe] signal.c:907
/lib/x86_64-linux-gnu/libpthread.so.0 [0x7efce50313d0]
/home/magaudet/open/ruby_Inliner/ruby(gc_mark_ptr+0x4e) [0x5559bedfe06e] gc.c:1111
/home/magaudet/open/ruby_Inliner/ruby(rb_iseq_mark+0xf5) [0x5559bee29295] iseq.c:128
/home/magaudet/open/ruby_Inliner/ruby(gc_marks_rest+0x74) [0x5559bee02094] gc.c:4629

According to backtrace, crash is here:

      RUBY_MARK_UNLESS_NULL(compile_data->mark_ary); 

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.