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

Invokedynamic: Tales from the Trenches

headius
February 03, 2013

Invokedynamic: Tales from the Trenches

Talk on the history of JRuby and invokedynamic given at FOSDEM 2013.

headius

February 03, 2013
Tweet

More Decks by headius

Other Decks in Programming

Transcript

  1. Me • Charles Oliver Nutter • Programmer my whole life

    • Professional Java since 1996 • [email protected], @headius • “Full time” JRuby guy • Sun (06-09), Engine Yard (09-12), Red Hat Sunday, February 3, 13
  2. invokedynamic 101 • invokevirtual, invokestatic, etc • Predefined behavior •

    Based on simple VM primitives • invokedynamic • User-defined bytecode • Primitives available as an IR Sunday, February 3, 13
  3. invokedynamic 101 • Emit invokedynamic bytecode • Name + signature

    + bootstrap pointer • On first call, bootstrap called • Name + signature + lookup context • Return a CallSite • Subsequent calls go through CallSite Sunday, February 3, 13
  4. Terminology • Invokedynamic: bytecode or JSR 292 • Call site:

    place in code where a call is made • Bootstrap: method called to set up indy call site Sunday, February 3, 13
  5. Terminology • Method handle: endpoint (call, field, ...) or logic

    (branches, arg manip, ...) to wrap an endpoint handle • Guard: logic to ensure site is bound to the proper target • GWT: guard-with-test, branch based on user test • SwitchPoint: on-until-off branch handle Sunday, February 3, 13
  6. Promises • “invokedynamic should be no slower than invokeinterface” •

    “all Hotspot optimizations should apply through indy sites” • “SwitchPoint should be ‘free’ when valid” Sunday, February 3, 13
  7. Promises • “JRuby plus invokedynamic will be fast” • “The

    fully-working optimized OpenJDK indy impl is just around the corner” Sunday, February 3, 13
  8. 2006 • Tom Enebo and I join Sun Microsystems •

    Working on JRuby full time • Dream come true! • Sun officially starts promoting JVM as a multi-language platform • Needed some work to get there... Sunday, February 3, 13
  9. 2007 • Talks start between JRuby and John Rose •

    How does JRuby work? • What do we need? • JSR 292 restarts with John Rose leading • Not much to see yet Sunday, February 3, 13
  10. 2008 • Early design work in JSR • Ola Bini

    represented JRuby • Few working builds • John Rose private builds • Multi-Language VM (Da Vinci) later on • We banked on the future Sunday, February 3, 13
  11. JRuby 1.1.5 • First version with indy support • Based

    on early proposal • invokeinterface on java.dyn.Dynamic • Dynamic type treated specially • Manual bootstrap setup • Worked...sorta Sunday, February 3, 13
  12. java.dyn.Dynamic public java.lang.Object doDynamicCall(java.lang.Object); Code: 0: aload_1 1: invokeinterface #3;

    //Method java/dyn/Dynamic.myDynamicMethod:()V 4: areturn Sunday, February 3, 13
  13. 2009 • Continuing evolution of JSR 292 • We tracked

    design changes • Performance work deferred • We kept up the faith :-) • First RI rev lands Sunday, February 3, 13
  14. Running on What? • Still no standard builds for OS

    X • MLVM repo • Based on bsd-port • External, periodic dump of indy work • Incubator for other projects • Henri Gomez: openjdk-osx-build Sunday, February 3, 13
  15. 2009-04-21; 6655646: dynamic languages need dynamically linked call sites Summary:

    invokedynamic instruction (JSR 292 RI) 2009-07-21; 6862576: vmIntrinsics needs cleanup in order to support JSR 292 intrinsics Summary: remove useless lazy evaluation of intrinsics; add LAST_COMPILER_INLINE to help categorize them 2009-09-15; 6863023: need non-perm oops in code cache for JSR 292 Summary: Make a special root-list for those few nmethods which might contain non-perm oops. 2009-12-16; 6829192: JSR 292 needs to support 64-bit x86 Summary: changes for method handles and invokedynamic hotspot Sunday, February 3, 13
  16. 2009-05-05; 6829144: JSR 292 JVM features need a provisional Java

    API Summary: JDK API and runtime (partial) for anonk, meth, indy 2009-10-21; 6891770: JSR 292 API needs initial unit tests Summary: backport working mlvm regression test to M3 implementation of JSR 292; requires jtreg 4.1 jdk Sunday, February 3, 13
  17. Meanwhile... • Mirah: statically-typed, Ruby-like language • Because why not

    • Local type inference • No runtime library • .java and .class backends • Way more interest than I expected... Sunday, February 3, 13
  18. What If This... public class Foo { private int a;

    public Foo(int a) { this.a = a; } public void show() { System.out.println(a); } } Sunday, February 3, 13
  19. ...Could Be This class Foo def initialize(a) @a = a

    end def show puts @a end end Sunday, February 3, 13
  20. Mirah class Foo def initialize(a:int) @a = a end def

    show puts @a end end Sunday, February 3, 13
  21. Mirah class Foo def initialize(a:dynamic) @a = a end def

    show puts @a end end Sunday, February 3, 13
  22. 2010 • Performance work starts a bit • Back and

    forth with Hotspot team • Testing JRuby, dumping assembly • Things start to look promising • Inlining thresholds biggest issue Sunday, February 3, 13
  23. 2010-01-05; 6829187: compiler optimizations required for JSR 292 2010-01-13; 6912065:

    final fields in objects need to support inlining optimizations for JSR 292 2010-01-29; 6917766: JSR 292 needs its own deopt handler 2010-02-01; 6921352: JSR 292 needs its own deopt handler 2010-02-01; 6921799: JSR 292 call sites should not be fixed-up 2010-02-23; 6928839: JSR 292 typo in x86 _adapter_check_cast 2010-03-08; 6932536: JSR 292 modified JDK MethodHandlesTest fails on x86_64 2010-03-09; 6919934: JSR 292 needs to support x86 C1 2010-03-16; 6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob 2010-03-17; 6934966: JSR 292 add C1 logic for saved SP over MethodHandle calls 2010-03-18; 6932091: JSR 292 x86 code cleanup 2010-03-31; 6939731: JSR 292 Zero build fix after 6934494 2010-04-29; 6829193: JSR 292 needs to support SPARC 2010-05-01; 6939134: JSR 292 adjustments to method handle invocation 2010-05-21; 6930772: JSR 292 needs to support SPARC C1 2010-05-25; 6934104: JSR 292 needs to support SPARC C2 2010-06-09; 6939203: JSR 292 needs method handle constants 2010-07-15; 6964498: JSR 292 invokedynamic sites need local bootstrap methods 2010-09-24; 6986944: JSR 292 assert(caller_nm->is_method_handle_return(caller_frame.pc())) failed: must be MH call site 2010-09-29; 6987634: JSR 292 assert(start_bci() >= 0 && start_bci() < code_size()) failed: correct osr_bci argument 2010-10-11; 6829194: JSR 292 needs to support compressed oops 2010-10-13; 6987555: JSR 292 unboxing to a boolean value fails on big-endian SPARC 2010-10-18; 6991596: JSR 292 unimplemented adapter_opt_i2i and adapter_opt_l2i on SPARC 2010-10-30; 6981777: implement JSR 292 EG adjustments from summer 2010 2010-10-30; 6984311: JSR 292 needs optional bootstrap method parameters 2010-11-04; 6997459: JSR 292 after 6994093 getting: on return to interpreted call, restored SP is corrupted 2010-11-09; 6998737: JSR 292: Remove the plug guarding the use of compressed oops 2010-11-30; 7001363: java/dyn/InvokeDynamic should not be a well-known class in the JVM 2010-12-22; 7007377: JSR 292 MethodHandlesTest.testCastFailure fails on SPARC with -Xcomp +DeoptimizeALot Sunday, February 3, 13
  24. 2011 • Wrapping things up for FCS • Focus on

    correctness • Some JIT work landing for perf • JRuby a primary test case Sunday, February 3, 13
  25. Java 7 GA • Changes within couple months of release

    • Signature polymorphism • Minor API and naming adjustments • java.lang.invoke package name • Performance still dismal • JIT work not completed in time Sunday, February 3, 13
  26. 2011-04-25; 7030715: JSR 292 JRuby test/test_super_call_site_caching.rb asserts with +DoEscapeAnalysis 2011-05-10;

    7042122: JSR 292: adjust various inline thresholds for JSR 292 API methods and method handle adapters 2011-05-17; 7045513: JSR 292 inlining causes crashes in methodHandleWalk.cpp 2011-05-26; 7047961: JSR 292 MethodHandleWalk swap args doesn't handle T_LONG and T_DOUBLE properly 2011-06-22; 7057587: JSR 292 - crash with jruby in test/test_respond_to.rb Sunday, February 3, 13
  27. 2011-02-11; 7013417: JSR 292 needs to support variadic method handle

    calls 2011-02-11; 7012650: implement JSR 292 EG adjustments through January 2010 2011-02-11; 7013730: JSR 292 reflective operations should report errors with standard exception types 2011-02-15; 7016261: JSR 292 MethodType objects should be serializable 2011-02-15; 7014755: JSR 292 member lookup interaction with security manager 2011-02-15; 7016520: JSR 292 rules for polymorphic signature processing must be in package-info 2011-03-18; 6839872: remove implementation inheritance from JSR 292 APIs 2011-03-23; 7012648: move JSR 292 to package java.lang.invoke and adjust names 2011-04-07; 6817525: turn on method handle functionality by default for JSR 292 2011-05-12; 7034977: JSR 292 MethodHandle.invokeGeneric should be renamed MethodHandle.invoke 2011-05-17; 7044892: JSR 292: API entry points sometimes throw the wrong exceptions or doesn't throw the expected one 2011-05-26; 7032323: code changes for JSR 292 EG adjustments to API, through Public Review 2011-06-03; 7051206: JSR 292 method name SwitchPoint.isValid is misleading to unwary users; should be hasBeenInvalidated Sunday, February 3, 13
  28. INVOKEDYNAMIC vcall:foo(LThreadContext;LIRubyObject;LIRubyObject;)LIRubyObject; [ // handle kind 0x6 : INVOKESTATIC InvocationLinker.invocationBootstrap(

    (LMethodHandles$Lookup;LString;LMethodType;LString;I)LCallSite;) // arguments: "-e", 1 ] Sunday, February 3, 13
  29. What to Do? • GA indy perf slower than non-indy!

    • Enable indy, knowing perf is bad? Sunday, February 3, 13
  30. What to Do? • GA indy perf slower than non-indy!

    • Enable indy, knowing perf is bad? • Disable, despite promises of future perf? Sunday, February 3, 13
  31. What to Do? • GA indy perf slower than non-indy!

    • Enable indy, knowing perf is bad? • Disable, despite promises of future perf? • Detect JVM version? Sunday, February 3, 13
  32. What to Do? • GA indy perf slower than non-indy!

    • Enable indy, knowing perf is bad? • Disable, despite promises of future perf? • Detect JVM version? • Detect VM version? Sunday, February 3, 13
  33. 2011-08-31; 7078382: JSR 292: don't count method handle adapters against

    inlining budgets 2011-09-02; 7071709: JSR 292: switchpoint invalidation should be pushed not pulled 2011-09-08; 7085860: JSR 292: implement CallSite.setTargetNormal and setTargetVolatile as native methods 2011-10-12; 7092712: JSR 292: unloaded invokedynamic call sites can lead to a crash with signature types not on BCP 2011-10-24; 7090904: JSR 292: JRuby junit test crashes in PSScavengeRootsClosure::do_oop 2011-10-25; 7094138: JSR 292: JRuby junit test fails in CallSite.setTargetNormal: obj->is_oop() failed: sanity check 2011-11-17; 7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not Sunday, February 3, 13
  34. Java 7u2 • Performance work finally released! • JRuby users

    put indy into production • NoClassDefFound era (ha!) begins • To this day, no 100% working Hotspot indy! • ...and apparently J9 is not much better • Maybe we should have Java syntax for indy? Sunday, February 3, 13
  35. NCDFE Bug • Method handles operate at bootstrap level •

    Must be able to bind user-loaded classes • Handle impl only handled first type right • Subsequent types presented incorrectly • NCDFE resulted in JITed code Sunday, February 3, 13
  36. NCDFE Workarounds • Load everything on bootstrap • JRuby does

    this for noverify • Not practical for server setups • Erase all types to bootstrap classes • Introduced checkcasts hurt perf • Impossible to maintain both versions Sunday, February 3, 13
  37. Other Issues • Inlining thresholds must be special-cased • Native

    handles are opaque • Native handles are expensive to create • Native handles are hard to inspect • Many optz can’t cross indy site Sunday, February 3, 13
  38. 2012 • Rewrite of Hotspot’s 292 subsystem • Mostly-native moves

    into Java code • LambdaForm instead of native • @ForceInline hints added for JIT purposes • Erases types, avoiding NCDFE issues Sunday, February 3, 13
  39. LambdaForm • Java objects represent MH chain • Unjitted, call

    directly through LFs • LF “compiler” emits bytecoded adapters • Bytecode inlined, optimized as normal • JIT becomes more important • Not universally loved... Sunday, February 3, 13
  40. def foo bar end def bar baz end def baz

    sleep end foo Sunday, February 3, 13
  41. LF pre-JIT at org.jruby.RubyKernel.sleep(RubyKernel.java:801) at org.jruby.RubyKernel$INVOKER$s$0$1$sleep.call(RubyKernel$INVOKER$s$0$1$sleep.gen) at org.jruby.internal.runtime.methods.JavaMethod$JavaMethodN.call(JavaMethod.java:642) at org.jruby.internal.runtime.methods.DynamicMethod.call(DynamicMethod.java:197)

    at java.lang.invoke.LambdaForm$DMH/692342133.invokeVirtual_LLLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLLL_L(LambdaForm.java:1112) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/1395089624.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$NFI/792791759.invoke_LLLLLL_L(LambdaForm$NFI) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/1254526270.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$DMH/1744347043.invokeSpecial_LLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLL_L(LambdaForm.java:1107) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/874088044.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLL_L(LambdaForm.java:1107) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/1837543557.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLLL_L(LambdaForm.java:1112) Sunday, February 3, 13
  42. at org.jruby.RubyKernel.sleep(RubyKernel.java:801) at org.jruby.RubyKernel$INVOKER$s$0$1$sleep.call(RubyKernel$INVOKER$s$0$1$sleep.gen) at org.jruby.internal.runtime.methods.JavaMethod$JavaMethodN.call(JavaMethod.java:642) at org.jruby.internal.runtime.methods.DynamicMethod.call(DynamicMethod.java:197) at java.lang.invoke.LambdaForm$DMH/692342133.invokeVirtual_LLLLL_L(LambdaForm$DMH)

    at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLLL_L(LambdaForm.java:1112) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/1395089624.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$NFI/792791759.invoke_LLLLLL_L(LambdaForm$NFI) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/1254526270.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$DMH/1744347043.invokeSpecial_LLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLL_L(LambdaForm.java:1107) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/874088044.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLL_L(LambdaForm.java:1107) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/1837543557.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLLL_L(LambdaForm.java:1112) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/1837543557.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLLL_L(LambdaForm.java:1112) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/1837543557.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$DMH/1191747167.invokeSpecial_LLLLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NFI/792791759.invoke_LLLLLL_L(LambdaForm$NFI) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/1395089624.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$NFI/792791759.invoke_LLLLLL_L(LambdaForm$NFI) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/1837543557.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$DMH/1191747167.invokeSpecial_LLLLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NFI/792791759.invoke_LLLLLL_L(LambdaForm$NFI) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/874088044.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLL_L(LambdaForm.java:1107) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/874088044.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLL_L(LambdaForm.java:1107) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/662441761.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LL_L(LambdaForm.java:1097) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/662441761.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$MH/1190524793.invokeExact_MT(LambdaForm$MH) at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:599) at org.jruby.runtime.invokedynamic.InvocationLinker.invocationFallback(InvocationLinker.java:138) at java.lang.invoke.LambdaForm$DMH/1304836502.invokeStatic_LLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$DMH/1151020327.invokeSpecial_LLLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLLL_L(LambdaForm.java:1112) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/1254526270.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$MH/1451043227.linkToCallSite(LambdaForm$MH) at ruby.__dash_e__.method__2$RUBY$baz(-e:1) at java.lang.invoke.LambdaForm$DMH/1304836502.invokeStatic_LLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$DMH/1151020327.invokeSpecial_LLLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLLL_L(LambdaForm.java:1112) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/1254526270.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$DMH/1744347043.invokeSpecial_LLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLL_L(LambdaForm.java:1107) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/874088044.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLL_L(LambdaForm.java:1107) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/1837543557.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLLL_L(LambdaForm.java:1112) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/1837543557.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLLL_L(LambdaForm.java:1112) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/1837543557.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$DMH/1191747167.invokeSpecial_LLLLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NFI/792791759.invoke_LLLLLL_L(LambdaForm$NFI) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/1395089624.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$NFI/792791759.invoke_LLLLLL_L(LambdaForm$NFI) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/1837543557.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$DMH/1191747167.invokeSpecial_LLLLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NFI/792791759.invoke_LLLLLL_L(LambdaForm$NFI) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/874088044.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLL_L(LambdaForm.java:1107) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/874088044.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLL_L(LambdaForm.java:1107) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/662441761.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LL_L(LambdaForm.java:1097) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/662441761.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$MH/1190524793.invokeExact_MT(LambdaForm$MH) at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:599) at org.jruby.runtime.invokedynamic.InvocationLinker.invocationFallback(InvocationLinker.java:138) at java.lang.invoke.LambdaForm$DMH/1304836502.invokeStatic_LLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$DMH/1151020327.invokeSpecial_LLLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLLL_L(LambdaForm.java:1112) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/1254526270.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$MH/1451043227.linkToCallSite(LambdaForm$MH) at ruby.__dash_e__.method__1$RUBY$bar(-e:1) at java.lang.invoke.LambdaForm$DMH/1304836502.invokeStatic_LLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$DMH/1151020327.invokeSpecial_LLLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLLL_L(LambdaForm.java:1112) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/1254526270.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$DMH/1744347043.invokeSpecial_LLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLL_L(LambdaForm.java:1107) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/874088044.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLL_L(LambdaForm.java:1107) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/1837543557.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLLL_L(LambdaForm.java:1112) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/1837543557.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLLL_L(LambdaForm.java:1112) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/1837543557.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$DMH/1191747167.invokeSpecial_LLLLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NFI/792791759.invoke_LLLLLL_L(LambdaForm$NFI) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/1395089624.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$NFI/792791759.invoke_LLLLLL_L(LambdaForm$NFI) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/1837543557.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$DMH/1191747167.invokeSpecial_LLLLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NFI/792791759.invoke_LLLLLL_L(LambdaForm$NFI) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/874088044.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLL_L(LambdaForm.java:1107) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/874088044.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLL_L(LambdaForm.java:1107) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/662441761.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LL_L(LambdaForm.java:1097) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/662441761.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$MH/1190524793.invokeExact_MT(LambdaForm$MH) at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:599) at org.jruby.runtime.invokedynamic.InvocationLinker.invocationFallback(InvocationLinker.java:138) at java.lang.invoke.LambdaForm$DMH/1304836502.invokeStatic_LLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$DMH/1151020327.invokeSpecial_LLLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLLL_L(LambdaForm.java:1112) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/1254526270.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$MH/1451043227.linkToCallSite(LambdaForm$MH) at ruby.__dash_e__.method__0$RUBY$foo(-e:1) at java.lang.invoke.LambdaForm$DMH/1304836502.invokeStatic_LLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$DMH/1151020327.invokeSpecial_LLLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLLL_L(LambdaForm.java:1112) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/1254526270.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$DMH/1744347043.invokeSpecial_LLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLL_L(LambdaForm.java:1107) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/874088044.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLL_L(LambdaForm.java:1107) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/1837543557.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLLL_L(LambdaForm.java:1112) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/1837543557.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLLL_L(LambdaForm.java:1112) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/1837543557.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$DMH/1191747167.invokeSpecial_LLLLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NFI/792791759.invoke_LLLLLL_L(LambdaForm$NFI) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/1395089624.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$NFI/792791759.invoke_LLLLLL_L(LambdaForm$NFI) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/1837543557.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$DMH/1191747167.invokeSpecial_LLLLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NFI/792791759.invoke_LLLLLL_L(LambdaForm$NFI) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/874088044.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLL_L(LambdaForm.java:1107) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/874088044.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLL_L(LambdaForm.java:1107) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/662441761.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LL_L(LambdaForm.java:1097) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/662441761.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$MH/1190524793.invokeExact_MT(LambdaForm$MH) at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:599) at org.jruby.runtime.invokedynamic.InvocationLinker.invocationFallback(InvocationLinker.java:138) at java.lang.invoke.LambdaForm$DMH/1304836502.invokeStatic_LLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$DMH/1151020327.invokeSpecial_LLLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLLL_L(LambdaForm.java:1112) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$LFI/1254526270.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$MH/1451043227.linkToCallSite(LambdaForm$MH) at ruby.__dash_e__.__file__(-e:1) sleep baz bar foo top-level of script Sunday, February 3, 13
  43. Java Release? • Work-in-progress until recent months • Only made

    it to OpenJDK8 this fall • Targeted for 7u12/14 right now • Approval seems to be going well • Still no 100% working indy release! Sunday, February 3, 13
  44. Meanwhile... • RubyFlux: Ruby to .java compiler • Dynamic calls

    converted to virtual • Generated superclass with all methods • method_missing, send, etc possible • Eclipse JDT for generating source • Early prototype Sunday, February 3, 13
  45. def foo bar end def bar self end a =

    100_000_000 while a > 0 foo; foo; foo; foo; foo a -= 1 end Sunday, February 3, 13
  46. public class foo_bar extends RObject { public static void main(String[]

    args) { new foo_bar().$main(); } public void $main() { RObject $last = RNil; RObject a = RNil; $last = a = new RFixnum(100000000L); while (a.$greater(new RFixnum(0L)).toBoolean()) { $last = foo(); $last = foo(); $last = foo(); $last = foo(); $last = foo(); $last = a = a.$minus(new RFixnum(1L)); ; } $last = RNil; ; } public RObject foo() { RObject $last = RNil; $last = bar(); return $last; } public RObject bar() { RObject $last = RNil; $last = RNil; return $last; } } Sunday, February 3, 13
  47. Performance • I believe, I really do • But it

    has gone back and forth Sunday, February 3, 13
  48. Performance • I believe, I really do • But it

    has gone back and forth • And I have shamefully not contributed Sunday, February 3, 13
  49. Performance • I believe, I really do • But it

    has gone back and forth • And I have shamefully not contributed • Other than whining and providing benches Sunday, February 3, 13
  50. Performance • I believe, I really do • But it

    has gone back and forth • And I have shamefully not contributed • Other than whining and providing benches • I vow to change this in 2013 Sunday, February 3, 13
  51. Debugging • MethodHandle errors are often cryptic • No MH

    chain inspection • Backward binding flips brain ugh bad • Errors may occur after repeated calls • Site rebinding bugs • PIC bugs • Failure path bugs Sunday, February 3, 13
  52. Security • With great power...comes great exploits • Recent hacks

    related to indy, MHs • I knew at least one would come out • ...so I helped test recent fixes • Imagine building reflection API today • In the presence of stack hacks! Sunday, February 3, 13
  53. MethodHandle API • MH API is very bare bones, low

    level • InvokeBinder - fluent DSL for MH chains • Build forward, not backward • Track signature, arg names • Many conveniences • https://github.com/headius/invokebinder Sunday, February 3, 13
  54. MethodHandle mh = MethodHandles.insertArguments( otherMH, index arg1, arg2); mh =

    MethodHandles.dropArguments(mh, 1, Blah.class) mh = MethodHandles.permuteArguments( mh, MethodType.methodType( String.class, Object.class, int.class new int[] {0, 1, 4, 5}); mh = MethodHandles.explicitCastArguments( mh, MethodType.methodType( String.class, Object.class, int.class); Sunday, February 3, 13
  55. MethodHandle mh = Binder .from(String.class, String.class, String.class) // String w(String,

    String) .drop(1, String.class) // String x(String) .insert(0, 'hello') // String y(String, String) .cast(String.class, CharSequence.class, Object.class) // String z(CharSequence, Object) .invoke(someTargetHandle); MethodHandle m11 = lookup .findStatic(Demo1.class, "twoArgs", MethodType.methodType(String.class, String.class, String.class)); m11 = MethodHandles.permuteArguments( m11, MethodType.methodType(String.class, String.class, String.class, int.class), 1, 0); MethodHandle m12 = Binder.from(String.class, String.class, String.class, int.class) .permute(1, 0) .invokeStatic(lookup, Demo1.class, "initials"); m12.invoke("one", "two", 3); // => "[two,one]" Argument Manipulation Sunday, February 3, 13
  56. MethodHandle mh = Binder .from(String.class, String.class, String.class) // String w(String,

    String) .drop(1, String.class) // String x(String) .insert(0, 'hello') // String y(String, String) .cast(String.class, CharSequence.class, Object.class) // String z(CharSequence, Object) .invoke(someTargetHandle); MethodHandle m11 = lookup .findStatic(Demo1.class, "twoArgs", MethodType.methodType(String.class, String.class, String.class)); m11 = MethodHandles.permuteArguments( m11, MethodType.methodType(String.class, String.class, String.class, int.class), 1, 0); MethodHandle m12 = Binder.from(String.class, String.class, String.class, int.class) .permute(1, 0) .invokeStatic(lookup, Demo1.class, "initials"); m12.invoke("one", "two", 3); // => "[two,one]" Argument Manipulation Sunday, February 3, 13
  57. MethodHandle post = Binder .from(void.class, String[].class) .invokeStatic(lookup, BinderTest.class, "finallyLogic"); MethodHandle

    handle = Binder .from(void.class, String[].class) .tryFinally(post) .invokeStatic(lookup, BinderTest.class, "bodyOfCode"); try/finally Sunday, February 3, 13
  58. MethodHandle exceptionHandler = Binder .from(target.type().insertParameterTypes(0, Throwable.class).changeReturnType(void.class)) .drop(0) .invoke(post); MethodHandle rethrow

    = Binder .from(target.type().insertParameterTypes(0, Throwable.class)) .fold(exceptionHandler) .drop(1, target.type().parameterCount()) .throwException(); target = MethodHandles.catchException(target, Throwable.class, rethrow); // if target returns a value, we must return it regardless of post MethodHandle realPost = post; if (target.type().returnType() != void.class) { // modify post to ignore return value MethodHandle newPost = Binder .from(target.type().insertParameterTypes(0, target.type().returnType()).changeReturnType(void.class)) .drop(0) .invoke(post); // fold post into an identity chain that only returns the value realPost = Binder .from(target.type().insertParameterTypes(0, target.type().returnType())) .fold(newPost) .drop(1, target.type().parameterCount()) .identity(); } return MethodHandles.foldArguments(realPost, target); try/finally Sunday, February 3, 13
  59. Symbolic Arguments • Easier to follow than indices • Easier

    to adapt to different signatures • Arity less of a challenge Sunday, February 3, 13
  60. MethodHandle mh = MethodHandles.insertArguments( otherMH, 0 arg1, arg2); mh =

    MethodHandles.dropArguments(mh, 1, Blah.class) mh = MethodHandles.permuteArguments( mh, MethodType.methodType( String.class, Object.class, int.class new int[] {0, 1, 4, 5}); mh = MethodHandles.explicitCastArguments( mh, MethodType.methodType( String.class, Object.class, int.class); Sunday, February 3, 13
  61. // Incoming args for DynamicMethod.call private static final Signature DYNAMIC_METHOD_SIG

    = Signature .returning(IRubyObject.class) .appendArg("method", DynamicMethod.class) .appendArg("context", ThreadContext.class) .appendArg("self", IRubyObject.class) .appendArg("selfClass", RubyModule.class) .appendArg("name", String.class); // Only want context and self private static final Signature CONTEXT_AND_SELF = DYNAMIC_METHOD_SIG .permute("context", "self"); // Easy generic transformations from one sig to another private static MethodHandle dynamicCallTarget(Signature from, Signature to) { return SmartBinder .from(from) .fold("selfClass", from.asFold(RubyClass.class).permuteTo(PGC, "context", "self")) .permute(to) .cast(to) .invokeVirtualQuiet(lookup(), "call") .handle(); } Args By Name Sunday, February 3, 13
  62. Use in JRuby • Dynamic calls • Dynamic “constants” •

    Global variables • Thread events • Lazy literals • Instance variables Sunday, February 3, 13
  63. Dynamic Calls • Per-class mutable method tables • Consistent call

    signature • Bootstrap binds fallback path • Fallback binds guards + target • Call site fails out after N invalidations Sunday, February 3, 13
  64. Dyncall Guard • GWT • Exact type check for “final”

    types • Metaclass identity • Slightly weaker than Hotspot • SwitchPoint • Per-class modification guard Sunday, February 3, 13
  65. if (self instanceof RubySymbol || self instanceof RubyFixnum || self

    instanceof RubyFloat || self instanceof RubyNil || self instanceof RubyBoolean.True || self instanceof RubyBoolean.False) { test = selfTest .insert(1, "selfJavaType", self.getClass()) .cast(boolean.class, Object.class, Class.class) .invoke(TEST_CLASS); } else { selfTest = selfTest.insert(0, "selfClass", selfClass); test = selfTest .cast(boolean.class, RubyClass.class, IRubyObject.class) .invoke(TEST); } gwt = createGWT(test, target, fallback, entry, site, curry); // wrap in switchpoint for mutation invalidation gwt = switchPoint.guardWithTest( gwt, curry ? insertArguments(fallback, 0, site) : fallback); Sunday, February 3, 13
  66. if (self instanceof RubySymbol || self instanceof RubyFixnum || self

    instanceof RubyFloat || self instanceof RubyNil || self instanceof RubyBoolean.True || self instanceof RubyBoolean.False) { test = selfTest .insert(1, "selfJavaType", self.getClass()) .cast(boolean.class, Object.class, Class.class) .invoke(TEST_CLASS); } else { selfTest = selfTest.insert(0, "selfClass", selfClass); test = selfTest .cast(boolean.class, RubyClass.class, IRubyObject.class) .invoke(TEST); } gwt = createGWT(test, target, fallback, entry, site, curry); // wrap in switchpoint for mutation invalidation gwt = switchPoint.guardWithTest( gwt, curry ? insertArguments(fallback, 0, site) : fallback); Sunday, February 3, 13
  67. if (self instanceof RubySymbol || self instanceof RubyFixnum || self

    instanceof RubyFloat || self instanceof RubyNil || self instanceof RubyBoolean.True || self instanceof RubyBoolean.False) { test = selfTest .insert(1, "selfJavaType", self.getClass()) .cast(boolean.class, Object.class, Class.class) .invoke(TEST_CLASS); } else { selfTest = selfTest.insert(0, "selfClass", selfClass); test = selfTest .cast(boolean.class, RubyClass.class, IRubyObject.class) .invoke(TEST); } gwt = createGWT(test, target, fallback, entry, site, curry); // wrap in switchpoint for mutation invalidation gwt = switchPoint.guardWithTest( gwt, curry ? insertArguments(fallback, 0, site) : fallback); Sunday, February 3, 13
  68. public static boolean testMetaclass( RubyClass metaclass, IRubyObject self) { return

    metaclass == ((RubyBasicObject)self).getMetaClass(); } Icky Hotspot artifact... Sunday, February 3, 13
  69. def foo self end def bar foo end 100_000.times do

    bar end Sunday, February 3, 13
  70. HERE BE DRAGONS • x86_64 ASM output from Hotspot •

    Google “hotspot printassembly” • hsdis shared lib • Drop into JVM dylib dir • -XX:+UnlockDiagnosticVMOptions -XX: +PrintAssembly • PROFIT Sunday, February 3, 13
  71. # parm0: rsi:rsi = '$01_dyncall' # parm1: rdx:rdx = 'org/jruby/runtime/ThreadContext'

    # parm2: rcx:rcx = 'org/jruby/runtime/builtin/IRubyObject' # parm3: r8:r8 = 'org/jruby/runtime/Block' ... 0x000000010c8e266c: test %rdx,%rdx 0x000000010c8e266f: je 0x000000010c8e26b5 ;*ifnull ; - java.lang.Class::cast@1 (line 3008) ; - java.lang.invoke.LambdaForm$MH/1631862159::guard@12 ; - java.lang.invoke.LambdaForm$MH/783286238::linkToCallSite@14 ; - $01_dyncall::method__1$RUBY$bar@3 (line 6) 0x000000010c8e2671: mov 0x8(%rcx),%r11d ; implicit exception: dispatches to 0x000000010c8e26f1 0x000000010c8e2675: cmp $0x21f1a6ba,%r11d ; {metadata('org/jruby/RubyObject')} 0x000000010c8e267c: jne 0x000000010c8e26d5 0x000000010c8e267e: mov %rcx,%r10 ;*checkcast ; - org.jruby.runtime.invokedynamic.InvocationLinker::testMetaclass@2 (line 694) ; - java.lang.invoke.LambdaForm$DMH/1348949648::invokeStatic_LL_I@11 ; - java.lang.invoke.LambdaForm$MH/591137559::convert@26 ; - java.lang.invoke.LambdaForm$MH/1638215613::guard@17 ; - java.lang.invoke.LambdaForm$DMH/476800120::invokeSpecial_LLLL_L@16 ; - java.lang.invoke.LambdaForm$MH/1631862159::guard@50 ; - java.lang.invoke.LambdaForm$MH/783286238::linkToCallSite@14 ; - $01_dyncall::method__1$RUBY$bar@3 (line 6) 0x000000010c8e2681: mov 0x14(%r10),%ebp ;*getfield metaClass ; - org.jruby.RubyBasicObject::getMetaClass@1 (line 517) ; - org.jruby.runtime.invokedynamic.InvocationLinker::testMetaclass@5 (line 694) ; - java.lang.invoke.LambdaForm$DMH/1348949648::invokeStatic_LL_I@11 ; - java.lang.invoke.LambdaForm$MH/591137559::convert@26 ; - java.lang.invoke.LambdaForm$MH/1638215613::guard@17 ; - java.lang.invoke.LambdaForm$DMH/476800120::invokeSpecial_LLLL_L@16 ; - java.lang.invoke.LambdaForm$MH/1631862159::guard@50 ; - java.lang.invoke.LambdaForm$MH/783286238::linkToCallSite@14 ; - $01_dyncall::method__1$RUBY$bar@3 (line 6) 0x000000010c8e2685: cmp $0x2576cde9,%ebp ; {oop(a 'org/jruby/MetaClass')} 0x000000010c8e268b: jne 0x000000010c8e269c ;*if_acmpne ; - org.jruby.runtime.invokedynamic.InvocationLinker::testMetaclass@8 (line 694) ; - java.lang.invoke.LambdaForm$DMH/1348949648::invokeStatic_LL_I@11 ; - java.lang.invoke.LambdaForm$MH/591137559::convert@26 ; - java.lang.invoke.LambdaForm$MH/1638215613::guard@17 ; - java.lang.invoke.LambdaForm$DMH/476800120::invokeSpecial_LLLL_L@16 ; - java.lang.invoke.LambdaForm$MH/1631862159::guard@50 ; - java.lang.invoke.LambdaForm$MH/783286238::linkToCallSite@14 ; - $01_dyncall::method__1$RUBY$bar@3 (line 6) 0x000000010c8e268d: mov %rcx,%rax 0x000000010c8e2690: add $0x30,%rsp 0x000000010c8e2694: pop %rbp 0x000000010c8e2695: test %eax,-0x18e369b(%rip) # 0x000000010afff000 ; {poll_return} 0x000000010c8e269b: retq Sunday, February 3, 13
  72. # parm0: rsi:rsi = '$01_dyncall' # parm1: rdx:rdx = 'org/jruby/runtime/ThreadContext'

    # parm2: rcx:rcx = 'org/jruby/runtime/builtin/IRubyObject' # parm3: r8:r8 = 'org/jruby/runtime/Block' ... mov 0x8(%rcx),%r11d ; implicit exception: dispatches to 0x000000010c8e26f1 cmp $0x21f1a6ba,%r11d ; {metadata('org/jruby/RubyObject')} jne 0x000000010c8e26d5 mov %rcx,%r10 ;*checkcast ; - InvocationLinker::testMetaclass@2 (line 694) mov 0x14(%r10),%ebp ;*getfield metaClass ; - RubyBasicObject::getMetaClass@1 (line 517) ; - InvocationLinker::testMetaclass@5 (line 694) cmp $0x2576cde9,%ebp ; {oop(a 'org/jruby/MetaClass')} jne 0x000000010c8e269c ;*if_acmpne ; - InvocationLinker::testMetaclass@8 (line 694) mov %rcx,%rax ... retq + safepoint checks... Sunday, February 3, 13
  73. Better Than Java? • Polymorphic calls • Hotspot inlines up

    to bimorphic • JRuby: trimorphic PIC, configurable • Smarter type checks possible • Eliminate boxing at call site Sunday, February 3, 13
  74. Constants • Lexical lazily-defined variables • Redefinable, but usually static

    • Single global invalidator (SwitchPoint) • Mostly due to lexical scoping • Constant target Sunday, February 3, 13
  75. Global Variables • Global, thread-local, frame-local • Only global gets

    cached • Per-variable guard • Constant value • Failover to lookup after N invalidations Sunday, February 3, 13
  76. Foo = 1 $bar = 1 def get_foo Foo end

    def get_bar $bar end Sunday, February 3, 13
  77. # parm0: rsi:rsi = '$06_constants' # parm1: rdx:rdx = 'org/jruby/runtime/ThreadContext'

    # parm2: rcx:rcx = 'org/jruby/runtime/builtin/IRubyObject' # parm3: r8:r8 = 'org/jruby/runtime/Block' # [sp+0x50] (sp of caller) mov %eax,-0x14000(%rsp) push %rbp sub $0x40,%rsp ;*synchronization entry ; - $06_constants::method__0$RUBY$get_foo@-1 (line 5) test %rsi,%rsi je 0x000000010d5d464c ;*ifnull ; - java.lang.Class::cast@1 (line 3008) ; - $06_constants::method__0$RUBY$get_foo@2 (line 5) test %rdx,%rdx je 0x000000010d5d466d ;*ifnull ; - java.lang.Class::cast@1 (line 3008) ; - $06_constants::method__0$RUBY$get_foo@2 (line 5) movabs $0x12c9a2e88,%rax ;*synchronization entry ; - $06_constants::method__0$RUBY$get_foo@-1 (line 5) ; {oop(a 'org/jruby/RubyFixnum')} add $0x40,%rsp pop %rbp test %eax,-0x95364b(%rip) # 0x000000010cc81000 ; {poll_return} retq Sunday, February 3, 13
  78. # parm0: rsi:rsi = '$06_constants' # parm1: rdx:rdx = 'org/jruby/runtime/ThreadContext'

    # parm2: rcx:rcx = 'org/jruby/runtime/builtin/IRubyObject' # parm3: r8:r8 = 'org/jruby/runtime/Block' # [sp+0x50] (sp of caller) ... movabs $0x12c9a2e88,%rax ;*synchronization entry ; - $06_constants::method__0$RUBY$get_foo@-1 (line 5) ; {oop(a 'org/jruby/RubyFixnum')} ... retq + safepoint yadda yadda Sunday, February 3, 13
  79. # parm0: rsi:rsi = '$06_constants' # parm1: rdx:rdx = 'org/jruby/runtime/ThreadContext'

    # parm2: rcx:rcx = 'org/jruby/runtime/builtin/IRubyObject' # parm3: r8:r8 = 'org/jruby/runtime/Block' # [sp+0x30] (sp of caller) mov %eax,-0x14000(%rsp) push %rbp sub $0x20,%rsp ;*synchronization entry ; - $06_constants::method__1$RUBY$get_bar@-1 (line 13) test %rdx,%rdx je 0x00000001057275e7 ;*ifnull ; - java.lang.Class::cast@1 (line 3008) ; - $06_constants::method__1$RUBY$get_bar@1 (line 17) movabs $0x7f6bef838,%rax ;*synchronization entry ; - $06_constants::method__1$RUBY$get_bar@-1 (line 13) ; {oop(a 'org/jruby/RubyFixnum')} add $0x20,%rsp pop %rbp test %eax,-0x18405e6(%rip) # 0x0000000103ee7000 ; {poll_return} retq Sunday, February 3, 13
  80. # parm0: rsi:rsi = '$06_constants' # parm1: rdx:rdx = 'org/jruby/runtime/ThreadContext'

    # parm2: rcx:rcx = 'org/jruby/runtime/builtin/IRubyObject' # parm3: r8:r8 = 'org/jruby/runtime/Block' # [sp+0x30] (sp of caller) ... movabs $0x7f6bef838,%rax ;*synchronization entry ; - $06_constants::method__1$RUBY$get_bar@-1 (line 13) ; {oop(a 'org/jruby/RubyFixnum')} ... retq Sunday, February 3, 13
  81. Better Than Java? • Constant folding • Lazy static finals

    can’t fold in Hotspot • SwitchPoint + constant value can! • Broke several benchmarks :-) Sunday, February 3, 13
  82. Better Than Java? • Constant folding • Lazy static finals

    can’t fold in Hotspot • SwitchPoint + constant value can! • Broke several benchmarks :-) Fixed in 7 Sunday, February 3, 13
  83. public class JavaLazyFinal { private static final long FINAL =

    System.currentTimeMillis(); private static long accum = 0 ; public static void main(String[] args) { for (int i = 0; i < 1000000; i++) { accumulate(); } System.out.println(accum); } public static void accumulate() { accum += FINAL; } } Sunday, February 3, 13
  84. # {method} 'accumulate' '()V' in 'JavaLazyFinal' # [sp+0x20] (sp of

    caller) ... 1063a6726: movabs $0x7fb283d70,%r10 ; {oop('JavaLazyFinal')} 1063a6730: mov 0x258(%r10),%r8d ;*getstatic FINAL ... retq ... movabs $0x7f6bef838,%rax ;*synchronization entry ; - $06_constants::method__1$RUBY$get_bar@-1 (line 13) ; {oop(a 'org/jruby/RubyFixnum')} ... retq Java 6 Sunday, February 3, 13
  85. {0x0000000102e40460} 'accumulate' '()V' in 'JavaLazyFinal' # [sp+0x20] (sp of caller)

    ... movabs $0x13c88b682e5,%r10 ... retq ... movabs $0x7f6bef838,%rax ;*synchronization entry ; - $06_constants::method__1$RUBY$get_bar@-1 (line 13) ; {oop(a 'org/jruby/RubyFixnum')} ... retq Java 7 Sunday, February 3, 13
  86. Instance Variables • Per-class mutable table of “fields” • Class

    maps names to offsets • Type guard • Specificity is up for debate... • Offset cached in MH chain directly • Future: true Java fields? Sunday, February 3, 13
  87. Thread Events • Rare cross-thread interrupts • kill, raise exception

    • Guard call sites, method entry, backedge • Invalidates everything...hmmm Sunday, February 3, 13
  88. Thread Event Guard • Global SwitchPoint • Target is a

    no-op • Fallback checks thread events • On event, invalidate SP • All code thrown out • Looking at hybrid volatile + SP options Sunday, February 3, 13
  89. Lazy Literals • Numbers, Strings, Regexp, True/False/Nil • Local caching

    of JRuby runtime • ConstantCallSite for runtime-isolated • MutableCallSite for runtime-specific • Classloader fails us here anyway • Do isolated constant handles pointing at same objects fold away? Sunday, February 3, 13
  90. base64 richards neural mandelbrot 0 1.25 2.5 3.75 5 Times

    faster than Ruby 2.0.0pre1 JRuby/Java 7 JRuby/Java 7 + indy Sunday, February 3, 13
  91. base64 richards neural mandelbrot 0 1.25 2.5 3.75 5 3.434

    2.519 2.048 2.99 3.973 Times faster than Ruby 2.0.0pre1 JRuby/Java 7 JRuby/Java 7 + indy Sunday, February 3, 13
  92. base64 richards neural mandelbrot 0 1.25 2.5 3.75 5 3.434

    2.519 2.048 2.99 3.973 4.107 2.946 3.84 Times faster than Ruby 2.0.0pre1 JRuby/Java 7 JRuby/Java 7 + indy Sunday, February 3, 13
  93. JRuby Rubinius 2.0.0rc1 MagLev MacRuby 0.12 Ruby 2.0.0 Ruby 1.9.3

    Ruby 1.8.7 0 25000 50000 75000 100000 4750 11439 19590.7 19609.5 23954.5 60232.3 90593 Smooth sort of a small array Iterations per second Sunday, February 3, 13
  94. jruby + Java ext jruby + Ruby ruby-2.0.0 + C

    ext ruby-1.9.3 + C ext rbx-2.0.0rc1 + Ruby macruby-0.12 + Ruby maglev + Ruby ruby-2.0.0 + Ruby ruby-1.9.3 + Ruby 0 1 2 3 4 3.96 2.48 1.39 1.19 0.51 0.51 0.51 0.29 0.1 red/black tree, pure Ruby versus native Runtime per iteration Sunday, February 3, 13
  95. Future • Ongoing tuning of JIT, inlining • Reduce perf

    cliff for unjitted or uninlined • Partial inlining helping a lot here • Inlining through closure receivers • Tie inlining to closure-receiving site? • Better EA! value types? tagged values? • Android! Sunday, February 3, 13