ruby--ruby/wasm
Yuta Saito dff70b50d0 [wasm] vm.c: stop unwinding to main for every vm_exec call by setjmp
the original rb_wasm_setjmp implementation always unwinds to the root
call frame to have setjmp compatible interface, and simulate sjlj's
undefined behavior. Therefore, every vm_exec call unwinds to main, and
a deep call stack makes setjmp call very expensive. The following
snippet from optcarrot takes 5s even though it takes less than 0.3s on
native.

```
[0x0, 0x4, 0x8, 0xc].map do |attr|
  (0..7).map do |j|
    (0...0x10000).map do |i|
      clr = i[15 - j] * 2 + i[7 - j]
      clr != 0 ? attr | clr : 0
    end
  end
end
```

This patch adds a WASI specialized vm_exec which uses lightweight
try-catch API without unwinding to the root frame. After this patch, the
above snippet takes only 0.5s.
2022-02-18 18:28:18 +09:00
..
tests
GNUmakefile.in
README.md
asyncify.h [wasm] vm.c: stop unwinding to main for every vm_exec call by setjmp 2022-02-18 18:28:18 +09:00
fiber.c
fiber.h
machine.c
machine.h
machine_core.S
missing.c
runtime.c
setjmp.c [wasm] vm.c: stop unwinding to main for every vm_exec call by setjmp 2022-02-18 18:28:18 +09:00
setjmp.h [wasm] vm.c: stop unwinding to main for every vm_exec call by setjmp 2022-02-18 18:28:18 +09:00
setjmp_core.S
wasm-opt

README.md

WebAssembly / WASI port of Ruby

How to cross-build

Requirement

Steps

  1. Download a prebuilt WASI SDK package from WASI SDK release page.
  2. Set WASI_SDK_PATH environment variable to the root directory of the WASI SDK package.
$ export WASI_SDK_PATH=/path/to/wasi-sdk-X.Y
  1. Download a prebuilt binaryen from Binaryen release page
  2. Set PATH environment variable to lookup binaryen tools
$ export PATH=path/to/binaryen:$PATH
  1. Configure
  • You can select which extensions you want to build.
  • If you got Out of bounds memory access while running the produced ruby, you may need to increase the maximum size of stack.
$ ./configure LDFLAGS="-Xlinker -zstack-size=16777216" \
  --host wasm32-unknown-wasi \
  --with-destdir=./ruby-wasm32-wasi \
  --with-static-linked-ext \
  --with-ext=ripper,monitor
  1. Make
$ make install

Now you have a WASI compatible ruby binary. You can run it by any WebAssembly runtime like wasmtime, wasmer, Node.js, or browser with WASI polyfill.

Note: it may take a long time (~20 sec) for the first time for JIT compilation

$ wasmtime ruby-wasm32-wasi/usr/local/bin/ruby --mapdir /::./ruby-wasm32-wasi/ -- -e 'puts RUBY_PLATFORM'
wasm32-wasi

Current Limitation

  • No Thread support for now.
  • Spawning a new process is not supported. e.g. Kernel.spawn and Kernel.system