Skip to content

Instantly share code, notes, and snippets.

@krestenkrab
Last active December 22, 2017 18:46
Show Gist options
  • Save krestenkrab/6339544 to your computer and use it in GitHub Desktop.
Save krestenkrab/6339544 to your computer and use it in GitHub Desktop.
Notes on the current status of Erjang

Elixir on Erjang

The last few weeks I've spent some night hacking time to get Erjang to be able to run Elixir. Here's a short note on the current status for those interested.

The bottom line is that we can now boot the Elixir REPL, it looks like this:

krab$ ./bin/iex 
Warning: could not run smart terminal, falling back to dumb one
Aug 26, 2013 11:11:14 AM erjang.EModuleManager$FunctionInfo$1 invoke
INFO: MISSING 'Elixir.Path':expand/1
Interactive Elixir (0.10.2-dev) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> 1/0
** (ArithmeticError) bad argument in arithmetic expression
    :erlang./(1, 0)
    :erlang.apply/2
    erl_eval.erl:569: :erl_eval.do_apply/6
    elixir.erl:138: :elixir.eval_forms/3
    :erlang.apply/2
    error_handler.erl:44: :error_handler.undefined_function/3
    :erlang.apply/2

iex(1)>

We're still not able to bootstrap Elixir on a Erjang-only system. Most significantly, there is a problem pertaining to regular expressions %r'foo' that have been compiled on BEAM currently cannot be loaded by Erjang. The trouble is that the Elixir compiler emits the value of the opaque data type re:mp() in the beam file, and Erjang can't grok that. We're working on a solution.

Regardless, this is a major step forward for Erjang. To get to this point, we had to implement a couple of things...

  • Erjang in now able to run Erlang R16B01.
  • Erjang now compiles and runs on Java 7, using Kilim 1.0 and ASM 4.0.
  • A bunch of new BIFs have been added and/or fixed.
  • Line numbers in Erlang stack traces actually work.

As for getting Elixir to run on Erjang, we found and fixed a handful of errors related to mangling of atoms to Java-permissible identifier names. Elixir has module names such as 'Elixir.Enum', which need to be mangled to something like Elixir$2EEnum to be a sensible Java identifier.

A few compiler-related bugs showed up due to Elixir's codegen. In one case, if an exception handler block is dead code, Erjang would elimiate the exception handling code, but still leave the handler's java class-file meta data. Now, when an exception handler is deemed dead code by the Erjang JIT, it will not emit the corrresponding metadata. Here's an example of an exception handler with dead code. Erjang determines that the outer handler (commented out) can never be activated.

 % try
      try
         do:something()
      catch
         _:_ -> false
      end
 % catch
 %    C:E -> raise(C,E,get_stacktrace)
 % end

Also, a number of BIFs are either new in R16 or happens to be touched by the code that Elixir generates. It seems that because Elixir uses binaries more than strings, these BIFs tend to focus in ones that need binaries.

  • erlang:binary_part/3 (and the gc_bif3 instruction)
  • erlang:binary_to_atom/2
  • erlang:'+'/1
  • erlang:integer_to_binary/1
  • binary:part/2,3

It's really easy to add a new BIF to Erjang, see here for an example of the binary:part/2 BIF implementation.

The last little wrinkle that we carved out was fixing line number support. We did have line numbers in stack traces, but they were wrong. Turns out that the numbers we did expose were indexes into the BEAM file's line number table. Now the BEAM loader also reads that table (if present), and line numbers are exposed correctly in traces.

Java 7 and onward

Upgrading to a newer Kilim based on ASM 4, and generating code appropriate for Java 7 was another challenge. The branch of Kilim that we're using in Erjang is this one. Being on ASM4 and being Java 7 compatible now lets us - when time permits - experiment with InvokeDynamic.

Retargeting for Java 7's invoke dynamic has the potential for many improvements. Roughly 50% code the generated (~90% of .class files) are simple trampoline classes which represent Erlang function objects. Reducing this could speed up launch times significantly, and reduce memory bloat.

@krestenkrab
Copy link
Author

Yes, Graal looks interesting; but I don't know how I would compile Erlang's process abstraction to it. Also, I don't understand the implications of using Graal in terms of portability to other JVMs, licensing, etc.

@devinus
Copy link

devinus commented Sep 9, 2013

@krestenkrab This is incredibly exciting. Please keep it up.

@heri16
Copy link

heri16 commented Dec 15, 2013

Looking forward to full compatibility when elixir is stable released in Q1 2014.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment