Invokedynamic / JSR-292
Upcoming SlideShare
Loading in...5
×

Like this? Share it with your network

Share
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
1,439
On Slideshare
1,439
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
19
Comments
0
Likes
10

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. InvokeDynamic @ytoshima
  • 2. • invokedynamic • Java7 invokedynamic Java VM • • JVM • • Java platform2
  • 3. Program Agenda • JVM to Multi-language VM • Invoke bytecodes • InvokeDynamic • JSR-292 API • Examples3
  • 4. Program Agenda • JVM to Multi-language VM • Invoke bytecodes • InvokeDynamic • JSR-292 API • Examples4
  • 5. JVM to Multi-Language VM Many languages are already available on JVM • Programming languages for Java Virtual Machine • http://www.is-research.de/info/vmlanguages/category/jvm-language/ BeanShell, Clojure, Groovy, JRuby, Mirah, JavaFX, Rhino, Nashorn, Kawa, Smalltalk, Jython, Scala, Ceylon, Kotlin,... •5
  • 6. JVM to Multi-Language VM The Da Vinci Machine Project • a multi-language renaissance for the JVM • http://openjdk.java.net/projects/mlvm/ • mailing list http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev • sub-projects Dynamic Invocation Lightweight method objects Lightweight bytecode loading Interface Injection Continuations and stack introspection Tail calls and tail recursion Tuples and value-oriented types Immediate wrapper types Runtime support for closures Runtime support for multimethods Faster interface invocation Faster reflection Symbolic freedom6
  • 7. JVM to Multi-Language VM JSR-292 • Dynamic Invocation • invokedynamic VM bootstrap • Lightweight method objects • MethodHandle invokedynamic bootstrap CallSite MethodHandle function pointer7
  • 8. JVM to Multi-Language VM JVM Language Summit • VM • http://openjdk.java.net/projects/mlvm/jvmlangsummit/ • Wiki page invokedynamic • http://www.wiki.jvmlangsummit.com/Main_Page • 2011 • http://medianetwork.oracle.com/media/show/16998 - 17017 • 17014 Method Handles and Beyond / John Rose • 17008 JSR 292 Cookbook / Rémi Forax • 17016 Adding invokedynamic Support to JRuby / Charles Nutter8
  • 9. JVM to Multi-Language VM Other resources • JSR-292 Cookbook • http://code.google.com/p/jsr292-cookbook/ • JSR-292 API • https://github.com/headius/invokebinder • MethodHandle • • https://github.com/ytoshima/indy-samples • git clone https://github.com/ytoshima/indy-samples.git9
  • 10. JVM to Multi-Language VM Other resources • JRuby • invokedynamic git clone http://github.com/jruby/jruby.git export JAVA_HOME=<path to jdk7> See cd jruby InvokeDynamicSupport.java ant for bootstrap method bin/jruby --bytecode test/fib.rb implementation : ALOAD 1 INVOKEDYNAMIC getFixnum (Lorg/jruby/runtime/ThreadContext;)Lorg/jruby/RubyFixnum; [org/jruby/runtime/invokedynamic/InvokeDynamicSupport.getFixnumBootstrap(Ljava/lang/ invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;J)Ljava/ lang/invoke/CallSite; (6), 0]10
  • 11. Program Agenda • JVM to Multi-language VM • Invoke bytecodes • InvokeDynamic • JSR-292 API • Examples11
  • 12. Invoke bytecodes Java6 invoke* opcode description 182 0xb6 invokevirtual 183 0xb7 invokespecial private, super.* 184 0xb8 invokestatic 185 0xb9 invokeinterface 186 0xba xxxunusedxxx -> invokedynamic from java7 187 0xbb new http://java.sun.com/docs/books/jvms/second_edition/html/VMSpecTOC.doc.html12
  • 13. Invoke bytecodes invokevirtual -- javap -private -verbose output public static void main(String[] args) {System.out.println("hello");} $ javap -c <class> ... 0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #6; //String hello 5: invokevirtual #7; //Method java/io/PrintStream.println:(Ljava/ lang/String;)V invokevirtual receiver ( this) ( PrintStream) receiver method virtual table invokedynamic13
  • 14. Program Agenda • JVM to Multi-language VM • Invoke bytecodes • InvokeDynamic • JSR-292 API • Examples14
  • 15. InvokeDynamic invokedynamic, MethodHandle • invokedynamic bytecode boot strap method CallSite • CallSite target MethodHandle • MutableCallSite target • MethodHandle bind ( ) • MethodHandle15
  • 16. InvokeDynamic invokedynamic Bootstrap method ... invokedynamic (unlinked) CallSite ... CallSite target 1 CallSite return ... invokedynamic (linked) CallSite target MethodHandle ... • invokedynamic java ASM • http://asm.ow2.org/ asm4 *-asm4 • http://forge.ow2.org/projects/asm/16
  • 17. InvokeDynamic invokedynamic17
  • 18. InvokeDynamic invokedynamic -- javap -private -verbose output invokedynamic javap          0: invokedynamic #22,  0   // InvokeDynamic #0:_:()Ljava/math /BigDecimal; bsm index : name : type          5: areturn // constant pool entry name, type bsm   #21 = NameAndType        #20:#10        //  _:()Ljava/math/BigDecimal;   #22 = InvokeDynamic      #0:#21         //  #0:_:()Ljava/math/BigDecimal; BootstrapMethods: 0: #17 invokestatic DynamicIndyTest.bsm:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/ lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Object;)Ljava/lang/invoke/CallSite; Method arguments: #19 1234567890.123456789018
  • 19. InvokeDynamic ASM 4.0 invokedynamic Link to a Sample import org.objectweb.asm.MethodVisitor; : Class<?> bsmClass = ... // bootstrap method String bsmName = “bsm” // bootstrap method MethodType bsmType = ... // MethodVisitor mv = ... Byte[] // invokedynamic javap mv.visitInvokeDynamicInsn(name /* passed to bsm */, descriptor, /* target method type as string */ new Handle(H_INVOKESTATIC, bsmClass.getName().replace(., /), bsmName, bsmType.toMethodDescriptorString()), bsmArgs);19
  • 20. InvokeDynamic ASM 4.0 invokedynamic • ClassWriter Gen + <N> • MethodVisitor <init> • MethodVisitor invokedynamic static method • MethodType • MethodVisitor visitInvokeDynamicInsn invokedynamic • visitInvokeDynamicInsn Object... bsmArgs Integer, Float, Long, Double, String, Type, Handle20
  • 21. Program Agenda • JVM to Multi-language VM • Invoke bytecodes • InvokeDynamic • JSR-292 API • Examples21
  • 22. JSR-292 API Package java.lang.invoke http://download.oracle.com/javase/7/docs/api/ CallSite MethodHandle target ConstantCallSite target CallSite MethodHandle MethodHandleProxies MethodHandle interface MethodHandles MethodHandle static method MethodHandles.Lookup MethodHandle factory object MethodType MethodHandle MutableCallSite target CallSite SwitchPoint state MH VolatileCallSite target volatile CallSite22
  • 23. JSR-292 API23
  • 24. JSR-292 API // Lookup MethodType mt; MethodHandle mh; MethodHandles.Lookup lookup = MethodHandles.lookup(); // String.class public String replace(char, char) // MethodType mt is (char,char)String mt = MethodType.methodType(/* rtype */ String.class, /* ptype0 */ char.class, /* ptype1 */ char.class); // MethodHandle mh = lookup.findVirtual(/* refc */String.class, "replace", mt); // receiver s = (String) mh.invokeExact("daddy",d,n); // invokeExact(Ljava/lang/String;CC)Ljava/lang/String; // -> “nanny”, same as: “daddy”.replace(‘d’,’n’)24
  • 25. JSR-292 API MethodHandles.Lookup • MethodHandles nested class • findVirtual, findStatic MethodHandle • MethodHandles.lookup() • Lookup object • MethodHandles.publicLookup() • public lookup Lookup object • bootstramp method lookup • invokedynamic Lookup • lookupClass() • lookupModes() (PUBLIC, PROTECTED, ...)25
  • 26. JSR-292 API insertArguments, bindTo import java.lang.invoke.*; public class BindEx { public static void main(String[] main) throws Throwable { MethodHandles.Lookup lookup = MethodHandles.lookup(); MethodHandle mh_replace = lookup.findVirtual(String.class, "replace", MethodType.methodType(String.class, char.class, char.class)); D((String)mh_replace.invokeExact("daddy", d, n) + " // " + mh_replace.type()); D(mh_replace.invoke("daddy", d, n)); MethodHandle mh_bound = mh_replace.bindTo("daddy"); D("mh_bound: " + (String)mh_bound.invokeExact(d, n) + " // " + mh_bound.type()); mh_bound = MethodHandles.insertArguments(mh_replace, 0, "daddy"); D("mh_bound: " + (String)mh_bound.invokeExact(d, n) + " // " + mh_bound.type()); MethodHandle mh_bound_all = MethodHandles.insertArguments(mh_bound, 0, d, n); D((String)mh_bound_all.invokeExact() + " // " + mh_bound_all.type()); } public static void D(Object o) { System.out.println("D: " + o); } }26
  • 27. JSR-292 API insertArguments, bindTo mh_replace (String,char,char)String bindTo mh_bound (char,char)String insertArguments output: mh_bound_all D: nanny // (String,char,char)String ()String D: nanny D: mh_bound: nanny // (char,char)String D: mh_bound: nanny // (char,char)String D: nanny // ()String27
  • 28. JSR-292 API dropArguments: import java.lang.invoke.*; import java.util.*; public class DropEx { public static void main(String[] main) throws Throwable { MethodHandles.Lookup lookup = MethodHandles.lookup(); MethodHandle mh_replace = lookup.findVirtual(String.class, "replace", MethodType.methodType(String.class, char.class, char.class)); MethodHandle mh_drop = MethodHandles.dropArguments(mh_replace, 1, Map.class, Set.class); D("mh_drop: " + (String)mh_drop.invokeExact("daddy", (Map)new HashMap(), (Set)new TreeSet(), d, n) + " // " + mh_drop.type()); D("mh_drop: " + (String)mh_drop.invoke("daddy", new HashMap(), new TreeSet(), d, n) + " // " + mh_drop.type()); } public static void D(Object o) { System.out.println("D: " + o);} }28
  • 29. JSR-292 API dropArguments: mh_replace (String,char,char)String dropArguments mh_drop (String,Map,Set,char,char)String output: D: mh_drop: nanny // (String,Map,Set,char,char)String D: mh_drop: nanny // (String,Map,Set,char,char)String29
  • 30. JSR-292 API asType, asCollector: public class AsCollectorEx { public static void main(String[] args) throws Throwable { Lookup lookup = lookup(); MethodHandle m0 = lookup.findStatic(AsCollectorEx.class, "printAll", methodType(void.class, Object[].class)); P("m0 : " + m0); MethodHandle mcoll = m0.asCollector(Object[].class, 4); mcoll.invoke("Foo", "Bar", "Fizz", "Buzz"); mcoll = mcoll.asType(methodType(void.class, String.class, String.class, String.class, String.class)); P("mcoll: " + mcoll); mcoll.invokeExact("Foo", "Bar", "Fizz", "Buzz"); Object[] params = new Object[] {"Foo", "Bar", "Fizz", "Buzz"}; MethodHandle mspr = mcoll.asSpreader(Object[].class, 4); P("mspr: " + mspr); mspr.invokeExact(params); } public static void printAll(Object[] args) { ... }30
  • 31. JSR-292 API asType, asCollector: m0 mspr (Object[])void (Object[])void asCollector mcoll 1 asSpreader (Object,Object,Object,Object)void output: asType m0 : MethodHandle(Object[])void mcoll 1: MethodHandle(Object,Object,Object,Object)void mcoll 2 (Foo Bar Fizz Buzz ) mcoll 2: MethodHandle(String,String,String,String)void (String,String,String,String)void (Foo Bar Fizz Buzz ) mspr: MethodHandle(Object[])void (Foo Bar Fizz Buzz )31
  • 32. JSR-292 API foldArguments: public class FoldEx { public static void main(String[] main) throws Throwable { Lookup lookup = lookup(); MethodHandle mh_replace = lookup.findVirtual(String.class, "replace", methodType(String.class, char.class, char.class)); MethodHandle mh_hdr = lookup.findStatic(FoldEx.class, "printHeader", methodType(String.class, char.class, char.class)); MethodHandle mh_folded = foldArguments(mh_replace, mh_hdr); D("mh_folded type: " + mh_folded.type()); D("mh_fold call: " + mh_folded.invoke(d, n)); } public static void D(Object o) { System.out.println("D: " + o);} public static String printHeader(char fromC, char toC) { System.out.println("* params: " + fromC + ", " + toC); return "daddy"; }32
  • 33. JSR-292 API foldArguments: target: mh_replace combiner: mh_hdr (String, char, char)String (String, char, char)String foldArguments mh_folded (char,char)String33
  • 34. JSR-292 API filterReturnValue: public class FilterReturnEx { public static void main(String[] main) throws Throwable { Lookup lookup = lookup(); MethodHandle mh_d2s = lookup.findStatic(FilterReturnEx.class, "double2String", methodType(String.class, double.class)); MethodHandle mh_s2bi = lookup.findStatic(FilterReturnEx.class, "string2BigDecimal", methodType(BigDecimal.class, String.class)); MethodHandle mh_filtered = filterReturnValue(mh_d2s, mh_s2bi); D("mh_filtered type: " + mh_filtered.type()); D("mh_filtered call: " + (BigDecimal)mh_filtered.invokeExact(123.456)); } public static String double2String(double dval) { return Double.toString(dval); } public static BigDecimal string2BigDecimal(String str) { return new BigDecimal(str); }34
  • 35. JSR-292 API filterReturnValue: target: mh_d2s rv filter: mh_s2bi (double)String (String)BigDecimal filterReturnValue target String mh_filtered (double)BigDecimal BigDecimal filter35
  • 36. JSR-292 API filterArguments: public class FilterEx { public static void main(String[] main) throws Throwable { MethodHandles.Lookup lookup = MethodHandles.lookup(); MethodHandle mh_domatch = lookup.findStatic(FilterEx.class, "domatch", MethodType.methodType(Matcher.class, String.class, Pattern.class)); MethodHandle mh_getPtn = lookup.findStatic(FilterEx.class, "getPtn", MethodType.methodType(Pattern.class, String.class)); MethodHandle mh_filtered = MethodHandles.filterArguments(mh_domatch, 1, mh_getPtn); D("mh_filtered type: " + mh_filtered.type()); D("mh_filtered call: " + mh_filtered.invoke("daddy", ".*dd.*")); } public static Matcher domatch(String str, Pattern ptn) { Matcher matcher = ptn.matcher(str); if (matcher.matches()) { System.out.println("matched: str: " + str + " ptn: " + ptn); } else { System.out.println("Did not match: str: " + str + " ptn: " + ptn); } return matcher; } public static Pattern getPtn(String sptn) { return Pattern.compile(sptn); }36
  • 37. JSR-292 API filterArguments: target: mh_domatch filters: mh_getPtn [...] (String,Pattern)Matcher (String)Pattern filterArguments mh_filtered target (String,String)Matcher output: D: mh_filtered type: (String,String)Matcher matched: str: daddy ptn: .*dd.* D: mh_filtered call: java.util.regex.Matcher[pattern=.*dd.* region=0,5 lastmatch=daddy]37
  • 38. JSR-292 API guardWithTest: public class GWTEx { public static void main(String[] args) throws Throwable { Lookup lookup = lookup(); MethodHandle test = lookup.findStatic(GWTEx.class, "isString", methodType(boolean.class, Object.class)); MethodHandle target = lookup.findStatic(GWTEx.class, "printString", methodType(void.class, Object.class, long.class)); MethodHandle fallback = lookup.findStatic(GWTEx.class, "printObject", methodType(void.class, Object.class, long.class, long.class)); MethodHandle test1 = dropArguments(test, 1, long.class); MethodHandle fallback1 = insertArguments(fallback, 2, 99); MethodHandle mh = guardWithTest(test1, target, fallback1); mh.invoke("This is a String", -1L); mh.invoke(new Integer(10), -1L); D("test : " + test); D("test1 : " + test1); D("target : " + target); D("fallback : " + fallback); D("fallback1: " + fallback1); D("mh : " + mh); } static boolean isString(Object o) { return (o instanceof String); } static void printString(Object o, long t) { System.out.println("printString: " + (String)o + " t: " + t); } static void printObject(Object o, long t, long t2) { System.out.println("printObject: " + o + " t: " + t + " t2: " + t2); }38
  • 39. JSR-292 API guardWithTest: test target fallback (Object)boolean (Object,long)void (Object,long,long)void dropArguments insertArguments test1 true (Object,long)boolean fallback1 (Object,long)void guardWithTest fallback CallSite false output: false mh printString: This is a String t: -1 printObject: 10 t: -1 t2: 99 (Object,long)void : CallSite39
  • 40. Program Agenda • JVM to Multi-language VM • Invoke bytecodes • InvokeDynamic • JSR-292 API • Examples40
  • 41. Examples Inline Cache Link to the sample • JSR-292 Cookbook inlining-cache • guardWithTest test, target, fallback receiver test true target false fallback • target41
  • 42. Examples invokedynamic (Pet.java main) DynamicIndy dynamicIndy = new DynamicIndy(); MethodHandle mh = dynamicIndy.invokeDynamic("talk", MethodType.methodType(void.class, Object.class), Pet.class, "bsm", MethodType.methodType(CallSite.class, Lookup.class, String.class, MethodType.class, Object.class), "dummy"); Object[] pets = new Object[] {new Cat(), new Dog(), new Cat(), new Dog()}; for (Object pet : pets) { for (int i = 0; i < 4; i++) { mh.invokeExact(pet); } }42
  • 43. Examples bootstrap method public static CallSite bsm(Lookup lookup, String name, MethodType type, Object arg) throws Throwable { D("bsm: type: " + type); InlineCacheCallSite site = new InlineCacheCallSite(lookup, name, type); MethodHandle fallback = FALLBACK_MH.bindTo(site); fallback = fallback.asCollector(Object[].class, type.parameterCount()); D("bsm: fallback: " + fallback); fallback = fallback.asType(type); D("bsm: fallback: " + fallback); site.setTarget(fallback); return site; } // lookup, name, type MutableCallSite // fallback bind CallSite target // fallback CallSite43
  • 44. Examples fallback method public static void fallback(InlineCacheCallSite site, Object[] args) throws Throwable { MethodType type = site.type(); Object receiver = args[0]; Class<?> receiverClass = receiver.getClass(); MethodHandle target = site.lookup.findVirtual(receiverClass, site.name, type.dropParameterTypes(0, 1)); target = target.asType(site.getTarget().type()); MethodHandle test = CHECK_CLASS_MH.bindTo(receiverClass); test = test.asType(test.type().changeParameterType(0, type.parameterType (0))); MethodHandle fallback = FALLBACK_MH.bindTo(site); fallback = fallback.asCollector(Object[].class, type.parameterCount()); fallback = fallback.asType(type); MethodHandle guard = MethodHandles.guardWithTest(test, target, fallback); site.setTarget(guard); target.invokeWithArguments(args); }44
  • 45. Examples test method public static boolean isCachedClass(Class<?> cls, Object receiver) { if (cls != receiver.getClass()) D("isCachedClass false !"); else D("isCachedClass true."); return cls == receiver.getClass(); }45
  • 46. Examples Inline Cache46
  • 47. Examples SwitchPoint example link to the sample • Inline • SwitchPoint guardWithTest target, fallback SwitchPoint valid target invalidate fallback • SwitchPoint invalidate SwitchPoint invalidate47
  • 48. Examples bootstrap method public static CallSite bsm(Lookup lookup, String name, MethodType type, Object arg) throws Throwable { AmethystConstantCallSite site = new AmethystConstantCallSite(type, "site1"); MethodType fallbackType = type.insertParameterTypes(0, AmethystConstantCallSite.class); MethodHandle myFallback = insertArguments( lookup.findStatic(SwitchPointEx.class, "constantFallback",fallbackType), 0, site); site.setTarget(myFallback); return site; }48
  • 49. Examples fallback method public static IAmethystObject constantFallback(AmethystConstantCallSite site, MyThreadContext context) { IAmethystObject value = context.getConstant(site.name()); if (value != null) { MethodHandle valueHandle = constant(IAmethystObject.class, value); valueHandle = dropArguments(valueHandle, 0, MyThreadContext.class); MethodHandle fallback = insertArguments( findStatic(SwitchPointEx.class, "constantFallback", methodType(IAmethystObject.class, AmethystConstantCallSite.class, MyThreadContext.class)), 0, site); SwitchPoint switchPoint = (SwitchPoint)context.runtime.getConstantInvalidator ().getData(); MethodHandle gwt = switchPoint.guardWithTest(valueHandle, fallback); site.setTarget(gwt); } else { D("In constantFallback value=null"); value = new IAmethystObject("(null)"); } return value; }49
  • 50. • % invokedynamic/JSR-292 API • java • Java 8 Closure invokedynamic, MethodHandle50