Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Project Amber

forax
April 07, 2017

Project Amber

What features are coming to Java 10 ?

forax

April 07, 2017
Tweet

More Decks by forax

Other Decks in Programming

Transcript

  1. Project Amber Rémi Forax Devoxx FR - April 2017 Project

    Amber Rémi Forax Devoxx FR - April 2017
  2. Me, myself and I Father – 3 kids Assistant Prof

    – University Paris East Marne la Vallée Developer – OpenJDK, ASM, Pro, etc Expert for the JCP – invokedynamic, lambda, module
  3. Lies lies lies lies lies lies lies lies lies lies

    lies damn lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies lies damn lies lies lies lies lies lies lies lies lies lies lies lies
  4. Project Valhalla OpenJDK project Started July 2014 Two new Features

    – Value types – Generics over primitive and value types
  5. What’s wrong with objects ? Every objects have an header

    – 64 bits (for hotspot) wasted for every objects Arrays of objects are array of references – Cache misses :( Too many references – Too much allocation → Slow the GC
  6. Value types Code like a class, works like an int

    value class complex { private final double re; private final double im; ... } No identity Must be immutable (avoid stack aliasing)
  7. Generics of value types class ArrayList<any E> implements List<E> {

    private E[] elements; ... } List<complex> list= new ArrayList<complex>(); Will work with primitive types too ! List<int> list = new ArrayList<int>();
  8. Value types + Generics Problems :( Bytecode is not ready

    for that ! Specialization of the generic code at runtime ? By the JIT ! Generics over objects still erased for compatibility Wildcards / Boxing List<?> vs List<int> vs List<Integer>
  9. Project Panama Java does not fear C anymore – Make

    the JIT generates the JNI Stub Need metadata to describe – C structs layout in memory – Calling convention Access C heap safely through interfaces
  10. Project Panama The VM is already able to do restricted

    auto- vectorisation of loop over arrays of primitives Add API to access to SIMD/AVX ops – Need to define 128/256/512 bits int/double ? • Use value types (defined by the JDK) – Intrinsics for the VM
  11. Current plan Java 10 – panama C without JNI +

    SIMD/AVX – stealth valhalla: Value types in the VM let JRuby, Groovy, Scala, etc play with it first Java 11 – full valhalla: Value types + Specialized Generics
  12. Project Amber http://openjdk.java.net/projects/amber/ explore and incubate smaller, productivity-oriented language features

    – Local-Variable Type Inference – Enhanced Enums – Lambda Leftovers – ???
  13. Local Variable Type Inference simple var a = 3; var

    list = new ArrayList<String>(); use super type: var anonymous = new Object() { int x; }; not supported: var lambda = x -> x + 2; var ref = String::length;
  14. Enhanced Enum Generics in enum enum ChronoField<X extends IntValueish> {

    YEAR<Year>, MONTH<Month>, DAY_OF_MONTH<Integer>, DAY_OF_WEEK<DayOfWeek>, } Frankenstenum in my opinion
  15. Lambda leftovers ‘_’ means unused parameter Map<String, Set<String>> map =

    ... map.computeIfAbsent(key, _ - > new HashSet<>()) .add(value); Lambda parameters open a new scope map.merge(key, value, (old, value) - > old + value); Better inference – Fix cases where overloading is obvious for a human
  16. Example { or [{ "username": "remi", "user": "remi", ... ...

    } }, ... v1 v2 Extracting a user name from a JSON document
  17. If instanceof … { or [{ "username": "remi", "user": "remi",

    ... ... } }, ... Object json = ... if (json instanceof JSObject) { return ((JSObject)json).getValue("username"); } if (json instanceof JSArray) { return ((JSArray)json).get(0).getValue("user"); } ...
  18. Enhanced Switch Switch on types Object json = ... switch(json)

    { case JSObject: return ((JSObject)json).getValue("username"); case JSArray: return ((JSArray)json).get(0).getValue("user"); default: ... }
  19. Smart cast / type flow Fuse instanceof/cast + declare a

    variable Object json = ... return switch(json) { case JSObject object: return return object.getValue("username"); case JSArray array: return array.get(0).getValue("user"); default: ... };
  20. Pattern Matching with Expression “break” is so 1970 ! Object

    json = ... return switch(json) { case JSObject object -> object.getValue("username") case JSArray array -> array.get(0).getValue("user") default: ... };
  21. Default ? We need a default because ... Object json

    = ... return switch(json) { case JSObject object -> object.getValue("username") case JSArray array -> array.get(0).getValue("user") default: ... };
  22. Algebraic Data Type Enumerate allowed subtypes /* closed */ interface

    Expr { data Value(int x) data Add(Expr left, Expr right) } 2 + (3 + 5) new Add(new Value(2), new Add(…, …)) or Add(Value(2), Add(Value(3), Value(5)))
  23. Data Class data Point(int x, int y); Provide a way

    to represent ‘dumb’ data – Abstraction ‘it’s a data class’ – Less boiler plate Generate (at runtime ?) – equals, hashCode, toString, getters ? – Value types also need that too !
  24. Destructured Pattern Matching Data class fields can be extracted public

    Expr simplify(Expr expr) { return switch(expr) { case Add(e1, e2) -> ... case Value(value) -> ... }; } Look ‘ma, no default
  25. Destructured Pattern Matching Match part of the subtree public Expr

    simplify(Expr expr) { return switch(expr) { case Add(Value(v1), Value(v2)) -> ... case Add(e1, e2) -> ... case Value(value) -> ... }; }
  26. Destructured Pattern Matching With the implementations public Expr simplify(Expr expr)

    { return switch(expr) { case Add(Value(v1), Value(v2)) -> new Value(v1 + v2)) case Add(e1, e2) -> simplify(...) case Value value -> value }; }
  27. ‘_’ means unused/anything Use _ in pattern return switch(expr) {

    case Add(Value(_), Value(v2)) -> case Add(_, _) -> case Value _ -> };
  28. Destructured Pattern Matching You can not change a local variable

    ! public Expr simplify(Expr expr) { return switch(expr) { case Add(Value(v1), Value(v2)) -> new Value(v1 + v2)) case Add(e1, e2) -> simplify(...) case Value _ -> expr }; } Use of local variable (non final)
  29. Destructured vs Encapsulation return switch(expr) { case Add(Value(v1), Value(v2)) ->

    ... ... }; if (expr instanceof Add) { Add add = (Add)expr; Expr left = add.getLeft(); if (left instanceof Value) { Value v1 = (Value)left; … } } /* data */ class Add { private final Expr left; private final Expr right; ... public Expr getLeft() { return left; } public Expr getRight() { return right; } }
  30. De-constructor ? return switch(expr) { case Add(Value(v1), Value(v2)) -> ...

    ... }; if (expr instanceof Add) { Add add = (Add)expr; Expr left, right = add.deconstructor(); if (left instanceof Value) { Value v1 = (Value)left; … } } /* data */ class Add { private final Expr left; private final Expr right; ... public Expr, Expr deconstructor() { return left, right; } ...
  31. Implementation Troubles Problems – If instanceof … else – Sharing

    – De-constructor / Scala unapply – Zero allocation Goal Pattern matching on types <=> as fast as method calls ?
  32. If instanceof … else instanceof == dynamic suite of typechecks

    – Instanceof itself creates a series of if … else Linearly checks all patterns is slooooooow
  33. Use invokedynamic The recipe is an array of pairs Pattern

    / Action • A text transformed as an automata at runtime • Action: a static method to call if the pattern match No instanceof guardWithTest is a typecheck on runtime classes
  34. And switch with statements ? If limited to switch on

    types, use the double switch trick ! String s; int index = invokedynamic(expr); recipe […] switch(index) { case 0: s = "JSObject"; break; case 1: s = "JSArray"; break; default: s = "other"; } return s;
  35. Sharing Some patterns starts with the same pattern Several classes

    may match the same pattern switch(expr) { case IAdd(IValue(v1), IValue(v2)) -> ... case IAdd(e1, e2) - > ... IAdd IValue IValue extract expr v1 v2 action1 action2
  36. At runtime (1/2) switch(expr) { case IAdd(IValue(v1), IValue(v2)) -> ...

    case IAdd(e1, e2) - > ... IAdd IValue IValue extract expr v1 v2 action1 action2 Add Add Value Value Value Add extract Add v1 action2
  37. At runtime (2/2) switch(expr) { case IAdd(IValue(v1), IValue(v2)) -> ...

    case IAdd(e1, e2) - > ... IAdd IValue IValue extract expr v1 v2 action1 action2 Add Value Value Add extract Add v1 action2 Value v1 action1 Value v2
  38. Guard or map ? switch(expr) { case IAdd(IValue(v1), IValue(v2)) ->

    ... case IAdd(e1, e2) - > … At Runtime, we construct Add extract Add v1 action2 Value v1 action1 Value v2 After N guards, use java.lang.ClassValue instead
  39. De-constructor / unapply Scala unapply is slow (Tuple and Optional

    are objects) /* data */ class Add { private final Expr left; private final Expr right; ... public Optional<Tuple<Expr, Expr>> unapply() { return Some((left, right)); } } Extract the values => 2 object creations
  40. Idea ! Create only one object for the whole pattern

    expr == Add(Value(v1), Value(v2)) <=> var foo = new $Foo$(); (expr as Add).deconstructor(foo::args1, foo::args2); (foo.args1 as Value).deconstructor(foo:args3); (foo args2 as Value).deconstructor(foo::args4); action(args3, args4); /* runtime */ class $Foo$ { Expr arg1; Expr arg2; int arg3; int arg4; } args1 args2 args3 args4
  41. Magic ! Avoid the creation of the $Foo$ object, with

    the help of the VM Reify the stackframe as an object var frame = StackFrame.alloc(LExpr;LExpr;II) add.deconstructor(frame.refAt(0), frame.refAt(1)); … action.invokeWithStackFrame(frame, 2); John Rose starts a prototype :)
  42. Java 10 – Speculative planning Panama Stealh Valhalla – Value

    types in the VM Amber – A lot of small improvements – Pattern Matching
  43. Pizza Java + generics + lambdas + pattern matching Generics

    → Java 5 Lambdas → Java 8 Pattern Matching → Java 10 ??