Fetching contributors…
Cannot retrieve contributors at this time
244 lines (180 sloc) 8.23 KB

Release Notes for the MagLev Alpha


iconv: 'Unable to find FFI 'iconv_open' in: ,

On Mac OSX, a require of iconv may result in the following error message:

ERROR 2023, Error, 'Unable to find FFI 'iconv_open' in: ,

This has been seen on machines with the MacPorts version of libiconv.dylib installed AND the DYLD_FALLBACK_LIBRARY_PATH environment variable set to load the MacPorts version. This is because the names of the routines in the MacPorts version of iconv are different than the names in the Apple supplied iconv.

Here are the names in the Apple provided iconv:

$ nm /usr/lib/libiconv.dylib | grep iconv_open
000150b5 T _iconv_open
000158cc T _libiconv_open

Here are the names in the MacPorts version:

$ nm /opt/local/lib/libiconv.dylib | grep iconv_open
0000000000017f30 T _libiconv_open
0000000000018a60 T _libiconv_open_into

Solution is to ensure the DYLD_FALLBACK_LIBRARY_PATH environment variable is not set when running MagLev.

Persistence support

See the Persistence API

Special methods

  • Underscore + camelCase = GemStone unmodifiable code. There are several methods that begin with an underscore and are camelCase, e.g. _isArray. MagLev will not allow you to re-define these methods.

  • The method names (selectors) eval, class_eval, module_eval and instance_eval are handled specially in maglev. If you define a method with one of those selectors, then you'll get an error when trying to call it. E.g., given:

    class C
      def eval(an_arg)
    end"puts 10")

    When you run it, you'll get:

    error , too many arguments,
              during foo.rb
    ERROR 2023, Error, 'too many arguments' (ArgumentError)

Dynamic vs Fixed Instance Variables

The MagLev VM supports both fixed and dynamic instance variables. For Ruby, the default type of instance variable is dynamic, for Smalltalk, the default is fixed.

The VM optimizes access to fixed instance variables by making references to them a simple integer offset from a well known location in the object structure. These optimized instance variables are known as “fixed” or “static” instance variables. The other type of instance variable is a dynamic instance variable. The VM must lookup references to dynamic instance variables at runtime, by searching for them by name. This takes more time than using a pre-computed index.

How to declare fixed instance variables

MagLev provides the '__fixed_instvars' directive to declare fixed inst vars (it is a “directive”, not a method, since it is recognized by the parser and handled at parse time, not an expression evaluated at runtime).

class C
  self.__fixed_instvars('@foo', :@bar)

  # rest of class....

There are some restrictions on the use of the __fixed_instvars directive. + May only be issued once per class. + May only be issued in the first opening of the class. + The parameters must be simple strings or symbols (i.e., cannot be

expressions that are evaluated, nor can they be string interpolations
like "@#{something_or_other}".

+ Must be in the main class body (not in a method definition nor in a

singleton construct).

Implications for Persistence

Why MagLev has all dynamic instance variables by default

Smalltalk classes contain a list of instance variables. All Smalltalk objects allocate space for all instance variables, and instance variables are accessed as fixed offsets from the object header. Whan an instance variable is added or removed from a Smalltalk class, or the order of instance variables is changed, the Smalltalk system creates a new version of that class, recompiles all methods to use the new offsets. All instances of the old class need to be migrated to the new class, at which time, the instance variables are then in-sync with the method definitions.

Ruby is not Smalltalk. In Smalltalk, the developer explicitly manages the list of fixed inst vars, and there is a clear trigger that indicates all methods need re-compiling and that old instances should be migrated to the new format. This is not the case in Ruby. Imagine a customer application that has this persisted class, and imagine that instance variables were fixed:

class C
  def foo
    @foo = 1

  def bar
    @bar = 2

The class and instances are persisted. Then they release version 2 of the app, and for some reason, they simply swap the order of the method defns:

class C
  def bar
    @bar = 2

  def foo
    @foo = 1

If they persist this, and the methods get re-compiled, or they add new methods, then we will have a mix of instances and/or methods that have different opinions on the ordering of the inst vars. We could work around that issue by sorting the fixed inst vars by name, but that only solves some of the scenarios, e.g., it doesn't fix addition of new variables or removal of old ones.

Use of Fixed Instance Variables

MagLev now supports the __fixed_instvars directive. This allows the Ruby developer to declare, and take responsibility for, fixed instance variables. If objects with fixed instance variables are persisted in the repository, and the developer decides to add, remove or re-order the fixed instance variables, they must also take responsibility for migrating old instances to the new schema.

--stone s

By default, maglev-ruby starts a VM that will attempt to connect to the stone (repository server) named 'maglev'. The --stone astone option tells the VM to connect to the stone named 'astone'.

New stones can be created and managed via the Rakefile in $MAGLEV_HOME:

$ rake -T stone
(in /Users/pmclain/GemStone/checkouts/git)
rake stone:all[task_name]        # Invoke a task on all MagLev servers
rake stone:create[server_name]   # Create a new MagLev server and repository
rake stone:destroy[server_name]  # Destroy an existing MagLev server and repository
rake stone:list                  # List MagLev servers managed by this Rakefile


This flag is intended as an easy way to commit code (and data) in a ruby file to the persistent store. The flag does two things (1) wraps the entire file in a persistent block, and (2) commits upon exiting.

E.g., this command:

$ maglev-ruby -Mcommit foo.rb

acts like this:

Maglev.persistent do
  require 'foo.rb'


Starts the VM in persistent mode (normally it is started in transient mode). E.g., this command:

$ maglev-ruby -Mpersistent foo.rb

acts like this:

Maglev.persistent do
  require 'foo.rb'


This is a debug flag that prints trace information when global variables are defined or have their values set.


This is a debug flag that prints trace information as each .rb file is read by MagLev (from either a require or a load).


This is a debug flag that prints s-expressions as they are parsed by the parser. This can be pretty verbose…


Runs MagLev with rlwrap. This provides command line editing support if you end up in the topaz debugger, or for irb.


MagLev comes with a copy of RubyGems pre-installed. Gems get loaded into $MAGLEV_HOME/lib/maglev/gems/1.8/gems. Gems that are based on a C-extension may not install or run with MagLev.


  • Note that we don't support instance variables as block arguments, { |@cc| } must be coded as { | c | @cc = c }.

  • Kernel#require: Tilde expansion is done only on ~/..., not on ~user/..., $" is not updated

Noise from rlwrap

  • In some cases, rlwrap (see Prerequisites) will output noise while typing at a Topaz prompt (Linux only).

Unsupported Features

  • ARGF is not supported.

  • Continuations are not supported.

  • Most methods in ObjectSpace are stubs that raise NotImplementedError.

  • String#unpack and Array#pack do not support pointers ('p' and 'P').

  • Kernel#set_trace_func is not supported.