scala 2.12 java 8 - meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • ii: some...
TRANSCRIPT
![Page 1: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/1.jpg)
Scala 2.12 ❤ Java 8Lukas Rytz, Scala Team @ Lightbend
![Page 2: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/2.jpg)
Changes on the Surface
• Lambdas for SAM types: Java 8 interop
• Scaladoc: a new look
• REPL: tab-completion
• Minor changes in the standard library
2
![Page 3: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/3.jpg)
Changes Under the Hood
• Java-style encoding for lambdas
• Default methods for traits
• A new bytecode optimizer
3
![Page 4: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/4.jpg)
Agenda• I: Changes on the surface
• II: Some internals of HotSpot
• III: The Scala 2.12 Optimizer
• IV: New Bytecode in Scala 2.12 • InvokeDynamic for Lambdas • Default Methods for Traits
4
![Page 5: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/5.jpg)
Lambdas for SAM Types• SAM = "Single Abstract Method"
• Lambda syntax to create SAM type instances
• Same as in Java 8, mostly useful for interop
5
scala> new Thread(() => println("hi")).run hi
![Page 6: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/6.jpg)
Interop Example: Streams
6
scala> val myList = java.util.Arrays.asList( | "a1", "a2", "b1", "c2", "c1")
scala> myList.stream. | filter(_.startsWith("c")). | map(_.toUpperCase). | sorted. | forEach(println) C1 C2
![Page 7: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/7.jpg)
Scaladoc's New Look
7
http://www.scala-lang.org/api/2.12.0-RC2
![Page 8: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/8.jpg)
REPL tab-completion• Available in 2.11.8, 2.12.0
• Uses the presentation compiler (Scala IDE, ensime)
8
scala> List("a", "b").map(_.to<TAB> ... toDouble toLowerCase toUpperCase
scala> List("a", "b").map(_.touc<TAB> scala> List("a", "b").map(_.toUpperCase<TAB>
def toUpperCase(): String def toUpperCase(x$1: java.util.Locale): String
![Page 9: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/9.jpg)
Right-Biased Either
9
scala> def toInt(s: String): Either[MyError, Int] = | ...
scala> def sum(a: String, b: String) = for { | x <- toInt(a) | y <- toInt(b) | } yield x + y sum: (a: String, b: String)Either[MyError,Int]
scala> sum("1", "2") res1: Either[MyError,Int] = Right(3)
![Page 10: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/10.jpg)
Changes to the Library
• A mutable.TreeMap (sorted map)
• Deprecated JavaConversions: only explicit asScala / asJava using JavaConverters
• Various minor performance improvements
10
![Page 11: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/11.jpg)
Agenda• I: Changes on the surface
• II: Some internals of HotSpot
• III: The Scala 2.12 Optimizer
• IV: New Bytecode in Scala 2.12 • InvokeDynamic for Lambdas • Default Methods for Traits
11
![Page 12: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/12.jpg)
Java Bytecode Example
12
// def f(x: Int) = x + 1
public f(I)I ILOAD 1 ICONST_1 IADD IRETURN
x xx
xx1
xx+1
this this this this x+1
![Page 13: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/13.jpg)
Interpretation
13
val stack: Stack[Any] val frameIdx: Stack[Int]
def intp(code: List[Instr]) = { code.head match { case IConst(n) => stack.push(n) case ILoad(n) => stack.push(stack(frameIdx.head + n)) case IAdd => stack.push(stack.pop() + stack.pop()) ... } intp(code.tail) }
x xx
xx1
xx+1
this this this thisframeIndex.head
![Page 14: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/14.jpg)
Making it Fast
• Bytecode that is executed "many" times is compiled to native code (assembly)
• Two compilers in JDK 7+ • C1 ("client" compiler in JDK 6): fast • C2 ("server"): advanced optimisations, slower
14
![Page 15: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/15.jpg)
"Many" Executions• Method invocation counter: 2k → C1, 15k → C2
• C1 assembly is instrumented: update invocation counter, other metrics
• Loop counter: 60k iterations → C1, ... → C2 • Assembly entrypoint at the loop start • Switch to the assembly code: "on-stack
replacement" (OSR)
15
![Page 16: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/16.jpg)
Optimizations
16
29
Optimizations in HotSpot JVM ! compiler tactics delayed compilation tiered compilation on-stack replacement delayed reoptimization program dependence graph rep. static single assignment rep. ! proof-based techniques
exact type inference memory value inference memory value tracking constant folding reassociation operator strength reduction null check elimination type test strength reduction type test elimination algebraic simplification common subexpression elimination integer range typing ! flow-sensitive rewrites conditional constant propagation dominating test detection flow-carried type narrowing dead code elimination
! language-specific techniques class hierarchy analysis devirtualization symbolic constant propagation autobox elimination escape analysis lock elision lock fusion de-reflection ! speculative (profile-based) techniques optimistic nullness assertions optimistic type assertions optimistic type strengthening optimistic array length strengthening untaken branch pruning optimistic N-morphic inlining branch frequency prediction call frequency prediction ! memory and placement transformation expression hoisting expression sinking redundant store elimination adjacent store fusion card-mark elimination merge-point splitting
! loop transformations loop unrolling loop peeling safepoint elimination iteration range splitting range check elimination loop vectorization ! global code shaping inlining (graph integration) global code motion heat-based code layout switch balancing throw inlining ! control flow graph transformation local code scheduling local code bundling delay slot filling graph-coloring register allocation linear scan register allocation live range splitting copy coalescing constant splitting copy removal address mode matching instruction peepholing DFA-based code generator
"JVM JIT compilation overview" by Vladimir Ivanov http://www.slideshare.net/ZeroTurnaround/vladimir-ivanovjvmjitcompilationoverview-24613146
![Page 17: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/17.jpg)
Inlining• Inlining enables most other optimizations
• Duplicated code can be specialized
• Heuristics decide what to inline: • Small methods (35 bytes) are inlined • "Hot" callsites are inlined (up to 325 bytes) • Max depth of 9
17
![Page 18: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/18.jpg)
Inlining Virtual Methods• Java / Scala has virtual methods by default
• Many callsites are monomorphic • Class Hierarchy Analysis (CHA): a virtual method
with no overrides can be inlined (C1, C2) • Profile-based inlining (C2): inline if the receiver at
a callsite is always the same • Profiles collected by interpreter and C1 assembly
18
![Page 19: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/19.jpg)
Speculative Inlining• Assumptions can invalidate compiled code
• A method gets an override when a new class is loaded
• A new receiver type reaches a (previously monomorphic) callsite
• Deoptimization: the assembly is discarded, the interpreter takes over
19
![Page 20: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/20.jpg)
Learn (a lot) More
• "JVM Mechanics", talk by Doug Hawkins (Azul) • Slides: http://www.slideshare.net/dougqh/jvm-
mechanics-when-does-the • Video: https://www.youtube.com/watch?
v=E9i9NJeXGmM
20
![Page 21: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/21.jpg)
Agenda• I: Changes on the surface
• II: Some internals of HotSpot
• III: The Scala 2.12 Optimizer
• IV: New Bytecode in Scala 2.12 • InvokeDynamic for Lambdas • Default Methods for Traits
21
![Page 22: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/22.jpg)
Megamorphic Callsites
22
class Range { def foreach(f: Int => Unit) = { while(..) { .. f.apply(i) .. } } }
(1 to 10) foreach (x => foo) (2 to 20) foreach (x => bar) (3 to 30) foreach (x => baz)
Virtual call: • Run-time type of f defines which code to run • Megamorphic callsite, varying targets • Method lookup on every loop iteration
![Page 23: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/23.jpg)
Solution: Inlining
23
val _this = 1 to 10 val _f = (x: Int) => foo while(..) { .. _f.apply(i) .. }
(1 to 10) foreach (x => foo)
Scala optimizer inlines foreach
Monomorphic callsite enables JVM optimizations: • Skip method lookup • Inlining apply enables further optimizations
![Page 24: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/24.jpg)
Value Boxingvar r = 0 (1 to 10000) foreach { x => r += x }
class anonfun(r: IntRef) { def apply(x: Int) { r.elem += x } }
val r = IntRef(0) val f = new anonfun(r) (1 to 10000) foreach f
Slow • Why? Not obvious..
![Page 25: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/25.jpg)
Inlining
25
val r = IntRef(0) val f = new anonfun(r) (1 to 10000) foreach f
val r = IntRef(0) val f = new anonfun(r) var x = 0 while (x < 10000) { r.elem += x }
Inline foreach and function body
Still slow (same as before)! • Why? IntRef • Escape analysis fails..
![Page 26: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/26.jpg)
Closure Elimination
26
val r = IntRef(0) val f = new anonfun(r) var x = 0 while (x < 10000) { r.elem += x }
val r = IntRef(0) var x = 0 while (x < 10000) { r.elem += x }
Eliminate the closure allocation
Fast! JVM escape analysis kicks in.
![Page 27: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/27.jpg)
Box Elimination
27
val r = IntRef(0) var x = 0 while (x < 10000) { r.elem += x }
var r = 0 var x = 0 while (x < 10000) { r += x }
Local var instead of IntRef
Same as before!JVM optimizes the IntRef just fine.
![Page 28: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/28.jpg)
Bars
28
Tim
e
0
3.25
6.5
9.75
13fo
reac
h
while
+ In
tRef
(cap
ture
d)
while
+ In
tRef
(no
clos
ure)
while
+ v
ar
~ 4x
![Page 29: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/29.jpg)
Compile-time Optimizer
• Goal: transform the code to make it please the JVM
• Don't perform optimizations that the JVM does well
• Avoid fruitless inlining: degrades performance ↣ JVM optimizer is sensitive to method size
29
![Page 30: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/30.jpg)
Agenda• I: Changes on the surface
• II: Some internals of HotSpot
• III: The Scala 2.12 Optimizer
• IV: New Bytecode in Scala 2.12 • InvokeDynamic for Lambdas • Default Methods for Traits
30
![Page 31: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/31.jpg)
InvokeDynamic (indy)• Bootstrap method
• Runs once, when indy is first executed • Arguments from the bytecode descriptor
• Target method • Invoked on each indy execution • Acts on the ordinary JVM stack
31
![Page 32: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/32.jpg)
InvokeDynamic (indy)
32
invokedynamic name(argTps)resTp bsRef bsArgs
def myBootstrap(predefArgs, customArgs): CallSite
class CallSite { val/var target: MethodHandle // invoked method }
MethodHandle referenceto bootstrap method
![Page 33: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/33.jpg)
Indy-Lambda
33
(s: String) => s.trim
invokedynamic apply()Lscala/Function1; LambdaMetafactory.altMetafactory // bootstrap (Lj/l/Object;)Lj/l/Object; // SAM type A.$anonfun(Lj/l/String;)Lj/l/String // body meth
SAM name SAM interface
PR #4463
def $anonfun(s: String) = s.trim
![Page 34: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/34.jpg)
LambdaMetaFactory• Synthesizes and loads a new class that implements
the SAM interface
• Returns a CallSite with a target that creates a new instance • If nothing is captured, the CallSite target
returns a singleton instance
34
![Page 35: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/35.jpg)
LMF 📦 Boxing Adaptation
35
trait T[T] { def apply(x: T): String }
val f: T[Int] = (x: Int) => "x:" + x
<synth> def anonfun$f(x: Int) = "x:" + x
LMF supports such differences, adds an unboxing conversion
Erasure: (Obect)String
![Page 36: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/36.jpg)
Boxing 📦 Scala vs Java
36
trait T[T] { def apply(x: T): String } val f: T[Int] = (x: Int) => "x:" + x
f.asInstanceOf[T[Any]].apply(null)
<synth> def anonfun$f$adapted(x: Object) = anonfun$f(unboxToInt(x))
val a: Int = (null: Integer) // 0 in Scala int a = (Integer) null; // NPE in Java
PR #4497
![Page 37: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/37.jpg)
Specialization
37
trait A[@spec(Int) T] { def apply(x: T): Int } class C extends A[Int] { def apply(x: Int) = x }
trait A { def apply(x: Object): Object def apply$mcI$sp(x: Int): String = apply(box(x)) } class C extends A { def apply(x: Object) = apply$mcI$sp(unbox(x)) def apply$mcI$sp(x: Int) = x }
![Page 38: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/38.jpg)
LMF 💔 Specialization
38
trait A[@spec(Int) T] { def apply(x: T): Int }
val f: T[Int] = x => x
Should not box
trait A { def apply(x: Object): Object def apply$mcI$sp(x: Int): String = apply(box(x)) }
This is the SAM, LMF will implement it
![Page 39: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/39.jpg)
Don't subvert @spec
• FunctionN: hand-written specializations where the specialized method is abstract
• User-defined SAM types: don't use LMF, create an anonymous class at compile-time
39
![Page 40: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/40.jpg)
$outer 📤 for local classes
40
class A { def f = () => { class C; serialize(new C) } }
class $anofun { // 2.11 def apply() = { class C; serialize(new C) } }
class A { // 2.12 def $anonfun { class C; serialize(new C) } }
$outer is $anonfun
$outer is A
![Page 41: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/41.jpg)
A Final's Secret 💌
41
class A { class B final class C }
scala> classOf[A#B].getDeclaredFields.toList List(public final A A$B.$outer)
scala> classOf[A#C].getDeclaredFields.toList List()
scala> (new a1.C:Any) match {case _:a2.C => "OK"} OK
![Page 42: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/42.jpg)
Fix $outer Capture 🎣
42
• Mark local classes with no subclasses final
• The existing logic eliminates the $outer field if it is not needed
PR #4652
![Page 43: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/43.jpg)
More $outer Capture 🐡
• 2.11: local is lifted to the $anonfun class
• 2.12: local ends up in A, the closure needs to capture and store the outer A • Emit local methods static when possible
43
PR #5099
class A { val f = () => { def local = 1; local } }
![Page 44: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/44.jpg)
Lazy Val Init Lock 🔐
44
class A { def f = () => { lazy val x = 1; x } }
// generates def x(v: IntRef) = { if(!init) lzyCompute(v) .. } def lzyCompute(v: IntRef) = this.synchronized{..}
• 2.11: methods generated in $anonfun. 2.12: in A
• Contention on the A instance, deadlocks
![Page 45: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/45.jpg)
Local Lazies à la Dotty ⏺• Observation: local lazies are boxed anyway
• Synchronize initialization on the box itself
45
def f = () => { lazy val x = 1; x }
// generates def x(v: LazyInt) = if (v.init) v.value else lzyCompute(v)
def lzyCompute(v: LazyInt) = v.synchronized{..}
scala-dev#133
![Page 46: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/46.jpg)
Agenda• I: Changes on the surface
• II: Some internals of HotSpot
• III: The Scala 2.12 Optimizer
• IV: New Bytecode in Scala 2.12 • InvokeDynamic for Lambdas • Default Methods for Traits
46
![Page 47: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/47.jpg)
Default Methods• Looks like it could be simple:
• Challenges • Super calls • Multiple inheritance / linearization • Performance
47
trait T { def f = 1 }
interface T { default int f() { return 1; } }
![Page 48: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/48.jpg)
Invokespecial 💍• Used for private methods, constructors, super calls
• Method lookup is dynamic!
• If A is a superclass (transitive) of C, lookup starts at B, otherwise it starts at A
• Method lookup in superclasses, then interfaces
48
class C extends B {.. invokespecial A.f ..}
![Page 49: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/49.jpg)
Bug in 2.11 🐛
49
class A { def f = 1 } class B extends A { override def f = 2 } trait T extends A class C extends B with T { def t = super[T].f // should be 1 }
// invokespecial A.f in class C // Lookup for f starts in B (not A)
// 2.12: "error: cannot emit super call"
PR #5369
![Page 50: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/50.jpg)
Invokespecial , Parents
50
trait T { def f = 1 } trait U extends T class C extends U { def t = super.f }
trait T { default int f() { return 1; } static int f$($this: T) { $this.f(); } } class C { def t = T.f$(this) }
invokespecial T.f is notallowed unless C implements T
invokespecial T.f
PR #5177
![Page 51: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/51.jpg)
Forwarders ↪ 2.11
51
trait T { def f = 1 } class C extends T
interface T { int f(); } class T$class { public static int f(T $this) { return 1; } } class C implements T { public int f() { return T$class.f(this); } }
![Page 52: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/52.jpg)
Forwarders ↪ 2.12
52
class A { def f = 1 } trait T extends A { override def f = 2 } class C extends T
interface T { default int f() { return 2; } }
class C extends A implements T { public int f() { T.super.f(); } }
T and A are unrelated
invokespecial
![Page 53: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/53.jpg)
JUnit 4 💔 Default Methods
53
trait T { @Test def runMe() { .. } } @RunWith(..) class C extends T
// Test C failed: No runnable methods
• -Xmixin-force-forwarders:junit
• Enabled by default
• JUnit 5 will support default methods
![Page 54: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/54.jpg)
Default Methods Perf 🏎• Observation: using default methods degrades
startup performance
• Compiling a simple HelloWorld.scala • Relying on default methods: 3.9s • With mixin forwarders: 2.9s
• Hot performance (sbt) is not affected
54
scala-lang blog, #5429
![Page 55: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/55.jpg)
Mixin Forwarders in RC2
55
trait T { def f = 1 } class C extends T
interface T { default public static int f$(T $this) { return $this.f(); } default public int f() { return 1; } } class C implements T { public int f() { return T.f$(this); } }
![Page 56: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/56.jpg)
JVM and Default Methods• Class Hierarchy Analysis is disabled for default methods
• Prevents inlining in C1, likely other optimizations
• Class loading: populating class vtables with default methods is slow • Search through all ancestors • Mixin forwarders avoid this for classes; 60% speedup
on scala -version • Still a hotspot in generate_default_methods,
when loading interfaces
56
![Page 57: Scala 2.12 Java 8 - Meetupfiles.meetup.com/19040703/bucharest-scala-2016.pdf · • II: Some internals of HotSpot ... Optimizations in HotSpot JVM ! compiler tactics class hierarchy](https://reader034.vdocuments.site/reader034/viewer/2022051509/5acffc527f8b9a1d328dbeb5/html5/thumbnails/57.jpg)
Thank You!
/ 0