20.03.2016 Views

the JVM with Truffle and Graal

1UueJB1

1UueJB1

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

Sulong: Fast LLVM IR Execution on<br />

<strong>the</strong> <strong>JVM</strong> <strong>with</strong> <strong>Truffle</strong> <strong>and</strong> <strong>Graal</strong><br />

FOSDEM 2016: 31. January 2016<br />

Manuel Rigger @RiggerManuel<br />

PhD student at Johannes Kepler University Linz, Austria


Why Do We Need A(no<strong>the</strong>r) LLVM IR<br />

Interpreter?<br />

Compiletime<br />

Linktime<br />

Runtime<br />

Speculative optimizations?<br />

Offline<br />

Lattner, Chris, <strong>and</strong> Vikram Adve. "LLVM: A compilation framework for lifelong program analysis & transformation."<br />

Code Generation <strong>and</strong> Optimization, 2004. CGO 2004. International Symposium on. IEEE, 2004.


Motivation Example: Function Pointer Calls<br />

int ascending(int a, int b){ return a - b; }<br />

int descending(int a, int b){ return b - a; }<br />

void bubble_sort(int *numbers, int count, (*compare)(int a, int b)) {<br />

for (int i = 0; i < count; i++) {<br />

for (int j = 0; j < count - 1; j++) {<br />

if (compare(numbers[j], numbers[j+1]) > 0) {<br />

swap(&numbers[j], &numbers[j+1]);<br />

}<br />

}<br />

}<br />

}


Sulong<br />

• LLVM IR interpreter running on <strong>the</strong> <strong>JVM</strong><br />

• With dynamic optimizations <strong>and</strong> JIT compilation!<br />

• Available under a BSD 3-Clause License<br />

• https://github.com/graalvm/sulong<br />

• Contributions are welcome!<br />

• Sulong: Chinese for velocisaurus<br />

• 速 : fast, rapid<br />

• 龙 : dragon


<strong>Truffle</strong> Multi-Language Environment<br />

[1]<br />

C<br />

JavaScript<br />

Ruby<br />

R<br />

C<br />

LLVM<br />

Java<br />

Scala<br />

<strong>Truffle</strong><br />

<strong>Graal</strong><br />

http://www.github.com/graalvm


AST Interpreter<br />

Function<br />

Node<br />

define i32 @ascending(i32 %a, i32 %b) {<br />

%1 = sub nsw i32 %a, %b<br />

ret i32 %1<br />

}<br />

WriteI32<br />

Node<br />

%1<br />

SubI32<br />

Node<br />

ReturnI32<br />

Node<br />

ReadI32<br />

Node<br />

%1<br />

ReadI32<br />

Node<br />

%a<br />

ReadI32<br />

Node<br />

%b


<strong>Truffle</strong> <strong>and</strong> <strong>Graal</strong><br />

U<br />

Node Rewriting<br />

for Profiling Feedback<br />

G<br />

Compilation using<br />

Partial Evaluation<br />

G<br />

U<br />

U<br />

Node Transitions<br />

I<br />

G<br />

I<br />

G<br />

U<br />

U<br />

U<br />

Uninitialized<br />

Integer<br />

I<br />

I<br />

I<br />

I<br />

I<br />

AST Interpreter<br />

Uninitialized Nodes<br />

S<br />

String<br />

G<br />

D<br />

Double<br />

Generic<br />

AST Interpreter<br />

Rewritten Nodes<br />

Compiled Code


<strong>Truffle</strong> <strong>and</strong> <strong>Graal</strong><br />

Deoptimization<br />

to AST Interpreter<br />

G<br />

Node Rewriting to Update<br />

Profiling Feedback<br />

G<br />

Recompilation using<br />

Partial Evaluation<br />

G<br />

G<br />

I<br />

G<br />

I<br />

G<br />

D<br />

G<br />

D<br />

G<br />

I<br />

I<br />

I<br />

D<br />

I<br />

I<br />

I<br />

D


Example 1: Value Profiling<br />

Uninitialized<br />

MemoryRead<br />

