Download - Invokedynamic: Tales from the Trenches
invokedynamicTales from the Trenches
Sunday, February 3, 13
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
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
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
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
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
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
Promises
• “JRuby plus invokedynamic will be fast”
• “The fully-working optimized OpenJDK indy impl is just around the corner”
Sunday, February 3, 13
The Beginning
Sunday, February 3, 13
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
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
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
2008
• “A First Taste of InvokeDynamic”
• http://blog.headius.com/2008/09/first-taste-of-invokedynamic.html
• 11 Sept, 2008
• ~7000 words, ~26k views
Sunday, February 3, 13
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
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
registerBootstrapMethod
static { Linkage.registerBootstrapMethod( SimpleExample.class, MethodHandles.findStatic( DynamicInvokerThingy.class, "bootstrap", Linkage.BOOTSTRAP_METHOD_TYPE));}
Sunday, February 3, 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
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
2009-04-21; 6655646: dynamic languages need dynamically linked call sitesSummary: invokedynamic instruction (JSR 292 RI)
2009-07-21; 6862576: vmIntrinsics needs cleanup in order to support JSR 292 intrinsicsSummary: 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 292Summary: 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 x86Summary: changes for method handles and invokedynamic
hotspot
Sunday, February 3, 13
2009-05-05; 6829144: JSR 292 JVM features need a provisional Java APISummary: JDK API and runtime (partial) for anonk, meth, indy
2009-10-21; 6891770: JSR 292 API needs initial unit testsSummary: backport working mlvm regression test to M3 implementation of JSR 292; requires jtreg 4.1
jdk
Sunday, February 3, 13
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
Sunday, February 3, 13
Sunday, February 3, 13
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
...Could Be Thisclass Foo def initialize(a) @a = a end
def show puts @a endend
Sunday, February 3, 13
Mirahclass Foo def initialize(a:int) @a = a end
def show puts @a endend
Sunday, February 3, 13
Mirahclass Foo def initialize(a:dynamic) @a = a end
def show puts @a endend
Sunday, February 3, 13
Middle Ages
Sunday, February 3, 13
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
2010-01-05; 6829187: compiler optimizations required for JSR 2922010-01-13; 6912065: final fields in objects need to support inlining optimizations for JSR 2922010-01-29; 6917766: JSR 292 needs its own deopt handler2010-02-01; 6921352: JSR 292 needs its own deopt handler2010-02-01; 6921799: JSR 292 call sites should not be fixed-up2010-02-23; 6928839: JSR 292 typo in x86 _adapter_check_cast2010-03-08; 6932536: JSR 292 modified JDK MethodHandlesTest fails on x86_642010-03-09; 6919934: JSR 292 needs to support x86 C12010-03-16; 6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob2010-03-17; 6934966: JSR 292 add C1 logic for saved SP over MethodHandle calls2010-03-18; 6932091: JSR 292 x86 code cleanup2010-03-31; 6939731: JSR 292 Zero build fix after 69344942010-04-29; 6829193: JSR 292 needs to support SPARC2010-05-01; 6939134: JSR 292 adjustments to method handle invocation2010-05-21; 6930772: JSR 292 needs to support SPARC C12010-05-25; 6934104: JSR 292 needs to support SPARC C22010-06-09; 6939203: JSR 292 needs method handle constants2010-07-15; 6964498: JSR 292 invokedynamic sites need local bootstrap methods2010-09-24; 6986944: JSR 292 assert(caller_nm->is_method_handle_return(caller_frame.pc())) failed: must be MH call site2010-09-29; 6987634: JSR 292 assert(start_bci() >= 0 && start_bci() < code_size()) failed: correct osr_bci argument2010-10-11; 6829194: JSR 292 needs to support compressed oops2010-10-13; 6987555: JSR 292 unboxing to a boolean value fails on big-endian SPARC2010-10-18; 6991596: JSR 292 unimplemented adapter_opt_i2i and adapter_opt_l2i on SPARC2010-10-30; 6981777: implement JSR 292 EG adjustments from summer 20102010-10-30; 6984311: JSR 292 needs optional bootstrap method parameters2010-11-04; 6997459: JSR 292 after 6994093 getting: on return to interpreted call, restored SP is corrupted2010-11-09; 6998737: JSR 292: Remove the plug guarding the use of compressed oops2010-11-30; 7001363: java/dyn/InvokeDynamic should not be a well-known class in the JVM2010-12-22; 7007377: JSR 292 MethodHandlesTest.testCastFailure fails on SPARC with -Xcomp +DeoptimizeALot
Sunday, February 3, 13
2011
• Wrapping things up for FCS
• Focus on correctness
• Some JIT work landing for perf
• JRuby a primary test case
Sunday, February 3, 13
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
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
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
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
What to Do?
Sunday, February 3, 13
What to Do?
• GA indy perf slower than non-indy!
Sunday, February 3, 13
What to Do?
• GA indy perf slower than non-indy!
• Enable indy, knowing perf is bad?
Sunday, February 3, 13
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
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
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
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
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
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
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
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
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
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
def foo barend
def bar bazend
def baz sleepend
foo
Sunday, February 3, 13
LF pre-JITat 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
Anonymous Classesat 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)
• Shared class metadata
• Patched versions of existing classes
• Reduced impact on symbol table, permgen
Sunday, February 3, 13
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 scriptSunday, February 3, 13
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
How Good Is It?
• We’ll come back to this
Sunday, February 3, 13
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
def foo barend
def bar selfend
a = 100_000_000while a > 0 foo; foo; foo; foo; foo a -= 1end
Sunday, February 3, 13
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
Other Pain
• Performance
• Debugging
• Security
• MethodHandle API
Sunday, February 3, 13
Performance
Sunday, February 3, 13
Performance
• I believe, I really do
Sunday, February 3, 13
Performance
• I believe, I really do
• But it has gone back and forth
Sunday, February 3, 13
Performance
• I believe, I really do
• But it has gone back and forth
• And I have shamefully not contributed
Sunday, February 3, 13
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
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
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
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
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
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
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
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
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
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 postMethodHandle 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
Symbolic Arguments
• Easier to follow than indices
• Easier to adapt to different signatures
• Arity less of a challenge
Sunday, February 3, 13
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
// Incoming args for DynamicMethod.callprivate 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 selfprivate static final Signature CONTEXT_AND_SELF = DYNAMIC_METHOD_SIG .permute("context", "self"); // Easy generic transformations from one sig to anotherprivate 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
Modern Era
Sunday, February 3, 13
Use in JRuby
• Dynamic calls
• Dynamic “constants”
• Global variables
• Thread events
• Lazy literals
• Instance variables
Sunday, February 3, 13
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
Dyncall Guard
• GWT
• Exact type check for “final” types
• Metaclass identity
• Slightly weaker than Hotspot
• SwitchPoint
• Per-class modification guard
Sunday, February 3, 13
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 invalidationgwt = switchPoint.guardWithTest( gwt, curry ? insertArguments(fallback, 0, site) : fallback);
Sunday, February 3, 13
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 invalidationgwt = switchPoint.guardWithTest( gwt, curry ? insertArguments(fallback, 0, site) : fallback);
Sunday, February 3, 13
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 invalidationgwt = switchPoint.guardWithTest( gwt, curry ? insertArguments(fallback, 0, site) : fallback);
Sunday, February 3, 13
public static boolean testMetaclass( RubyClass metaclass, IRubyObject self) { return metaclass == ((RubyBasicObject)self).getMetaClass();}
Icky Hotspot artifact...
Sunday, February 3, 13
def foo selfend def bar fooend 100_000.times do barend
Sunday, February 3, 13
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
# 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
# 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
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
Constants
• Lexical lazily-defined variables
• Redefinable, but usually static
• Single global invalidator (SwitchPoint)
• Mostly due to lexical scoping
• Constant target
Sunday, February 3, 13
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
Foo = 1$bar = 1 def get_foo Fooend def get_bar $barend
Sunday, February 3, 13
# 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
# 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
# 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
# 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
Better Than Java?
• Constant folding
• Lazy static finals can’t fold in Hotspot
• SwitchPoint + constant value can!
• Broke several benchmarks :-)
Sunday, February 3, 13
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
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
# {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
{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
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
Thread Events
• Rare cross-thread interrupts
• kill, raise exception
• Guard call sites, method entry, backedge
• Invalidates everything...hmmm
Sunday, February 3, 13
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
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
JRuby/Java 7 JRuby/Java 7 + indy
Sunday, February 3, 13
base64 richards neural mandelbrot0
1.25
2.5
3.75
5
Tim
es fa
ster
tha
n R
uby
2.0.
0pre
1
JRuby/Java 7 JRuby/Java 7 + indy
Sunday, February 3, 13
base64 richards neural mandelbrot0
1.25
2.5
3.75
5
3.434
2.519
2.048
2.99
3.973
Tim
es fa
ster
tha
n R
uby
2.0.
0pre
1
JRuby/Java 7 JRuby/Java 7 + indy
Sunday, February 3, 13
base64 richards neural mandelbrot0
1.25
2.5
3.75
5
3.434
2.519
2.048
2.99
3.9734.107
2.946
3.84
Tim
es fa
ster
tha
n R
uby
2.0.
0pre
1
JRuby/Java 7 JRuby/Java 7 + indy
Sunday, February 3, 13
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
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
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
Thank you!
• [email protected], @headius
• github/headius/invokebinder
• github/headius/rubyflux
• github/mirah/mirah
• blog.headius.com
Sunday, February 3, 13