Carbone Ruby VM README COPYING THANKS FEATURES TODO ChangeLog doc/guide.txt doc/generator.txt doc/input_language.txt doc/gc.txt doc/proposals.txt 20020416_1129 |
The Carbone Ruby VM ========================== Carbone is a vmgen based, efficient virtual machine for Ruby. It targets compatibility, performance and portability. Anton Ertl's vmgen is originally the build tool for Gforth, the fastest portable Forth implementation. It produces VMs that use direct threaded code and support various optimizations that make the execution of a virtual machine less virtual (i.e. faster). There is lots of flexibility gained in the decision to use vmgen; to name the most important: VM instructions can be coded in C What's already working in the Carbone VM is: * sending * generically calling C functions * parts of the Ruby object system * defining classes * defining methods * defining procs * calling methods, procs * instance variables for classes * Fixnum This is a developers-only prerelease of Carbone. BTW there is no compiler yet. Neither forward nor backwards compatibility is guaranteed! You have been warned. Carbone is released under the GPL. Parts will be under LPGL. I think about adopting the Guile Copyright. The preferred way for support and especially the exchange of ideas and patches is carbone-dev@mail.freesoftware.fsf.org and more occasionally than regularly irc (#ruby-lang). Carbone's author till now is Markus Liedl <markus.lado@gmx.de> Missing: -------- (in about the order I will continue) yield mixins mixins ivars (already prepared) super super with arguments full constants support singleton classes optional arguments rest array arguments parallel assignment continuations threads full eval support (esp. introduction of new variables) builtin classes like String, ... special variables ($' $: ...) (and somewhere in between this list I will start to build a frontend using the RubyInRuby Parser --- if I find no better parser) Dependencies ------------ Gforth snapshot from May 2001, which includes vmgen http://www.complang.tuwien.ac.at/anton/vmgen/ also see the paper there. Bison, Flex Ruby, MétaRuby for preprocessing Fixnum-Builtins to C/vmgen code www.ruby-lang.org, cvs.ruby-lang.org:/src/lib/metaruby (also changes neccessary in configuration.rb: $options[:metaruby] = "/..../src/lib/metaruby") GCC preferably version 3; but 2.x works also fine (you may have to adjust configuration.rb: $options[:has_gcc_3_0] = true; ...) Boehm GC optional; for example Debians libgc6 and libgc6-dev Till now it's running it on Linux. Build Process ------------- get the sources: cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/carbone \ login cvs -z3 -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/carbone \ co carbone $EDITOR carbone/configuration.rb cd carbone make gen ./gen -h ./gen -c tests/fib.lg make tests make all-tests and to build an optimized VM: change to `DEBUG = false' in carbone/configuration.rb make opt t=tests/fib.lg this will profile the VM using the given code; measure the unoptimized VM and then re-compile it with appropriate super-instructions. The resulting VM is named `$(t).vm', so in the example this would be `tests/fib.lg.vm'. You can see that by running `tests/fib.lg.vm -V', which will tell you something like: /--------------------------------------------------- | Carbone v0.1 -- A efficient Ruby VM | # of superinstructions : 39 | class-method cache : hash | | initialized \--------------------------------------------------- Note that the number of super-instructions is not 0. The list of super-instructions rests in vm/rb-super.vmg; and one can see which super-instructions got applied to some code by using the -c flag. Global configuration data is kept in configuration.rb. The files configuration.h and Makefile.conf are produced when executing `ruby configure.rb' (but this is done automatically if configuration.rb is changed; and in this case old *.o files are also swept away). Input Language -------------- The input language - Carbone's first native language - is Lisp-like, corresponding to a subset of LGram level 1. It is parsed and precompiled Ruby code. see doc/input_language.txt Usage ----- ./gen [options] [ file | -e string ] Options: -h Print this message and exit -c dump compiled code before execution -t trace execution -e use commandline for input -p profile VM code sequences >stderr -i inspect compilation of vm builtins -V version info plus details about VM internals -S don't use superinstructions -s print statistics for example: [.../carbone] ./gen -sScte "(send (lit 1) + ((lit 2)))" ------------------------------------------------------------------- initialized - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - send (lit 1) + ((lit 2)) - - - - - - - - - - - - - - - - - 0x849d0d0: lit 0x1 0x849d0d8: lit 0x2 0x849d0e0: swap 0x849d0e4: lit 0x7c 0x849d0ec: lit 0x1 0x849d0f4: send 0x849d0f8: nip 0x849d0fc: end - - - - - - - - - - - - - - - - - entering engine(0x849d0d0,0x863887c,(nil)) 0x849d0d0: lit , fp=(nil), sp=0x863887c i=0x1 -- 0x849d0d8: lit , fp=(nil), sp=0x8638878 i=0x2 -- 0x849d0e0: swap , fp=(nil), sp=0x8638874 i1=0x1 i2=0x2 -- 0x849d0e4: lit , fp=(nil), sp=0x8638874 i=0x7c -- 0x849d0ec: lit , fp=(nil), sp=0x8638870 i=0x1 -- 0x849d0f4: send , fp=(nil), sp=0x863886c rcv=0x1 sel=+<0x7c> inpar=0x1 -- retip=0xbffff97c oldfp=0x400aeb78 0x849d0f4: fixnumPlus, fp=(nil), sp=0x8638868 other=0x2 rcv=0x1 inpar=0x1 retip=0xbffff97c oldfp=0x400aeb78 -- ires=0x3 0x849d0f8: nip , fp=(nil), sp=0x8638874 i1=0x2 i=0x3 -- 0x849d0fc: end , fp=(nil), sp=0x8638878 i=0x3 ==> 0x3 (3) .uncached method searches: 1 ------------------------------------------------------------------- `send' is the interesting instruction, that transfers control to the implementation of Fixnum#+, which is a instruction named `fixnumPlus' in the current implementation. The `lit' instructs before it exist "only" to push receiver, selector, parameters and number of parameters in a well defined order, so that send and the method implementation can refind them. `nip' is necessary to throw away the parameter (which is responsability of the caller); The stack effect of `nip' is `( i1 i -- i )' (as seen in vm/rb-inst.vmg) which means: left side of `--' pop stack-top into variable i pop next stack-top into variable i1 right side of `--' push i as new stack-top The net effect is to pull out the stack element under the top stack element (which is the result of the called method, Fixnum#+ in this case). The instruction generator puts in one `nip' for each parameter (as seen in comp/generator.c#374) The GForth manual is a good read. Speed ----- I see Carbone running about seven times faster than matz' Ruby machine (on PentiumIII hardware). This happens especially with code that does not use lots of builtins (like Fixnum#+, ...); They are compiled C code like in matz' Ruby machine). But with code that recurses or calls other methods that are implemented in Ruby (better said: Carbon input language). From obvious reasons the mentioned improvment factor will go down to zero when spending all the time in builtins; (long running builtins, not Fixnum#+; but this effect begins with it). One may say snippets that do no work are producing larger speed improvments; but this is also the kind of code one calls object oriented; i.e. many levels of indirection, abstraction ..... Some of the files in carbone/tests/ may be interesting. (I hope there are no more logical errors in this code, so I will no more report a speed improvment factor of twenty, when this only happens because the corresponding Ruby code was different and doing the double work ... ) The produced assembler code for each VM instruction: cd carbone/vm; make engine.gdis; less engine.gdis |