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