1. invokedynamic
Tales from the Trenches
Sunday, February 3, 13
2. Me
• Charles Oliver Nutter
• Programmer my whole life
• Professional Java since 1996
• headius@headius.com, @headius
• “Full time” JRuby guy
• Sun (06-09), Engine Yard (09-12), Red Hat
Sunday, February 3, 13
3. 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
4. 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
5. 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
6. 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
7. 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
8. Promises
• “JRuby plus invokedynamic will be fast”
• “The fully-working optimized OpenJDK
indy impl is just around the corner”
Sunday, February 3, 13
10. 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
11. 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
12. 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
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
14. 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
15. 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
17. 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
18. 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
19. hotspot
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
Sunday, February 3, 13
20. jdk
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
Sunday, February 3, 13
21. 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
24. 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
25. ...Could Be This
class Foo
def initialize(a)
@a = a
end
def show
puts @a
end
end
Sunday, February 3, 13
26. Mirah
class Foo
def initialize(a:int)
@a = a
end
def show
puts @a
end
end
Sunday, February 3, 13
27. Mirah
class Foo
def initialize(a:dynamic)
@a = a
end
def show
puts @a
end
end
Sunday, February 3, 13
29. 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
30. 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
31. 2011
• Wrapping things up for FCS
• Focus on correctness
• Some JIT work landing for perf
• JRuby a primary test case
Sunday, February 3, 13
32. 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
33. 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
34. 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
37. What to Do?
• GA indy perf slower than non-indy!
Sunday, February 3, 13
38. What to Do?
• GA indy perf slower than non-indy!
• Enable indy, knowing perf is bad?
Sunday, February 3, 13
39. 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
40. 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
41. 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
42. 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
43. 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
44. 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
45. 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
46. 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
47. 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
48. 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
49. def foo
bar
end
def bar
baz
end
def baz
sleep
end
foo
Sunday, February 3, 13
50. at
LF pre-JIT
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
51. Anonymous Classes
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)
• Shared class metadata
• Patched versions of existing classes
• Reduced impact on symbol table, permgen
Sunday, February 3, 13
52. at org.jruby.RubyKernel.sleep(RubyKernel.java:801) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLLL_L(LambdaForm.java:1112)
at org.jruby.RubyKernel$INVOKER$s$0$1$sleep.call(RubyKernel$INVOKER$s$0$1$sleep.gen) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH)
sleep
at org.jruby.internal.runtime.methods.JavaMethod$JavaMethodN.call(JavaMethod.java:642) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136)
at org.jruby.internal.runtime.methods.DynamicMethod.call(DynamicMethod.java:197) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625)
at java.lang.invoke.LambdaForm$DMH/692342133.invokeVirtual_LLLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604)
at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLLL_L(LambdaForm.java:1112) at java.lang.invoke.LambdaForm$LFI/1837543557.interpret_L(LambdaForm$LFI)
at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$DMH/1191747167.invokeSpecial_LLLLLL_L(LambdaForm$DMH)
at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm$NFI/792791759.invoke_LLLLLL_L(LambdaForm$NFI) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604)
at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$LFI/662441761.interpret_L(LambdaForm$LFI)
at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LL_L(LambdaForm.java:1097)
at java.lang.invoke.LambdaForm$LFI/1395089624.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH)
at java.lang.invoke.LambdaForm$NFI/792791759.invoke_LLLLLL_L(LambdaForm$NFI) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136)
at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$LFI/1395089624.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625)
at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm$NFI/792791759.invoke_LLLLLL_L(LambdaForm$NFI) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604)
at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$LFI/662441761.interpret_L(LambdaForm$LFI)
at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm$MH/1190524793.invokeExact_MT(LambdaForm$MH)
at java.lang.invoke.LambdaForm$LFI/1254526270.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:599)
at java.lang.invoke.LambdaForm$DMH/1744347043.invokeSpecial_LLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at org.jruby.runtime.invokedynamic.InvocationLinker.invocationFallback(InvocationLinker.java:138)
at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLL_L(LambdaForm.java:1107) at java.lang.invoke.LambdaForm$LFI/1837543557.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$DMH/1304836502.invokeStatic_LLLL_L(LambdaForm$DMH)
at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$DMH/1191747167.invokeSpecial_LLLLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$DMH/1151020327.invokeSpecial_LLLLL_L(LambdaForm$DMH)
at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm$NFI/792791759.invoke_LLLLLL_L(LambdaForm$NFI) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLLL_L(LambdaForm.java:1112)
at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH)
at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136)
at java.lang.invoke.LambdaForm$LFI/874088044.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625)
at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLL_L(LambdaForm.java:1107) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604)
at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$LFI/874088044.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$LFI/1254526270.interpret_L(LambdaForm$LFI)
at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLL_L(LambdaForm.java:1107) at java.lang.invoke.LambdaForm$MH/1451043227.linkToCallSite(LambdaForm$MH)
at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at ruby.__dash_e__.method__0$RUBY$foo(-e:1)
at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm$DMH/1304836502.invokeStatic_LLLL_L(LambdaForm$DMH)
foo
at java.lang.invoke.LambdaForm$LFI/1837543557.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) 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.interpretWithArguments(LambdaForm.java:604) 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$LFI/874088044.interpret_L(LambdaForm$LFI) 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$NamedFunction.invoke_LLLL_L(LambdaForm.java:1107) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136)
at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625)
at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) 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.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm$LFI/1254526270.interpret_L(LambdaForm$LFI)
at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLLL_L(LambdaForm.java:1112) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$DMH/1744347043.invokeSpecial_LLLL_L(LambdaForm$DMH)
at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$LFI/662441761.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLL_L(LambdaForm.java:1107)
at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) 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.interpretName(LambdaForm.java:625) 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.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625)
at java.lang.invoke.LambdaForm$LFI/1837543557.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604)
at java.lang.invoke.LambdaForm$DMH/1191747167.invokeSpecial_LLLLLL_L(LambdaForm$DMH) 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$NFI/792791759.invoke_LLLLLL_L(LambdaForm$NFI) at java.lang.invoke.LambdaForm$LFI/662441761.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$MH/1190524793.invokeExact_MT(LambdaForm$MH) 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.MethodHandle.invokeWithArguments(MethodHandle.java:599) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136)
at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at org.jruby.runtime.invokedynamic.InvocationLinker.invocationFallback(InvocationLinker.java:138) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625)
at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$DMH/1304836502.invokeStatic_LLLL_L(LambdaForm$DMH) 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$DMH/1151020327.invokeSpecial_LLLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$LFI/1837543557.interpret_L(LambdaForm$LFI)
at java.lang.invoke.LambdaForm$NFI/792791759.invoke_LLLLLL_L(LambdaForm$NFI) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLLL_L(LambdaForm.java:1112) 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$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) 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$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136)
at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625)
at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) 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$LFI/1254526270.interpret_L(LambdaForm$LFI) 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$MH/1451043227.linkToCallSite(LambdaForm$MH) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLLL_L(LambdaForm.java:1112)
at java.lang.invoke.LambdaForm$NFI/792791759.invoke_LLLLLL_L(LambdaForm$NFI) at ruby.__dash_e__.method__1$RUBY$bar(-e:1) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH)
at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$DMH/1304836502.invokeStatic_LLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136)
bar
at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm$DMH/1151020327.invokeSpecial_LLLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625)
at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLLL_L(LambdaForm.java:1112) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604)
at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$LFI/1837543557.interpret_L(LambdaForm$LFI)
at java.lang.invoke.LambdaForm$LFI/874088044.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm$DMH/1191747167.invokeSpecial_LLLLLL_L(LambdaForm$DMH)
at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLL_L(LambdaForm.java:1107) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) 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.interpretWithArguments(LambdaForm.java:604) 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$LFI/1254526270.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136)
at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm$DMH/1744347043.invokeSpecial_LLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625)
at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLL_L(LambdaForm.java:1107) 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$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$LFI/1395089624.interpret_L(LambdaForm$LFI)
at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLL_L(LambdaForm.java:1107) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) 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.interpretName(LambdaForm.java:625) 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.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136)
at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm$LFI/874088044.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625)
at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLL_L(LambdaForm.java:1107) 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$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$LFI/1837543557.interpret_L(LambdaForm$LFI)
at java.lang.invoke.LambdaForm$NamedFunction.invoke_LL_L(LambdaForm.java:1097) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm$DMH/1191747167.invokeSpecial_LLLLLL_L(LambdaForm$DMH)
at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm$NFI/792791759.invoke_LLLLLL_L(LambdaForm$NFI)
at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH)
at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm$LFI/1837543557.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136)
at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLLL_L(LambdaForm.java:1112) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625)
at java.lang.invoke.LambdaForm$LFI/662441761.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604)
at java.lang.invoke.LambdaForm$MH/1190524793.invokeExact_MT(LambdaForm$MH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm$LFI/874088044.interpret_L(LambdaForm$LFI)
at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:599) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLL_L(LambdaForm.java:1107)
at org.jruby.runtime.invokedynamic.InvocationLinker.invocationFallback(InvocationLinker.java:138) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH)
at java.lang.invoke.LambdaForm$DMH/1304836502.invokeStatic_LLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$LFI/1837543557.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136)
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.interpretName(LambdaForm.java:625)
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.interpretWithArguments(LambdaForm.java:604)
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$LFI/874088044.interpret_L(LambdaForm$LFI)
at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLL_L(LambdaForm.java:1107)
at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH)
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.invokeWithArguments(LambdaForm.java:1136)
at java.lang.invoke.LambdaForm$LFI/1254526270.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$DMH/1191747167.invokeSpecial_LLLLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625)
at java.lang.invoke.LambdaForm$MH/1451043227.linkToCallSite(LambdaForm$MH) at java.lang.invoke.LambdaForm$NFI/792791759.invoke_LLLLLL_L(LambdaForm$NFI) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604)
at ruby.__dash_e__.method__2$RUBY$baz(-e:1) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$LFI/662441761.interpret_L(LambdaForm$LFI)
at java.lang.invoke.LambdaForm$DMH/1304836502.invokeStatic_LLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LL_L(LambdaForm.java:1097)
baz
at java.lang.invoke.LambdaForm$DMH/1151020327.invokeSpecial_LLLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH)
at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLLL_L(LambdaForm.java:1112) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136)
at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$LFI/1395089624.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625)
at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm$NFI/792791759.invoke_LLLLLL_L(LambdaForm$NFI) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604)
at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$LFI/662441761.interpret_L(LambdaForm$LFI)
at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm$MH/1190524793.invokeExact_MT(LambdaForm$MH)
at java.lang.invoke.LambdaForm$LFI/1254526270.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:599)
at java.lang.invoke.LambdaForm$DMH/1744347043.invokeSpecial_LLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at org.jruby.runtime.invokedynamic.InvocationLinker.invocationFallback(InvocationLinker.java:138)
at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLL_L(LambdaForm.java:1107) at java.lang.invoke.LambdaForm$LFI/1837543557.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$DMH/1304836502.invokeStatic_LLLL_L(LambdaForm$DMH)
at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$DMH/1191747167.invokeSpecial_LLLLLL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$DMH/1151020327.invokeSpecial_LLLLL_L(LambdaForm$DMH)
at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm$NFI/792791759.invoke_LLLLLL_L(LambdaForm$NFI) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLLL_L(LambdaForm.java:1112)
at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH)
at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136)
at java.lang.invoke.LambdaForm$LFI/874088044.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625)
at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLL_L(LambdaForm.java:1107) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604)
at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$LFI/874088044.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm$LFI/1254526270.interpret_L(LambdaForm$LFI)
at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLL_L(LambdaForm.java:1107) at java.lang.invoke.LambdaForm$MH/1451043227.linkToCallSite(LambdaForm$MH)
at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at ruby.__dash_e__.__file__(-e:1)
top-level of script
at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136)
at java.lang.invoke.LambdaForm$LFI/1837543557.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625)
at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLLL_L(LambdaForm.java:1112) at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604)
at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH) at java.lang.invoke.LambdaForm$LFI/874088044.interpret_L(LambdaForm$LFI)
at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136) at java.lang.invoke.LambdaForm$NamedFunction.invoke_LLLL_L(LambdaForm.java:1107)
at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625) at java.lang.invoke.LambdaForm$DMH/1627674070.invokeStatic_LL_L(LambdaForm$DMH)
at java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:604) at java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:1136)
at java.lang.invoke.LambdaForm$LFI/1837543557.interpret_L(LambdaForm$LFI) at java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:625)
Sunday, February 3, 13
53. 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
54. How Good Is It?
• We’ll come back to this
Sunday, February 3, 13
55. 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
56. 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
57. 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
58. Other Pain
• Performance
• Debugging
• Security
• MethodHandle API
Sunday, February 3, 13
60. Performance
• I believe, I really do
Sunday, February 3, 13
61. Performance
• I believe, I really do
• But it has gone back and forth
Sunday, February 3, 13
62. Performance
• I believe, I really do
• But it has gone back and forth
• And I have shamefully not contributed
Sunday, February 3, 13
63. 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
64. 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
65. 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
66. 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
67. 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
72. try/finally
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);
Sunday, February 3, 13
73. Symbolic Arguments
• Easier to follow than indices
• Easier to adapt to different signatures
• Arity less of a challenge
Sunday, February 3, 13
84. def foo
self
end
def bar
foo
end
100_000.times do
bar
end
Sunday, February 3, 13
85. 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
88. 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
89. Constants
• Lexical lazily-defined variables
• Redefinable, but usually static
• Single global invalidator (SwitchPoint)
• Mostly due to lexical scoping
• Constant target
Sunday, February 3, 13
90. 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
91. Foo = 1
$bar = 1
def get_foo
Foo
end
def get_bar
$bar
end
Sunday, February 3, 13
96. Better Than Java?
• Constant folding
• Lazy static finals can’t fold in Hotspot
• SwitchPoint + constant value can!
• Broke several benchmarks :-)
Sunday, February 3, 13
97. Better Than Java?
• Constant folding Fixed in 7
• Lazy static finals can’t fold in Hotspot
• SwitchPoint + constant value can!
• Broke several benchmarks :-)
Sunday, February 3, 13
98. 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
101. 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
103. 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
104. 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
109. Smooth sort of a small array
JRuby 90593
Rubinius 2.0.0rc1 60232.3
MagLev 23954.5
MacRuby 0.12 19609.5
Ruby 2.0.0 19590.7
Ruby 1.9.3 11439
Ruby 1.8.7 4750
0 25000 50000 75000 100000
Iterations per second
Sunday, February 3, 13
110. red/black tree, pure Ruby versus native
jruby + Java ext 0.1
jruby + Ruby 0.29
ruby-2.0.0 + C ext 0.51
ruby-1.9.3 + C ext 0.51
rbx-2.0.0rc1 + Ruby 0.51
macruby-0.12 + Ruby 1.19
maglev + Ruby 1.39
ruby-2.0.0 + Ruby 2.48
ruby-1.9.3 + Ruby 3.96
0 1 2 3 4
Runtime per iteration
Sunday, February 3, 13
111. 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