Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Java truffle native image #572

Merged
merged 4 commits into from
Jul 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions impls/java-truffle/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -677,3 +677,23 @@ It's also worth observing that the Truffle/GraalVM provide _other_ interesting b
that are not performance-related. I won't cover them here. I think the most interesting
non-performance benefit is the promise of interoperability with other Truffle languages.

## Bonus: AOT-compiled Mal

GraalVM can ahead-of-time compile Java into a stand-alone executable (with some caveats)
called a _native image_.
This works even for Truffle interpreters! With AOT-compiled Mal, we get all the JIT compilation
goodness of Truffle, _and_ we ditch the need for a Java runtime, **and** we skip the long JVM
start-up time! A GraalVM native image of our Mal interpreter is well suited for scripts and
command line applications.

The `make-native.sh` script can be used to compile a native image of any Mal step.
To run it, though, you'll need some additional
[prerequisites](https://www.graalvm.org/reference-manual/native-image/#prerequisites).

The `make-native.sh` script

* assumes you've already run `gradle build` to compile all Java classes
* takes as its only argument a step name, e.g. `step3_env`
** when no argument is supplied, `stepE_macros` is selected by default
* produces a `build/${STEP}` native image

4 changes: 2 additions & 2 deletions impls/java-truffle/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ repositories {
}

dependencies {
implementation 'org.graalvm.truffle:truffle-api:20.1.0'
implementation 'org.graalvm.truffle:truffle-api:21.1.0'
implementation 'org.organicdesign:Paguro:3.2.0'
annotationProcessor 'org.graalvm.truffle:truffle-dsl-processor:20.1.0'
annotationProcessor 'org.graalvm.truffle:truffle-dsl-processor:21.1.0'
}

group = 'com.github.mmcgill'
Expand Down
8 changes: 8 additions & 0 deletions impls/java-truffle/make-native.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/usr/bin/env bash

STEP=${1:-stepE_macros}

CP=$(gradle -q --console plain printClasspath)
native-image --macro:truffle --no-fallback --initialize-at-build-time \
-H:+TruffleCheckBlackListedMethods \
-cp "$CP" truffle.mal.$STEP build/$STEP
3 changes: 3 additions & 0 deletions impls/java-truffle/src/main/java/truffle/mal/Core.java
Original file line number Diff line number Diff line change
Expand Up @@ -1393,6 +1393,7 @@ abstract class EvalBuiltin extends BuiltinNode {
protected EvalBuiltin() { super("eval"); }

@Specialization
@TruffleBoundary
protected Object eval(Object ast) {
return language.evalForm(ast).call();
}
Expand All @@ -1404,11 +1405,13 @@ abstract class ThrowBuiltin extends BuiltinNode {

protected ThrowBuiltin() { super("throw"); }

@TruffleBoundary
@Specialization
protected Object throwException(String obj) {
throw new MalException(obj);
}

@TruffleBoundary
@Fallback
protected Object throwException(Object obj) {
throw new MalException(obj);
Expand Down
5 changes: 4 additions & 1 deletion impls/java-truffle/src/main/java/truffle/mal/MalEnv.java
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ class LexicalScope {
final LexicalScope parent;
final int depth;
final Map<MalSymbol, EnvSlot> slots;
private int staticBindingCount;
final Map<MalSymbol, Assumption> notDynamicallyBound;

LexicalScope() {
Expand All @@ -287,6 +288,7 @@ class LexicalScope {
this.parent = parent;
this.depth = parent == null? 0 : parent.depth+1;
this.slots = new HashMap<>();
this.staticBindingCount = 0;
this.notDynamicallyBound = new HashMap<>();
}

Expand All @@ -309,6 +311,7 @@ private Assumption getNotDynamicallyBound(MalSymbol symbol) {
public EnvSlot allocateSlot(MalSymbol symbol) {
var slot = new EnvSlot(0, slots.size(), getNotDynamicallyBound(symbol));
slots.put(symbol, slot);
staticBindingCount++;
return slot;
}

Expand Down Expand Up @@ -354,7 +357,7 @@ public void wasDynamicallyBound(MalSymbol sym) {
}

public int getStaticBindingCount() {
return slots.size();
return staticBindingCount;
}

static class EnvSlot {
Expand Down
9 changes: 9 additions & 0 deletions impls/java-truffle/src/main/java/truffle/mal/Types.java
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,15 @@ public MalVector append(Object obj) {
return new MalVector(vector.append(obj), this.meta);
}

@TruffleBoundary
public MalVector concat(Object[] objs) {
var v = vector.mutable();
for (int i=0; i < objs.length; ++i) {
v.append(objs[i]);
}
return new MalVector(v.immutable(), meta);
}

@TruffleBoundary
public MalVector concat(Iterable<? extends Object> objs) {
return new MalVector(vector.concat(objs), meta);
Expand Down
15 changes: 10 additions & 5 deletions impls/java-truffle/src/main/java/truffle/mal/step2_eval.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
Expand All @@ -15,6 +14,7 @@
import com.oracle.truffle.api.CallTarget;
import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.TruffleLanguage;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.frame.FrameDescriptor;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.TruffleObject;
Expand Down Expand Up @@ -137,9 +137,9 @@ static class VectorNode extends MalNode {

@Override
public Object executeGeneric(VirtualFrame frame) {
var elements = new ArrayList<>(elementNodes.length);
var elements = new Object[elementNodes.length];
for (int i=0; i < elementNodes.length; i++) {
elements.add(elementNodes[i].executeGeneric(frame));
elements[i] = elementNodes[i].executeGeneric(frame);
}
return MalVector.EMPTY.concat(elements);
}
Expand Down Expand Up @@ -174,14 +174,19 @@ static class LookupNode extends MalNode {
this.symbol = symbol;
}

@Override
public Object executeGeneric(VirtualFrame frame) {
@TruffleBoundary
private Object lookup() {
var result = replEnv.get(symbol);
if (result == null) {
throw new MalException(symbol+" not found");
}
return result;
}

@Override
public Object executeGeneric(VirtualFrame frame) {
return lookup();
}
}

static class ApplyNode extends MalNode {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,9 +204,9 @@ static class VectorNode extends MalNode {
@ExplodeLoop
@Override
public Object executeGeneric(VirtualFrame frame, MalEnv env) {
var elements = new ArrayList<>(elementNodes.length);
var elements = new Object[elementNodes.length];
for (int i=0; i < elementNodes.length; i++) {
elements.add(elementNodes[i].executeGeneric(frame, env));
elements[i] = elementNodes[i].executeGeneric(frame, env);
}
return MalVector.EMPTY.concat(elements);
}
Expand Down