Polyglot Programming

TornadoVM can be used with the GraalVM Truffle Polyglot API to invoke Task-Graphs from guest programming languages such as Python, Ruby, etc. This guide will describe how to execute TornadoVM programs through code written in Python, JavaScript, and Ruby.

1. Prerequisites

A) Configuration of the JAVA_HOME Variable

To enable polyglot support, the JAVA_HOME variable must be set to the GraalVM path. Instructions on how to install TornadoVM with GraalVM can be found here: Installation for GraalVM for JDK 21.0.1 on Linux and macOS.

$ export JAVA_HOME=<path to GraalVM jdk 21>

B) GraalVM Polyglot Dependencies

The implementations of the programming languages (e.g., Python, JavaScript, Ruby) that are supported by the GraalVM polyglot API are now shipped as standalone distributions. And they can either be used as any other Java library from Maven Central, or as standalone toolkits.

2. Using the GraalVM Polyglot Dependencies from Maven Central

A) Build TornadoVM with the GraalVM Polyglot Dependencies from Maven Central

To build TornadoVM and utilize the maven dependencies for GraalPy, GraalVM JavaScript and TruffleRuby, you can build TornadoVM and use the graalvm-polyglot profile.

$ make graal-jdk-21 polyglot

B) Run the Examples

Now, that TornadoVM is built with the polyglot dependencies, you can run the available examples that exhibit the interoperability of Python, JavaScript and Ruby code from Java.

$ tornado --debug -m tornado.examples/uk.ac.manchester.tornado.examples.polyglot.HelloPython
$ tornado --debug -m tornado.examples/uk.ac.manchester.tornado.examples.polyglot.HelloJS
$ tornado --debug -m tornado.examples/uk.ac.manchester.tornado.examples.polyglot.HelloRuby

3. Using the GraalVM Polyglot Dependencies as Standalone Toolkits

However, to interoperate from programs written in those programming languages and invoke a Java method, users would use the standalone distributions. However, an aftermath of the last change is that the dedicated builds of GraalVM implemented languages, such as GraalPy, GraalVM JavaScript and TruffleRuby, do not work out-of-the-box with TornadoVM. Instead, users must build those frameworks from source.

A) Build GraalVM Polyglot Dependencies from Source

GraalVM implementations of the programming languages that can interoperate with Java are provided as standalone distributions, e.g., GraalPy, GraalVM JavaScript, TruffleRuby. As detailed in the GraalVM Reference Manuals, the following dependencies must be downloaded for each of the programming languages supported:

To ease users, we outline beneath two steps in order to build each of the programming languages supported and to interoperate with TornadoVM.

Step 1: Build GraalPy, GraalVM JavaScript and TruffleRuby, from source.

  • Python

$ git clone https://github.com/oracle/graalpython.git && cd graalpython && git checkout graal-23.1.0
$ git clone https://github.com/graalvm/mx.git mx
$ export PATH=$PWD/mx:$PATH
$ mx fetch-jdk
$ export JAVA_HOME=~/.mx/jdks/labsjdk-ce-21.0.1-jvmci-23.1-b22
$ mx --dy /compiler python-gvm
  • JavaScript

$ git clone https://github.com/oracle/graaljs.git && cd graaljs && git checkout graal-23.1.0
$ git clone https://github.com/graalvm/mx.git mx
$ export PATH=$PWD/mx:$PATH
$ mx fetch-jdk
$ export JAVA_HOME=~/.mx/jdks/labsjdk-ce-21.0.1-jvmci-23.1-b22
$ mx --dynamicimports /compiler build
  • Ruby

$ git clone https://github.com/oracle/truffleruby.git && cd truffleruby && git checkout graal-23.1.0
$ git clone https://github.com/graalvm/mx.git mx
$ export PATH=$PWD/mx:$PATH
$ mx fetch-jdk
$ export JAVA_HOME=~/.mx/jdks/labsjdk-ce-21.0.1-jvmci-23.1-b22
$ mx sforceimports
$ mx --dynamicimports /compiler build

Step 2: Set up the suitable variable for each programming language.

Set the JAVA_HOME variable to the GraalVM JDK:

$ export JAVA_HOME=<path to GraalVM jdk 21>

To enable TornadoVM to employ the standalone built distribution of the GraalVM implementations, users must set the following variables.

Note: The following examples show tentantive paths for a Linux environment. If you are using Mac OS X, you should ensure that your path includes the </Contents/Home> suffix.

  • For Python, set GRAALPY_HOME:

$ export GRAALPY_HOME=<path-to-graalpy>/../graal/sdk/mxbuild/linux-amd64/GRAALVM_03DCD25EA1_JAVA21/graalvm-03dcd25ea1-java21-23.1.0-dev
  • For JavaScript, set GRAALJS_HOME:

$ export GRAALJS_HOME=<path-to-graaljs>/../graal/sdk/mxbuild/linux-amd64/GRAALVM_3AF13F6F38_JAVA21/graalvm-3af13f6f38-java21-23.1.0-dev
  • For Ruby, set TRUFFLERUBY_HOME:

$ export TRUFFLERUBY_HOME=<path-to-truffleruby>/../graal/sdk/mxbuild/linux-amd64/GRAALVM_AEA5C30A3B_JAVA21/graalvm-aea5c30a3b-java21-23.1.0-dev

B) Interoperate between a Polyglot Programming Language and TornadoVM through Graal’s Polyglot API

In the following example, we will iterate over the necessary steps to invoke a TornadoVM computation from Python, JavaScript and Ruby programs, using the MyCompute class from the TornadoVM examples module. However, users can create their own Java classes with the code to be accelerated following the TornadoVM API guidelines Core Programming.

Step 1: Create a variable that is of the Java class type.

  • Python

myclass = java.type('uk.ac.manchester.tornado.examples.polyglot.MyCompute')
  • JavaScript

var myclass = Java.type('uk.ac.manchester.tornado.examples.polyglot.MyCompute')
  • Ruby

myclass = Java.type('uk.ac.manchester.tornado.examples.polyglot.MyCompute')

Step 2: Use this variable to invoke the Java function that contains the Task-Graph.

In this example, the function is named compute() and it performs a matrix multiplication.

  • Python

myclass.compute()
  • JavaScript

myclass.compute()
  • Ruby

myclass.compute()

Step 3: Execute the Ruby/JavaScript/Python program through TornadoVM.

The polyglot program can be executed using the tornado command, followed by the --truffle option and the language of the program, as follows:

$ tornado --truffle python|ruby|js|node <path/to/polyglot/program>

All of the existing TornadoVM options (e.g., --printKernel, etc.) can be used as always.

C) Run the Examples

The tornado-assembly/src/examples/polyglotTruffle directory contains three examples, one for each of the supported languages. These examples can be executed using the polyglotTests.sh script.

$ ./scripts/polyglotTests.sh
  • Python

$ tornado --printKernel --truffle python $TORNADO_SDK/examples/polyglotTruffle/mxmWithTornadoVM.py
  • JavaScript

$ tornado --printKernel --truffle js $TORNADO_SDK/examples/polyglotTruffle/mxmWithTornadoVM.js
  • Ruby

$ tornado --printKernel --truffle ruby $TORNADO_SDK/examples/polyglotTruffle/mxmWithTornadoVM.rb