Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

JDK7: Improved support for dynamic languages

3,400 views

Published on

Presented at J-Fall 2009 conference.

Published in: Technology, News & Politics
  • Be the first to comment

JDK7: Improved support for dynamic languages

  1. 1. JDK7: Improved support for dynamic languages Sander Mak Info Support Wednesday, November 11, 2009
  2. 2. Overview • JVM Languages • Problems for dynamic languages • MLVM: Multi Language Virtual Machine • Method handles • Invokedynamic • Wrap-up Wednesday, November 11, 2009
  3. 3. The Java Platform The JVM has become a complex beast... 1.0 1996 1.1 1.2 1.3 1.4 1.5 1.6 2009 • Performance • Binary compatibility • Safety • Platform independence Wednesday, November 11, 2009
  4. 4. The Java Platform Wednesday, November 11, 2009
  5. 5. The Java Platform Java language JVM Java libraries Wednesday, November 11, 2009
  6. 6. The Java Platform • More expressiveness: – ‘Pure’ OO Java JRuby – Blocks/Closures/ Scala JVM Higher order functions Groovy – Dynamic typing Clojure – Metaprogramming JavaFX Java libraries • Proven VM • Interop with Java ‘legacy’ Wednesday, November 11, 2009
  7. 7. JVM Languages Java Wednesday, November 11, 2009
  8. 8. JVM Languages Groovy Clojure JRuby Java JavaFX Scala Wednesday, November 11, 2009
  9. 9. JVM Languages jProlog Pizza MultiJava Fan JLog Groovy Clojure MetaJ JRuby Java JavaFX Jaskell Rhino Scala JBasic Aardappel Funnel Jacl Drools Jython Wednesday, November 11, 2009
  10. 10. JVM Languages 240+ Languages Wednesday, November 11, 2009
  11. 11. JVM Languages ‘Language fictions’ JVM Exceptions Primitive types Objects Access control Garbage coll. Threading Memory model Wednesday, November 11, 2009
  12. 12. JVM Languages ‘Language fictions’ Java Enums Checked exc. JVM Generics Exceptions Exceptions Primitive types Primitive types Objects Objects Access control Access control Garbage coll. Garbage coll. Threading Threading. Memory model Memory model Wednesday, November 11, 2009
  13. 13. JVM Languages JRuby ‘Language Open classes Dynamic typing fictions’ Java Closures Enums Enums Checked exc. Checked exc. JVM Generics Generics Exceptions Exceptions Exceptions Primitive types Primitive types Primitive types Objects Objects Objects Access control Access control Access control Garbage coll. Garbage coll. Garbage coll. Threading Threading. Threading Memory model Memory model Memory model Wednesday, November 11, 2009
  14. 14. JVM Languages JRuby ‘Language Open classes Dynamic typing fictions’ Java Closures Enums Enums Checked exc. Checked exc. JVM Generics Generics Exceptions Exceptions Exceptions Primitive types Primitive types Primitive types Objects Objects Objects Access control Access control Access control Garbage coll. Garbage coll. Garbage coll. Threading Threading. Threading Memory model Memory model Memory model Wednesday, November 11, 2009
  15. 15. Compiling dynamic languages Performance Smaller = better for Java Wednesday, November 11, 2009
  16. 16. Compiling dynamic languages Performance (in fairness: JRuby compares well to Ruby) Smaller = better for JRuby Wednesday, November 11, 2009
  17. 17. Compiling dynamic languages First: statically typed Java Java public class Test { public static void main(String[] args) { ArrayList<String> names = new ArrayList<String>(); names.add("John"); names.add("Pete"); Collections.sort(names); } } Wednesday, November 11, 2009
  18. 18. Compiling dynamic languages Java public class Test { public static void main(String[] args) { ArrayList<String> names = new ArrayList<String>(); names.add("John"); names.add("Pete"); Collections.sort(names); } } Wednesday, November 11, 2009
  19. 19. Compiling dynamic languages Where are the types? Bytecode 0: new #2; //class java/util/ArrayList 3: dup 4: invokespecial #3; //Method java/util/ArrayList."<init>":()V 7: astore_1 8: aload_1 9: ldc #4; //String John 11: invokevirtual #5; //Method java/util/ArrayList.add:(Ljava/lang/ Object;)Z 14: pop 15: aload_1 16: ldc #6; //String Pete 18: invokevirtual #5; //Method java/util/ArrayList.add:(Ljava/lang/ Object;)Z 21: pop 22: aload_1 23: invokestatic #7; //Method java/util/Collections.sort:(Ljava/util/ List;)V 26: return Wednesday, November 11, 2009
  20. 20. Compiling dynamic languages At the callsites! Bytecode 0: new #2; //class java/util/ArrayList 3: dup 4: invokespecial #3; //Method java/util/ArrayList."<init>":()V 7: astore_1 8: aload_1 9: ldc #4; //String John 11: invokevirtual #5; //Method java/util/ArrayList.add:(Ljava/lang/ Object;)Z 14: pop 15: aload_1 16: ldc #6; //String Pete 18: invokevirtual #5; //Method java/util/ArrayList.add:(Ljava/lang/ Object;)Z 21: pop 22: aload_1 23: invokestatic #7; //Method java/util/Collections.sort:(Ljava/util/ List;)V 26: return Wednesday, November 11, 2009
  21. 21. Compiling dynamic languages At the callsites!in JVM Invocation Bytecode Bytecode Example 0: new #2; //class java/util/ArrayList 3: dupinvokestatic Collections.sort(list) 4: invokespecial #3; //Method java/util/ArrayList."<init>":()V 7: astore_1 invokevirtual list.add(element) list :: java.util.ArrayList 8: aload_1 9: ldc #4; //String John invokeinterface list.add(element) list :: java.util.List 11: invokevirtual #5; //Method java/util/ArrayList.add:(Ljava/lang/ Object;)Z invokespecial constructor call, i.e.: new ArrayList() 14: pop 15: aload_1 16: ldc #6; //String Pete 18: invokevirtual #5; //Method java/util/ArrayList.add:(Ljava/lang/ Object;)Z 21: pop 22: aload_1 23: invokestatic #7; //Method java/util/Collections.sort:(Ljava/util/ List;)V 26: return Wednesday, November 11, 2009
  22. 22. Compiling dynamic languages • JVM ‘more dynamic’ than Java • Exception: method calls – Signature at callsite must match exactly TargetClass Name Method descriptor 18: invokevirtual #5; //Method java/util/ArrayList.add:(Ljava/lang/Object;)Z – Dispatch on static type of call and dynamic type of receiver – Method must exist at compile time – Link to target is fixed, no relinking Wednesday, November 11, 2009
  23. 23. Compiling dynamic languages Again, where are the types? JRuby names = ["John", "Pete"] puts names.sort • Type inference not feasible • Types may be constructed @ runtime • Types may change @ runtime • Invocation of closures constructed @ runtime Wednesday, November 11, 2009
  24. 24. Compiling dynamic languages Compiling 2 lines of JRuby ... ... yields >80 bytecode instructions Bytecode public class Test_dot_ruby extends org/jruby/ast/executable/AbstractScript { public <init>()V ANEWARRAY org/jruby/runtime/CallSite ICONST_1 LDC "sort" INVOKESTATIC Test_dot_ruby.setCallSite ([Lorg/jruby/runtime/CallSite;ILjava/lang/String;)[Lorg/jruby/ runtime/CallSite; ICONST_0 LDC "puts" INVOKESTATIC Test_dot_ruby.setFunctionalCallSite ([Lorg/jruby/runtime/CallSite;ILjava/lang/String;) [Lorg/jruby/runtime/CallSite; PUTFIELD Test_dot_ruby.callSites : [Lorg/jruby/runtime/CallSite; ALOAD 0 ICONST_2 INVOKEVIRTUAL Test_dot_ruby.initStrings (I)[Lorg/jruby/util/ByteList; LDC 1 LDC "Pete" INVOKESTATIC org/jruby/ast/executable/AbstractScript.createByteList ([Lorg/jruby/util/ByteList;ILjava/ Wednesday, November 11, 2009
  25. 25. Compiling dynamic languages Compiling 2 lines of JRuby ... details Method call ... yields >80 bytecode instructions Lorg/jruby/runtime/builtin/IRubyObject Bytecode LDC “sort” public class Test_dot_ruby extends org/jruby/ast/executable/AbstractScript { INVOKESTATIC Test_dot_ruby.setCallSite ... public <init>()V ANEWARRAY org/jruby/runtime/CallSite ICONST_1INVOKEVIRTUAL org/jruby/runtime/CallSite.call LDC "sort" ... INVOKESTATIC Test_dot_ruby.setCallSite ([Lorg/jruby/runtime/CallSite;ILjava/lang/String;)[Lorg/jruby/ runtime/CallSite; ICONST_0 ‘Fat call paths’ LDC "puts" INVOKESTATIC Test_dot_ruby.setFunctionalCallSite ([Lorg/jruby/runtime/CallSite;ILjava/lang/String;) [Lorg/jruby/runtime/CallSite; PUTFIELD Test_dot_ruby.callSites : [Lorg/jruby/runtime/CallSite; ALOAD 0 ICONST_2 INVOKEVIRTUAL Test_dot_ruby.initStrings (I)[Lorg/jruby/util/ByteList; LDC 1 LDC "Pete" INVOKESTATIC org/jruby/ast/executable/AbstractScript.createByteList ([Lorg/jruby/util/ByteList;ILjava/ Wednesday, November 11, 2009
  26. 26. Compiling dynamic languages • Common solutions: - Don’t compile, interpret (sometimes unavoidable) - AOT compilation into specialized invoker classes (suitable for core methods) - AOT compilation, then use reflection (for user defined types) - JIT bytecode generation of small stub methods Either way: abundance of synthetic types and bytecode hard to optimize for JVM Wednesday, November 11, 2009
  27. 27. MLVM • Change of direction @ Sun – Introduction of JavaFX – Fortress language – Officially supporting JRuby – Open sourcing JDK (compiler & VM) • Still, JVM remains Java-centric • Enter: the MLVM and JSR-292 Multi Language VM Da Vinci Machine Wednesday, November 11, 2009
  28. 28. MLVM John Rose @ Sun: Language implementers know what they want   (and know how to simulate it with 100x slowdown)   VM implementers know what VMs can do   (and know how to make their favorite language sing) Let's bring them together. (JSR 292 ‘invokedynamic’) Wednesday, November 11, 2009
  29. 29. JSR-292 So what do dynamic languages want? Binding Marker Delay binding as long Indicate in bytecode as possible. Hide that a dynamic call exact destination of should be made call @ compiletime Adaptation Language should be able to implement its own coercion rules when matching type signatures Wednesday, November 11, 2009
  30. 30. Method handles • Lightweight, safe method pointers • Like java.lang.reflect.Method, but: – No argument boxing/unboxing – Access checks only at creation time – Leaner, and as fast as direct call – No wrapping of exceptions Wednesday, November 11, 2009
  31. 31. Method handles • Lightweight, safe method pointers • Like java.lang.reflect.Method, but: – No argument boxing/unboxing – Access checks only at creation time – Leaner, and as fast as direct call – No wrapping of exceptions Java 7 MethodHandle mh = MethodHandles.lookup().findStatic( Enclosing.class, “methodName”, MethodType.make(String.class, int.class, String.class) ) mh.<String>invoke(1, “2”) Wednesday, November 11, 2009
  32. 32. Method handles • Lightweight, safe method pointers • Like java.lang.reflect.Method, but: – No argument boxing/unboxing – Access checks only at creation time – Leaner, and as fast as direct call – No wrapping of exceptions Bytecode 59: aload 4 61: invokevirtual #11; //Method java/dyn/MethodHandle.invoke:(I;Ljava/ lang/String;)Ljava/lang/String Wednesday, November 11, 2009
  33. 33. Method handles • Instance methods: first arg is receiver Wednesday, November 11, 2009
  34. 34. Method handles • Instance methods: first arg is receiver Java 7 MethodHandle mh = MethodHandles.lookup().findVirtual( Enclosing.class, “methodName”, MethodType.make(String.class, int.class, String.class) ) mh.<String>invoke(receiver, 1, “2”) • Receiver may be pre-bound to MH • Faster than normal ‘invokevirtual’! • Method Handles prepare for closures... Wednesday, November 11, 2009
  35. 35. Method handles • Immutable: MH has one function type • Signature polymorphism for invoke • Can be composed and/or adapted: – Add or drop arguments – Guard with test – Convert arguments JVM ‘knows’ Method Handles: • Can inline (chains of) method handles Wednesday, November 11, 2009
  36. 36. Method handles • Immutable: MH has one function type MH Chain example: Test MH • Signature polymorphism for invoke Guard Originalcomposed and/or adapted: • Can be Insert with Success MH MH arg. test – Add or drop arguments – Guard with test Fallback MH mh.invoke(..) – Convert arguments JVM ‘knows’ Method Handles: • Can inline (chains of) method handles Wednesday, November 11, 2009
  37. 37. Anonymous classloading Create unnamed classes from byte[] • Garbage collectible Class not in system dictionary, Class.forName() won’t work • Inherit access & security from host Host class is caller of Anon. classloader • Create patchable template classes Specialize classes by patching constant pool @ loadtime Vastly improves runtime code generation Wednesday, November 11, 2009
  38. 38. Anonymous classloading Java 7 Create unnamed classes from byte[] MethodType methodType = MethodType.make(int.class, • Garbage collectible int.class, int.class); Class not in system dictionary, Class.forName() won’t work ExprBuilder builder = new ExprBuilder(methodType); • Inherit access & security from host Var a = builder.parameter(0); Var b = builder.parameter(1); Host class is caller of Anon. classloader builder. • Create patchable template classes load(a). load(b). Specialize classes by patching constant pool @ loadtime add(); MethodHandle mh = builder.createMethodHandle(Main.class); Vastly improves runtime code generation System.out.println(mh.invoke(2, 3)); Wednesday, November 11, 2009
  39. 39. Anonymous classloading Java 7 Create unnamed classes from byte[] MethodType methodType = MethodType.make(int.class, • Garbage collectible int.class, int.class); Class not in system dictionary, Class.forName() won’t work ExprBuilder builder = new ExprBuilder(methodType); • Inherit access & security from host Var a = builder.parameter(0); Var b = builder.parameter(1); Host class is caller of Anon. classloader builder. • Create patchable template classes load(a). load(b). Specialize classes by patching constant pool @ loadtime add(); MethodHandle mh = builder.createMethodHandle(Main.class); Vastly improves runtime code generation System.out.println(mh.invoke(2, 3)); Wednesday, November 11, 2009
  40. 40. Anonymous classloading Java 7 Create unnamed classes from byte[] MethodType methodType = MethodType.make(int.class, • Garbage collectible int.class, int.class); Class not in system dictionary, Class.forName() won’t work ExprBuilder builder = new ExprBuilder(methodType); • Inherit access & security from host Var a = builder.parameter(0); Var b = builder.parameter(1); Host class is caller of Anon. classloader builder. • Create patchable template classes load(a). load(b). Specialize classes by patching constant pool @ loadtime add(); MethodHandle mh = builder.createMethodHandle(Main.class); Vastly improves runtime code generation System.out.println(mh.invoke(2, 3)); Wednesday, November 11, 2009
  41. 41. JSR-292 So what do dynamic languages want? Binding Marker Delay binding as long Indicate in bytecode as possible. Hide that a dynamic call exact destination of should be made call @ compiletime Adaptation Language should be able to implement its own coercion rules when matching type signatures Wednesday, November 11, 2009
  42. 42. JSR-292 So what do dynamic languages want? Adaptation MH can be chained to add Language should be able to implement its custom conversion rules own coercion rules when matching type signatures Argument list can be adjusted Wednesday, November 11, 2009
  43. 43. JSR-292 So what do dynamic languages want? Binding MH is a flexible, adaptable Delay binding as long as possible. Hide pointer to methods exact destination of call @ compiletime Invocation overhead low Invocation binds directly to single method handle Wednesday, November 11, 2009
  44. 44. Invokedynamic New bytecode, last piece of JSR-292 puzzle: Name Method descriptor 18: invokedynamic #5; //NameAndType addInts:(II)I • Invocation without reference to actual method descriptor • Instead, symbolic name and type • No receiver: all arguments are equal What is the target? Wednesday, November 11, 2009
  45. 45. Invokedynamic - bootstrap Bootstrap method receives dynamic calls Java 7 static { Linkage.registerBootstrapMethod( "bootstrapID"); } static CallSite bootstrapID(Class<?> callerClass, String methodName, MethodType methodType) { MethodHandle target = .. CallSite site = new CallSite(callerClass, methodName, methodType); site.setTarget(target); return site; } Wednesday, November 11, 2009
  46. 46. Invokedynamic - bootstrap Bootstrap method receives dynamic calls Java 7 static { Linkage.registerBootstrapMethod( "bootstrapID"); } static CallSite bootstrapID(Class<?> callerClass, String methodName, MethodType methodType) { MethodHandle target = .. CallSite site = new CallSite(callerClass, methodName, methodType); site.setTarget(target); return site; } Wednesday, November 11, 2009
  47. 47. Invokedynamic - bootstrap Bootstrap method receives dynamic calls Java 7 static { Linkage.registerBootstrapMethod( "bootstrapID"); } static CallSite bootstrapID(Class<?> callerClass, String methodName, MethodType methodType) { MethodHandle target = .. CallSite site = new CallSite(callerClass, methodName, methodType); site.setTarget(target); return site; } Wednesday, November 11, 2009
  48. 48. Invokedynamic - bootstrap Bootstrap method receives dynamic calls Java 7 static { Linkage.registerBootstrapMethod( "bootstrapID"); } static CallSite bootstrapID(Class<?> callerClass, String methodName, MethodType methodType) { MethodHandle target = .. CallSite site = new CallSite(callerClass, methodName, methodType); site.setTarget(target); return site; } Wednesday, November 11, 2009
  49. 49. Invokedynamic - bootstrap • CallSite immutable, except for target • After installing target, invokedynamic invokes MH directly DynamicInvokerClass ImplementationClass aload_1; invokedyn. meth:Type; implementation(Type) { return; result = .. return result } bootstrap( .. ) { ..lookup.. return CallSite } Wednesday, November 11, 2009
  50. 50. Invokedynamic - bootstrap • CallSite immutable, except for target • After installing target, invokedynamic invokes MH directly DynamicInvokerClass ImplementationClass aload_1; invokedyn. meth:Type; implementation(Type) { return; result = .. return result } bootstrap( .. ) { ..lookup.. return CallSite } Wednesday, November 11, 2009
  51. 51. Invokedynamic - bootstrap • CallSite immutable, except for target • After installing target, invokedynamic invokes MH directly DynamicInvokerClass ImplementationClass aload_1; invokedyn. meth:Type; implementation(Type) { return; result = .. return result } bootstrap( .. ) { ..lookup.. return CallSite } Wednesday, November 11, 2009
  52. 52. Invokedynamic - bootstrap • CallSite immutable, except for target • After installing target, invokedynamic invokes MH directly DynamicInvokerClass ImplementationClass aload_1; invokedyn. meth:Type; implementation(Type) { return; result = .. return result CallSite is } bootstrap( .. ) { sub-classable ..lookup.. return CallSite MH can be guarded } with test Wednesday, November 11, 2009
  53. 53. Invokedynamic - bootstrap • CallSite immutable, except for target • After installing target, invokedynamic invokes MH directly DynamicInvokerClass ImplementationClass aload_1; invokedyn. meth:Type; Method implementation(Type) { return; Handle(s) result = .. return result } CallSite target bootstrap( .. ) { may be changed ..lookup.. return CallSite later! } Wednesday, November 11, 2009
  54. 54. Project coin: JSR-292 syntax Java 7 import java.dyn.*; public class HelloSimple { public static void main(String... args) { greeter.<void>invoke(args[0]); // Direct MH InvokeDynamic.sayIt(args[0]); // invokedynamic } public static void greeter(String x) { .. println } static MethodHandle greeter = MethodHandles.lookup().findStatic( Hello.class, "greeter", MethodType.make(void.class, String.class)); // bootstrap: link “sayIt” to greeter MH Wednesday, November 11, 2009
  55. 55. Project coin: JSR-292 syntax Java 7 import java.dyn.*; public class HelloSimple { public static void main(String... args) { greeter.<void>invoke(args[0]); // Direct MH InvokeDynamic.sayIt(args[0]); // invokedynamic } public static void greeter(String x) { .. println } static MethodHandle greeter = MethodHandles.lookup().findStatic( Hello.class, "greeter", MethodType.make(void.class, String.class)); // bootstrap: link “sayIt” to greeter MH Wednesday, November 11, 2009
  56. 56. Project coin: JSR-292 syntax Java 7 import java.dyn.*; public class HelloSimple { public static void main(String... args) { greeter.<void>invoke(args[0]); // Direct MH InvokeDynamic.sayIt(args[0]); // invokedynamic } public static void greeter(String x) { .. println } static MethodHandle greeter = MethodHandles.lookup().findStatic( Hello.class, "greeter", MethodType.make(void.class, String.class)); // bootstrap: link “sayIt” to greeter MH Wednesday, November 11, 2009
  57. 57. Invokedynamic • Invokedynamic + bootstrap method allow language to up-call from VM to custom code for linking/calling. Not impossible before, but hard and slow. JVM now fully optimizes dynamic calls. Wednesday, November 11, 2009
  58. 58. JSR-292 So what do dynamic languages want? Binding Marker Delay binding as long Indicate in bytecode as possible. Hide that a dynamic call exact destination of should be made call @ compiletime Adaptation Language should be able to implement its own coercion rules when matching type signatures Wednesday, November 11, 2009
  59. 59. JSR-292 So what do dynamic languages want? Marker invokedynamic bytecode Indicate in bytecode that a dynamic call should be made Binding bootstrap mechanism and Delay binding as long as possible. Hide method handles exact destination of call @ compiletime Wednesday, November 11, 2009
  60. 60. Wrap-up • JSR-292 invokedynamic features: – Language implementors can avoid tricks – Level the playing ground, speedwise – Allow existing VM optimizations to be applied to new paradigms • JSR292/invokedynamic will be backported Wednesday, November 11, 2009
  61. 61. Wrap-up • JRuby, Groovy actively working on JSR-292 support • For example, JRuby can cut 80% of linking/calling code in runtime • Unfortunately no real benchmarks, but: – Surinx preliminary testing: up to 5-fold increase on naive fibonacci testcase • JDK7 due 1st quarter 2010 Wednesday, November 11, 2009
  62. 62. Questions Wednesday, November 11, 2009

×