steve-s / talk2compiler

Talk to Graal Compiler on stock JDK11

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Talk to (Graal) Compiler (on JDK11+)

Sample project showing how to control Graal Compiler via Truffle API.

Talk2Compiler

Pre requirements

Setup

$ git clone https://github.com/jaroslavtulach/talk2compiler
$ cd talk2compiler
$ JAVA_HOME=/jdk-11 mvn package exec:exec -Dexec.appArgs=Truffle

Working with the sources

The project stands in its master state as a platform ready for your experimentations. Use it to get the Graal JIT compiler under your control. Use it to get the best from the dynamic just in time compiler surrouding your code. Just enclose your code into the Main.execute method and you'll be in direct contact with the assembly - code in Java, but directly influence the native code. That is what we are aiming at!

Look at the Compiler

Download GraalVM EE and launch Ideal Graph Visualizer. It starts listening on port 4445 and is ready to accept graphs showing progress of Graal compilations. Either run the program with -Pigv

$ JAVA_HOME=/jdk-11 mvn -Pigv process-classes exec:exec -Dexec.appArgs=Truffle

or run the tests to dump the execution graphs

$ JAVA_HOME=/jdk-11 mvn -Pigv test

The igv profile passes additional arguments to the JVM: -Dgraal.Dump=:1 -Dgraal.PrintGraph=Network. A tree of graphs representing Truffle::Main shall appear in the IGV. The most interesting phase is Graal Graphs/Before phase Lowering - it contains all the Graal optimizations, yet the vertexes still resemble bytecode instructions and are OS architecture neutral.

Exploring the Compilations

Try to add field into Main class called warmWelcome. Use different message format when it is true and different when it is false. When you look at the graph you shall see the load of the field value and if vertex.

Try to make the field final. The load and if disappears. Remove the final modifier and annotate the field as @CompilationFinal. The result is the same. Modify the value of the field (in the Main.execute method), but don't forget to call CompilerDirectives.transferToInterpreterAndInvalidate() to tell the compiler to recompile.

Rather than using these primitive operations, consider using profiles like ConditionProfile.createBinaryProfile(). Profiles are built with the above primitives, yet they are easier to use.

Speed a Graph Algorithm up

The BooleanNetwork branch contains a graph with states representing spreading of tumor in a brain. Let's search the graph for a state that matches certain pattern - nulls are ignored, true and false values must match. The algorithm counts how many nodes in the graph match.

The algorithm can run in regular HotSpot mode as well as in Truffle one entered via CallTarget. When in Truffle mode, one can apply additional hints - namely @CompilerDirectives.CompilationFinal(dimensions = 1), @ExplodeLoop and CompilerAsserts.partialEvaluationConstant - to speed the execution up by expanding the match loop and eliminating the null checks.

Build a Polymorphic Cache

The @ExplodeLoop annotation can be used to control the amount of generated code. Use it to build a polymorphic cache a phone book mapping between names and numbers. Control the size of the cache (e.g. generated code) fallback to regular (slow) lookup in a HashMap.

Nodes and DSL

Create simple AST to process array of numbers. Send the graph to IGV and see how the partial evaluation reduced it to three load and two plus instructions. Change the example to use Object[]. Rewrite Plus.compute to support not only int, but also double and/or any object. Observe the gigantic IGV graph. Use compiler directives, profiles & etc. to optimize the graph again. After realizing that it is too complex, use the DSL specialization annotation processors to do the hard work for you.

About

Talk to Graal Compiler on stock JDK11


Languages

Language:Java 100.0%