Node<br />

expectedValue = memory[ptr];<br />

deoptimizeAndRewrite();<br />

Profiling<br />

MemoryRead<br />

Node<br />

MemoryRead<br />

Node<br />

currentValue = memory[ptr];<br />

if (currentValue == expectedValue) {<br />

return expectedValue;<br />

} else {<br />

deoptimizeAndRewrite();<br />

}<br />

return memory[ptr];


Example 2: Polymorphic Function Pointer<br />

Inline Caches<br />

No call<br />

compare(a, b) > 0<br />

1 call<br />

2 calls<br />

>2 calls<br />

Uninitialized<br />

CallNode<br />

Direct<br />

CallNode<br />

Direct<br />

CallNode<br />

Indirect<br />

CallNode<br />

compare(a, b);<br />

Uninitialized<br />

CallNode<br />

Direct<br />

CallNode<br />

Uninitialized<br />

CallNode<br />

if (compare == &ascending) {<br />

return ascending(a, b);<br />

} else if (compare == &descending) {<br />

return descending(a, b);<br />

} else {<br />

deoptimizeAndRewrite();<br />

}


Function Pointer Call Inlining<br />

descending<br />

bubble_sort<br />

bubble_sort<br />

descending<br />

ascending<br />

ascending


Demo


Getting started<br />

• Download <strong>the</strong> mx build tool<br />

$ hg clone https://bitbucket.org/allr/mx<br />

$ export PATH=$PWD/mx:$PATH<br />

• Clone <strong>the</strong> repo <strong>and</strong> build <strong>the</strong> project<br />

$ git clone https://github.com/graalvm/sulong<br />

$ cd sulong<br />

$ mx build<br />

• Compile <strong>and</strong> run a program<br />

$ mx su-clang -S -emit-llvm -o test.ll test.c<br />

$ mx su-run test.ll


Developing <strong>with</strong> mx<br />

• Generate Eclipse project files (also available for o<strong>the</strong>r IDEs)<br />

$ mx eclipseinit<br />

• Quality tools<br />

$ mx checkstyle/findbugs/pylint/...<br />

• run Sulong tests<br />

$ mx su-tests<br />

• Eclipse remote debugging (port 5005)<br />

$ mx su-debug test.ll


Compilation<br />

• Textual information about which LLVM functions are compiled<br />

$ mx su-run test.ll -Dgraal.Trace<strong>Truffle</strong>Compilation=true<br />

• View <strong>Truffle</strong> <strong>and</strong> <strong>Graal</strong> graphs<br />

$ mx igv<br />

$ mx su-run test.ll -Dgraal.Dump=<strong>Truffle</strong>


Example: <strong>Truffle</strong> Graph


Implementation of Memory<br />

• Unmanaged mode<br />

• Heap allocation: by native st<strong>and</strong>ard libraries<br />

• Stack allocation: Java Unsafe API<br />

• <strong>Graal</strong> Native Function Interface for library interoperability<br />

<strong>Graal</strong> Foreign<br />

Function Interface<br />

malloc


Current State<br />

• Performance: room for improvement on most benchmarks<br />

• Completeness: mostly focused on C so far<br />

• Missing: longjmp/setjmp, inline assembly, full support of 80 bit floats<br />

• Can execute most of <strong>the</strong> gcc.c-torture/execute benchmarks


Outlook<br />

• Low overhead security-related instrumentations<br />

<strong>Graal</strong> is specialized to perform optimizations for operations like bounds or<br />

type checks<br />

• Memory safety via allocating on <strong>the</strong> Java heap<br />

• Tracking of integer overflows<br />

• Full <strong>Truffle</strong> integration<br />

• Debugger <strong>with</strong> source code highlighting<br />

• Language interoperability


Q/A @RiggerManuel<br />

• Thanks for listening!


Attributions<br />

• [1] The JRuby logo is copyright (c) Tony Price 2011, licensed under <strong>the</strong><br />

terms of Creative Commons Attribution-NoDerivs 3.0 Unported (CC<br />

BY-ND 3.0)

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!