On Tue, Sep 28, 2004 at 07:13:20AM +0900, Mauricio Fern?ndez wrote:
> On Mon, Sep 27, 2004 at 01:20:44AM +0900, Alexander Kellett wrote:
> >    Rubydium works by generating optimized platform specific code 
> >    on the fly, as needed, using instance type information gathered 
> >    during the execution itself.
> > 
> >    Optimisations are possible as the generated code can be specialized
> >    for the types in question, therefore allowing heavy inlining of
> >    speed critical sections.
> 
> How are you going to implement code cache invalidation? Will you just
> detect method redefinitions or is there some better way?

ouch, good question :P

in the case of non-inlined non-type-specialized methods this is trivial
as the dispatcher will be called into again, will have been notifed of
the modification to the object model, and will be able to adjust the
generated method as needed. 

however, in the case of an inlined/specialized method, in which a method 
call from within the specialized parent could result in a object model 
modification, this becomes slightly more difficult. in this case a kind 
of "cache exception" would be thrown, the inlined method would be jumped 
out of, and a new updated method generated and control passed on.

> >    This preview can execute an primitive subset of the 
> >    Ruby language, its slow, buggy, more complex than i'd 
> >    really like, and will probably make you loose a fair 
> >    amount of hair just getting the preview working :)
> 
> How large a subset?

have just been working on some stability improvements
to the current engine while trying to find out exactly what
sort of stuff could be implemented with the current subset.
i've got this nice example running in the latest version :)

      def strlen str
         return str.get_element(0)
      end
      def putstr str
         size = str.get_element(0)
         n = 1 # pos 0 is the length
         while n < (size + 1)
            putchar str.get_element(n)
            n += 1
         end
      end
      def num_to_s num
         n = num
         pos = 0
         while n > 0
            pos += 1
            n /= 10
         end
         t = VByteArray.new
         t.alloc((pos + 1) * 4)
         size = pos
         t.set_element(0, size)
         n = num
         while n > 0
            ch = ?0 + n % 10
            t.set_element(pos, ch)
            n /= 10
            pos += -1
         end
         t
      end
      def mul_line sx, sy, y
         max_num_len = strlen(num_to_s(sx * sy))
         alignment = max_num_len + 1
         x = 1
         while x < (sy + 1)
            num_str = num_to_s(x * y)
            num_spaces = alignment - strlen(num_str)
            c = 0
            while c < num_spaces
               putstr " "
               c += 1
            end
            putstr num_str
            x += 1
         end
      end
      def mul_table sx, sy
         y = 1
         while y < (sy + 1)
            mul_line sx, sy, y
            putstr "\\n"
            y += 1
         end
      end
      mul_table 12, 12

which produces the very pretty (:P) output: 

      1   2   3   4   5   6   7   8   9  10  11  12
      2   4   6   8  10  12  14  16  18  20  22  24
      3   6   9  12  15  18  21  24  27  30  33  36
      4   8  12  16  20  24  28  32  36  40  44  48
      5  10  15  20  25  30  35  40  45  50  55  60
      6  12  18  24  30  36  42  48  54  60  66  72
      7  14  21  28  35  42  49  56  63  70  77  84
      8  16  24  32  40  48  56  64  72  80  88  96
      9  18  27  36  45  54  63  72  81  90  99 108
     10  20  30  40  50  60  70  80  90 100 110 120
     11  22  33  44  55  66  77  88  99 110 121 132
     12  24  36  48  60  72  84  96 108 120 132 144

(note the code doesn't reflect ruby's api basically
 out of pure lazyness on my part, it would be possible
 to use ruby's object model / naming schemes however i 
 just quickly hacked this together in a half hour :))

> >    However, its a proof of concept that does show that
> >    The Twist is implementable using the libjit library.
> 
> How does libjit interact with low-level things like OS threads?

as far as i can tell (and as far as the libjit documentation
reports) this should be no problem :), this is principally a 
question of making sure that the standard library is reentrant.
however as 90% of the standard lib will be implemented in ruby
itself. i see no reason why not :)

> >    Any failed tests?, first please check that you actually do have an
> >    interpreter build of libjit rather than a x86 backend build. If you're
> >    certain that there are other errors, feel free to email me the failure 
> >    reports :)
> 
> Do you know when it will become possible to use the x86 backend?

the libjit x86 backend doesn't implement some of the more esoteric
features that i've used. hopefully i'll be able to get this up and
running in the near future :)

> And how big a speed increase can be expected relative to the interpreted VM?

in a quick benchmark 1000 calls to method with an 10000 iteration loop
took 22 seconds with ruby. and exactly the same with rubydium :) this
is as currently no inlining of the calls is performed thusly an actual
ruby method call (to dynamically generate the method) takes place for 
every call. 

i've benchmarked libjit quickly, a gcd (greatest common denominator)
benchmark takes 15 seconds. this is in comparison to 30 seconds for a 
non optimised gcc. 12 seconds for -O3 gcc (though the compile takes
3 seconds :P). and... well... lets say a "while" longer for ruby :) 
(an hour based on a quick sample)

i would hope that for that particular benchmark, rubydium will be
able to achieve the 15 second time within the coming 6 months of
development.

hope that helped answer your questions :)
cheers,
Alex