Opportunities for a Truffle-based Golo Interpreter
Julien Ponge, Frédéric Le Mouël, Nicolas Stouls, Yannick Loiseau
OOpportunities for a Truffle-based Golo Interpreter
Julien Ponge , Fr´ed´eric Le Mou¨el , Nicolas Stouls , and Yannick Loiseau Universit´e de LyonINSA-Lyon, CITI-INRIA F-69621, Villeurbanne, France [email protected] Clermont Universit´e, Universit´e Blaise Pascal, LIMOS, BP 10448,F-63000, Clermont-Ferrand, France [email protected]
April 2015
Abstract
Golo is a simple dynamically-typed language for theJava Virtual Machine. Initially implemented as aahead-of-time compiler to JVM bytecode, it leverages invokedynamic and JSR 292 method handles to imple-ment a reasonably efficient runtime. Truffle is emerg-ing as a framework for building interpreters for JVM lan-guages with self-specializing AST nodes. Combined withthe Graal compiler, Truffle offers a simple path towardswriting efficient interpreters while keeping the engineer-ing efforts balanced. The Golo project is interested in ex-perimenting with a Truffle interpreter in the future, as itwould provides interesting comparison elements betweeninvokedynamic versus
Truffle for building a language run-time.
Golo is a simple dynamically-typed language for the JavaVirtual Machine [1]. Initially designed as an experimentaround the capabilities of the new invokedynamic
JVMinstruction that appeared in Java SE 7 [2], it has sinceemerged as a language supported by a small communitythat goes beyond the bounds of academia. Applicationshave been found in
Internet of Things (IoT) settings, and we consider Golo to be small enough to be used for lan-guage and runtime experiments by researchers, studentsand hobbyists. This claim is supported by examples suchas ConGolo, a derivative experiment for contextual pro-gramming , and the community projects . Golo is cur-rently being proposed for incubation at the Eclipse Foun-dation in the hope of finding new opportunities and con-tinuing the development at a vendor-neutral foundation .Figure 1 provides a sample Golo program. It computesseveral Fibonacci numbers with the naive recursive defi-nition of the fib function. It takes advantage of regularJava executors and Golo APIs for promises and futures[3] to perform the computations on 2 worker threads, andcollect the results through reduction of futures.Briefly, the main characteristics of the Golo program-ming language are the following:• dynamic typing using Java types,• higher-order functions and binding to Java single-method and functional interfaces,• ability to augment existing types (including fromJVM languages) with new methods, See https://github.com/dynamid/contextual-golo-lang . The kiss web framework is a good example: https://github.com/k33g/kiss . See https://projects.eclipse.org/proposals/golo . a r X i v : . [ c s . P L ] M a y odule samples.Concurrencyimport java.util.concurrentimport gololang.Asynclocal function fib = |n| {if n <= 1 {return n} else {return fib(n - 1) + fib(n - 2)}}function main = |args| {let executor = Executors.newFixedThreadPool(2)let results = [30, 34, 35, 38, 39, 40, 41, 42]:map(|n| -> executor: enqueue(-> fib(n)):map(|res| -> [n, res]))reduce(results, "", |acc, next| ->acc + next: get(0) + " -> " + next: get(1) + "\n"):onSet(|s| -> println("Results:\n" + s)):onFail(|e| -> e: printStackTrace())executor: shutdown()executor: awaitTermination(120_L, TimeUnit.SECONDS())} Figure 1: Computing Fibonacci numbers in Golo withconcurrent and asynchronous APIs. • tuples and structures (augmenting the later is remi-niscent of Go-style objects [4]),• dynamic objects with instance-level definitions,• Python-style decorators (i.e., higher-order function-based).Unlike many other JVM languages such as JRuby,Jython or Nashorn, Golo is not a port of an existing lan-guage to the JVM and invokedynamic. This is interesting,as Golo was designed around the capabilities of invokedy-namic, which gives a different perspective on the designof a invokedynamic-based runtime.
Golo uses ahead-of-time bytecode generation rather thaninterpretation. The grammar of Golo is written usingthe LL ( k ) JJTree / JavaCC parser generator [5], mainlydue to its simplicity and lack of a runtime dependency,as it generates all the Java code required for a workingparser. The front-end generates an abstract syntax directlyfrom JJTree, which is then transformed into an intermedi-ate representation based on a Golo-specific object model,comprising classes to model reference lookups, functions,common statements and so on. The intermediate rep-resentation is visited by several phases to check for un-declared references, expand lambda functions / closuresto anonymous functions, and ultimately generated JVMbytecode with the popular ASM library [6].
Stable bytecode, adaptive runtime dispatch.
Thecompiler generates a largely untyped bytecode. Mostreferences are on the java.lang.Object type, withsome peculiar portions of the bytecode doing castchecks (e.g., branch conditions require refining to java.lang.Boolean and unboxing the primitive boolean value). The generated bytecode remains stableat runtime, unlike speculations and invalidations as foundin Nashorn to try to take advantage of primitive typeswhen possible.As most call sites (including arithmetic operators) arebased on invokedynamic, the runtime adapts the dispatch2 nlineCache(monomorphic) operatorimpl.asTypeguardWithTest fallbackclass == guardbindTo/insertArguments (Object)Object(Object,Object)Object (Class,Object)boolean(Class,Class,Object,Object)boolean(Object)Object(Object,Object)Object e.g.,2plus(Integer,Long)Long(InlineCache,Object[])Object test truefalse
Figure 2: Operator monomorphic inline-cache based on method handles.targets through evolving method handle chains, based ontypes observed at runtime. Figure 2 gives an example:operators use a monomorphic inline-cache construct [7].The construction relies on a guarded combinator that dis-patches to the right target as long as type remain stable(e.g., plus(Integer, Long) Long for
10 + 10 L ). Thefallback branch points to a handler that dynamically findsa new target based on the observed types, and overwritesthe call site method handle dispatch chain with the newone. (filter / map / reduce)
Figure 3: Filter / Map / Reduce micro-benchmark.
Euclidian GCD
Figure 4: Greatest common divisor micro-benchmark.
Performance considerations.
In general, Golo exhibitsgood performance on function and method dispatch . Fig-ure 3 shows the results of a micro-benchmark based onapplying the usual filter , map and reduce operations oncollections. Golo is practically as fast as a baseline inJava where the operations are implemented using collec-tion copies . See https://github.com/golo-lang/golo-jmh-benchmarks for a collection of micro-benchmarks. This micro-benchmark was written while Golo was still compatiblewith Java SE 7, hence it would be interesting to compare with Java SE 8streams.
Writing an interpreter for Golo based on Truffle [8] isinteresting for comparing the effectiveness of invokedy-namic versus
Truffle to implement common languageruntime patterns (e.g., arithmetic operations or inline-caches). In terms of performance, the following pointsare of comparison interest:1. functions and methods dispatch,2. arithmetic operations (Truffle node specialisationcan potentially eliminate some boxings),3. dispatch in Golo dynamic objects (Truffle proposesa
Shapes abstraction),4. statistical optimizations for application profiling(Truffle exposes node counters that could be use tomine application behavior and dynamically activaterelevant optimizations).We are looking forward to experimentions with Trufflein the near future, and have elements of comparisons inthe challenges of designing programming language on theJVM.
References [1] Julien Ponge, Fr´ed´eric Le Mou¨el, and Nicolas Stouls.Golo, a dynamic, light and efficient language for post-invokedynamic jvm. In
Proc. of PPPJ 2013 , pages153–158, New York, NY, USA, 2013. ACM.[2] John R. Rose. Bytecodes meet combinators: invoke-dynamic on the JVM. In
Proc. of VMIL’09 . ACM,2009. [3] B. Liskov and L. Shrira. Promises: Linguistic sup-port for efficient asynchronous procedure calls in dis-tributed systems. In
Proc. of PLDI’88 , pages 260–267, New York, NY, USA, 1988. ACM.[4] Rob Pike. Go at Google. In
Proc. of Splash’12 , pages5–6, New York, NY, USA, 2012. ACM.[5] Viswanathan Kodaganallur. Incorporating languageprocessing into java applications: A javacc tutorial.
IEEE Software , 21(4):70–77, 2004.[6] Eric Bruneton, Romain Lenglet, and Thierry Cou-paye. Asm: A code manipulation tool to implementadaptable systems. In
Adaptable and extensible com-ponent systems , 2002.[7] Urs H¨olzle, Craig Chambers, and David Ungar.Optimizing dynamically-typed object-oriented lan-guages with polymorphic inline caches. In
Proc. ofECOOP’91 , pages 21–38. Springer-Verlag, 1991.[8] Stefan Marr, Tobias Pape, and WolfgangDe Meuter. Are We There Yet? Simple Language-Implementation Techniques for the 21st Century.