Golo, a Dynamic, Light and Efficient Language for Post-invokedynamic JVM

50a17cd98aab2cc4d8e144741e11b1b7?s=47 Julien Ponge
September 12, 2013

Golo, a Dynamic, Light and Efficient Language for Post-invokedynamic JVM

50a17cd98aab2cc4d8e144741e11b1b7?s=128

Julien Ponge

September 12, 2013
Tweet

Transcript

  1. PPPJ 2013 Stuttgart, Germany — a Dynamic, Light and Efficient

    Language for Post-invokedynamic JVM Julien Ponge Frédéric Le Mouël Nicolas Stouls
  2. A new language built with {invokedynamic}

  3. DynaMid Middleware for dynamic environments APIs Languages Frameworks Runtimes

  4. public static java.lang.Object main(java.lang.Object); Code: 0: ldc #19 2: invokedynamic

    #29, 0 7: pop 8: aconst_null 9: areturn runtime-bound call site method handles + combinators (type, logic, ...)
  5. Hackable language implementation Humble approach to a new research field

    invokedynamic / JSR 292 for new languages? Disseminate experience outside of academia, F/OSS
  6. Language quick, incomplete, Tour

  7. module hello function main = |args| { let message =

    "Hello, PPPJ'13!" var a = 1 a = a + 1 display(message) display(">>> " + a) } local function display = |what| -> println(what)
  8. module hello import java.util.LinkedList function main = |args| { let

    l = LinkedList() l: add(1) l: add(2) l: add(3) var sum = 0 foreach n in l { sum = sum + n } println(">>> " + sum) } constructors as functions calling an instance method
  9. let list = LinkedList(): append(1, 2, 3, 4) let result

    = list: map(|x| -> x + 10): filter(|x| -> (x % 2) == 0): reduce(0, |acc, x| -> acc + x) # >>> 26 println(">>> " + result) append? map, filter, reduce?
  10. function main = |args| { println("http://google.com": toURL(): getContent(): readFully()) }

    Augmentation on String Augmentation on InputStream
  11. augment java.lang.String { function toURL = |this| -> java.net.URL(this) }

    augment java.io.InputStream { function readFully = |this| { let streamReader = java.io.InputStreamReader(this) let reader = java.io.BufferedReader(streamReader) let buffer = java.lang.StringBuilder() var line = 0 while line isnt null { line = reader: readLine() buffer: append(line orIfNull "") } reader: close() return buffer: toString() } }
  12. let contacts = HashMap(): add("mrbean", HashMap(): add("email", "bean@gmail.com"): add("url", "http://mrbean.com")):

    add("larry", HashMap(): add("email", "larry@iamricherthanyou.com")) # MrBean and Larry let mrbean = contacts: get("mrbean") let larry = contacts: get("larry") # Illustrates orIfNull println(mrbean: get("url") orIfNull "n/a") println(larry: get("url") orIfNull "n/a") # Querying a non-existent data model because there is no 'address' entry println(mrbean: get("address")?: street()?: number() orIfNull "n/a") dealing with null
  13. let data = [ [1, 2, 3], tuple[1, 2, 3],

    array[1, 2, 3], set[1, 2, 3, 3, 1], map[ ["a", 10], ["b", 20] ], vector[1, 2, 3], list[1, 2, 3] ] Tuples Arrays (JVM) LinkedHashSet LinkedHashMap ArrayList LinkedList
  14. let what = |item| -> match { when item: contains("@")

    then "an email?" when item: startsWith("+33") then "a French phone number?" when item: startsWith("http://") then "a website URL?" otherwise "I have no clue, mate!" } let func = what: andThen(|str| -> println(">>> " + str)) let data = ["http://golo-lang.org/", "+33.6.11.22.33", "foo@bar.com", "def foo = bar(_._) with :> T"] foreach item in data { func(item) }
  15. let counter = DynamicObject(): define("value", 0): define("incr", |this| { this:

    value(this: value() + 1) return this }) # 0 println(counter: value()) # Increment twice counter: incr(): incr() # 2 println(counter: value())
  16. struct Point = { x, y } augment hello.types.Point {

    function moveBy = |this, dx, dy| { this: x(this: x() + dx) this: y(this: y() + dy) return this } } # struct Point{x=11, y=-4} println(Point(1, 1): moveBy(10, -5)) + toString, equals, hashCode
  17. $ du -hc lib/*.jar 48K lib/asm-4.1.jar 252K lib/golo-0-preview7-SNAPSHOT.jar 60K lib/jcommander-1.30.jar

    360K total $ golo {compile, run, golo, version}
  18. AOT, invokedynamic call sites polymorphic inline-cache, megamorphic inline-cache, null-safe dispatch,

    dynamic objects, operators, ...
  19. invokedynamic toString (Object)Object MethodInvocationSupport.bootstrap(...) fallback initial state

  20. invokedynamic toString (Object)Object MethodInvocationSupport.bootstrap(...) fallback guard asType SomeClass::toString()String monomorphic

  21. fallback guard asType Foo::toString()String guard asType SomeClass::toString()String polymorphic (< n)

  22. WeakHashMap { Foo::toString()String SomeClass::toString()String (...) } megamorphic (≥ n) foldArguments(target,

    combiner) exactInvoker(type) custom_vtable_lookup(callsite, args[]) + bind / asCollector / asType
  23. How about performance? (take with a grain of salt)

  24. Check specific runtime code Try to port to other JVM

    languages hard to be “fair” stay idiomatic no types, ever no tricks dispatch, mostly
  25. *Groovy with invokedynamic is not included (very bad on polymorphic

    call sites) 0" 2" 4" 6" 8" 10" 12" Monomorphic" TriMorphic" MegaMorphic" JRuby" Clojure" Groovy" Java"reflec@on" Golo" Java" java version "1.7.0_17" Java(TM) SE Runtime Environment (build 1.7.0_17-b02) Java HotSpot(TM) 64-Bit Server VM (build 23.7-b01, mixed mode)
  26. 0" 5" 10" 15" 20" 25" 30" 35" 40" Java"

    Java" (boxing)" Golo" Groovy" (indy)" Java" reflec;on" Clojure" JRuby" Groovy" fib(40)' 0" 0.2" 0.4" 0.6" 0.8" 1" 1.2" 1.4" 1.6" Golo" Groovy" Groovy"(indy)" Clojure" JRuby" Filter,(map,(reduce(
  27. Experience with invokedynamic Thin and reasonably efficient runtimes Frequent invalidations

    worse than reflection (e.g., Groovy-indy) Memory impact of many call sites? JVM support for boxing elimination? Faster vtable helpers for instance-based dispatch?
  28. What’s next? Converge towards a proper v0 release Dynamic class

    adapters, proxies, etc Concurrency APIs Doc generation More performance + memory benchmarks (Debian shootout?) Runtime extensions (e.g., dynamic sandbox / monitoring) Type specialization mechanisms? Graal / Truffle interpreter?
  29. Q+A @golo_lang - #gololang http://golo-lang.org/ http://dynamid.citi-lab.fr/ Julien Ponge Frédéric Le

    Mouël Nicolas Stouls