From 9b521f27bd84cd3eac5c68ffdc03e71bb63b3ac0 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Thu, 23 Mar 2023 00:21:05 -0500 Subject: [PATCH] Start propagating callInfo through call path This is an attempt to start passing callInfo (flags for keyword arguments calls) through the call stack to bring it closer to the target method body. This will allow us to perform appropriate keyword munging on the receiver side without having to store the callInfo in ThreadContext and clear it when done. We can also introduce new encodings for kwargs, such as directly in the args array rather than pre-packaging in a Hash at the point of call. --- .../runtime/methods/DynamicMethod.java | 40 ++++++ .../org/jruby/ir/instructions/CallBase.java | 6 +- .../ir/instructions/ClassSuperInstr.java | 6 +- .../ir/instructions/InstanceSuperInstr.java | 6 +- .../ir/instructions/UnresolvedSuperInstr.java | 6 +- .../jruby/ir/instructions/ZSuperInstr.java | 3 +- .../jruby/ir/runtime/IRRuntimeHelpers.java | 124 +++++++++++++++++- .../ir/targets/indy/ClassSuperInvokeSite.java | 3 +- .../indy/ClassSuperIterInvokeSite.java | 3 +- .../targets/indy/InstanceSuperInvokeSite.java | 3 +- .../indy/InstanceSuperIterInvokeSite.java | 3 +- .../org/jruby/ir/targets/indy/InvokeSite.java | 54 ++++---- .../indy/UnresolvedSuperInvokeSite.java | 3 +- .../indy/UnresolvedSuperIterInvokeSite.java | 3 +- .../ir/targets/indy/ZSuperInvokeSite.java | 3 +- .../simple/NormalInvocationCompiler.java | 33 +++-- .../main/java/org/jruby/runtime/CallSite.java | 40 ++++++ .../main/java/org/jruby/runtime/Helpers.java | 9 ++ .../runtime/callsite/CachingCallSite.java | 54 +++++++- .../callsite/ProfilingCachingCallSite.java | 34 +++++ .../callsite/RefinedCachingCallSite.java | 36 +++++ .../jruby/runtime/callsite/SuperCallSite.java | 106 ++++++++++++--- 22 files changed, 494 insertions(+), 84 deletions(-) diff --git a/core/src/main/java/org/jruby/internal/runtime/methods/DynamicMethod.java b/core/src/main/java/org/jruby/internal/runtime/methods/DynamicMethod.java index c88f60bce8d1..180d3b332f46 100644 --- a/core/src/main/java/org/jruby/internal/runtime/methods/DynamicMethod.java +++ b/core/src/main/java/org/jruby/internal/runtime/methods/DynamicMethod.java @@ -41,6 +41,7 @@ import org.jruby.Ruby; import org.jruby.RubyModule; import org.jruby.RubySymbol; +import org.jruby.ir.runtime.IRRuntimeHelpers; import org.jruby.runtime.Arity; import org.jruby.runtime.Block; import org.jruby.runtime.CallType; @@ -158,6 +159,45 @@ public void setIsBuiltin(boolean isBuiltin) { } } + /** + * A call path specialized for passing keyword arguments. Keywords can be passed + * as a Hash or as a series of values, with the exact configuration being passed + * in callInfo. The default version sets callInfo using thread-local storage. + * + * @param context The thread context for the currently executing thread + * @param self The 'self' or 'receiver' object to use for this call + * @param clazz The Ruby class against which this method is binding + * @param name The incoming name used to invoke this method + * @param callInfo The call info flags for passing keyword configuration + * @param args The arguments and keywords for the method + * @return The result of the call + */ + public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, + String name, int callInfo, IRubyObject... args) { + IRRuntimeHelpers.setCallInfo(context, callInfo); + return call(context, self, clazz, name, args); + } + + /** + * A call path specialized for passing keyword arguments. Keywords can be passed + * as a Hash or as a series of values, with the exact configuration being passed + * in callInfo. The default version sets callInfo using thread-local storage. + * + * @param context The thread context for the currently executing thread + * @param self The 'self' or 'receiver' object to use for this call + * @param clazz The Ruby class against which this method is binding + * @param name The incoming name used to invoke this method + * @param callInfo The call info flags for passing keyword configuration + * @param block The block passed to this invocation + * @param args The arguments and keywords for the method + * @return The result of the call + */ + public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, + String name, int callInfo, Block block, IRubyObject... args) { + IRRuntimeHelpers.setCallInfo(context, callInfo); + return call(context, self, clazz, name, args, block); + } + /** * The minimum 'call' method required for a dynamic method handle. * Subclasses must implement this method, but may implement the other diff --git a/core/src/main/java/org/jruby/ir/instructions/CallBase.java b/core/src/main/java/org/jruby/ir/instructions/CallBase.java index 9675f8779b0d..e8682dbe2949 100644 --- a/core/src/main/java/org/jruby/ir/instructions/CallBase.java +++ b/core/src/main/java/org/jruby/ir/instructions/CallBase.java @@ -539,13 +539,13 @@ public Object interpret(ThreadContext context, StaticScope currScope, DynamicSco IRubyObject[] values = prepareArguments(context, self, currScope, dynamicScope, temp); Block preparedBlock = prepareBlock(context, self, currScope, dynamicScope, temp); - IRRuntimeHelpers.setCallInfo(context, getFlags()); + int callInfo = getFlags(); if (hasLiteralClosure()) { - return callSite.callIter(context, self, object, values, preparedBlock); + return callSite.callIter(context, self, object, callInfo, preparedBlock, values); } - return callSite.call(context, self, object, values, preparedBlock); + return callSite.call(context, self, object, callInfo, preparedBlock, values); } public IRubyObject[] prepareArguments(ThreadContext context, IRubyObject self, StaticScope currScope, DynamicScope dynamicScope, Object[] temp) { diff --git a/core/src/main/java/org/jruby/ir/instructions/ClassSuperInstr.java b/core/src/main/java/org/jruby/ir/instructions/ClassSuperInstr.java index 564226f35dcb..588a9f047b4e 100644 --- a/core/src/main/java/org/jruby/ir/instructions/ClassSuperInstr.java +++ b/core/src/main/java/org/jruby/ir/instructions/ClassSuperInstr.java @@ -97,12 +97,12 @@ public Object interpret(ThreadContext context, StaticScope currScope, DynamicSco IRubyObject[] args = prepareArguments(context, self, currScope, currDynScope, temp); Block block = prepareBlock(context, self, currScope, currDynScope, temp); - IRRuntimeHelpers.setCallInfo(context, getFlags()); + int callInfo = getFlags(); if (isLiteralBlock) { - return IRRuntimeHelpers.unresolvedSuperIter(context, self, args, block); + return IRRuntimeHelpers.unresolvedSuperIter(context, self, callInfo, args, block); } else { - return IRRuntimeHelpers.unresolvedSuper(context, self, args, block); + return IRRuntimeHelpers.unresolvedSuper(context, self, callInfo, args, block); } } diff --git a/core/src/main/java/org/jruby/ir/instructions/InstanceSuperInstr.java b/core/src/main/java/org/jruby/ir/instructions/InstanceSuperInstr.java index 27b685bab142..9ff5f006da67 100644 --- a/core/src/main/java/org/jruby/ir/instructions/InstanceSuperInstr.java +++ b/core/src/main/java/org/jruby/ir/instructions/InstanceSuperInstr.java @@ -131,12 +131,12 @@ public Object interpret(ThreadContext context, StaticScope currScope, DynamicSco Block block = prepareBlock(context, self, currScope, currDynScope, temp); RubyModule definingModule = ((RubyModule) getDefiningModule().retrieve(context, self, currScope, currDynScope, temp)); - IRRuntimeHelpers.setCallInfo(context, getFlags()); + int callInfo = getFlags(); if (isLiteralBlock) { - return IRRuntimeHelpers.instanceSuperIter(context, self, getId(), definingModule, args, block); + return IRRuntimeHelpers.instanceSuperIter(context, self, getId(), definingModule, callInfo, args, block); } else { - return IRRuntimeHelpers.instanceSuper(context, self, getId(), definingModule, args, block); + return IRRuntimeHelpers.instanceSuper(context, self, getId(), definingModule, callInfo, args, block); } } diff --git a/core/src/main/java/org/jruby/ir/instructions/UnresolvedSuperInstr.java b/core/src/main/java/org/jruby/ir/instructions/UnresolvedSuperInstr.java index b50ff615993a..1c371585a119 100644 --- a/core/src/main/java/org/jruby/ir/instructions/UnresolvedSuperInstr.java +++ b/core/src/main/java/org/jruby/ir/instructions/UnresolvedSuperInstr.java @@ -115,12 +115,12 @@ public Object interpret(ThreadContext context, StaticScope currScope, DynamicSco IRubyObject[] args = prepareArguments(context, self, currScope, currDynScope, temp); Block block = prepareBlock(context, self, currScope, currDynScope, temp); - IRRuntimeHelpers.setCallInfo(context, getFlags()); + int flags = getFlags(); if (isLiteralBlock) { - return IRRuntimeHelpers.unresolvedSuperIter(context, self, args, block); + return IRRuntimeHelpers.unresolvedSuperIter(context, self, flags, args, block); } else { - return IRRuntimeHelpers.unresolvedSuper(context, self, args, block); + return IRRuntimeHelpers.unresolvedSuper(context, self, flags, args, block); } } diff --git a/core/src/main/java/org/jruby/ir/instructions/ZSuperInstr.java b/core/src/main/java/org/jruby/ir/instructions/ZSuperInstr.java index 8a8f7ff64fce..dbdce75992d1 100644 --- a/core/src/main/java/org/jruby/ir/instructions/ZSuperInstr.java +++ b/core/src/main/java/org/jruby/ir/instructions/ZSuperInstr.java @@ -81,9 +81,8 @@ public Object interpret(ThreadContext context, StaticScope currScope, DynamicSco IRubyObject[] args = prepareArguments(context, self, currScope, currDynScope, temp); Block block = prepareBlock(context, self, currScope, currDynScope, temp); - IRRuntimeHelpers.setCallInfo(context, getFlags()); - return IRRuntimeHelpers.zSuper(context, self, args, block); + return IRRuntimeHelpers.zSuper(context, self, getFlags(), args, block); } @Override diff --git a/core/src/main/java/org/jruby/ir/runtime/IRRuntimeHelpers.java b/core/src/main/java/org/jruby/ir/runtime/IRRuntimeHelpers.java index 44ca6172a045..2df913b58cb7 100644 --- a/core/src/main/java/org/jruby/ir/runtime/IRRuntimeHelpers.java +++ b/core/src/main/java/org/jruby/ir/runtime/IRRuntimeHelpers.java @@ -1292,11 +1292,21 @@ public static IRubyObject instanceSuperSplatArgs(ThreadContext context, IRubyObj return instanceSuper(context, self, methodName, definingModule, splatArguments(args, splatMap), block); } + @JIT // for JVM6 + public static IRubyObject instanceSuperSplatArgs(ThreadContext context, IRubyObject self, String methodName, RubyModule definingModule, int callInfo, IRubyObject[] args, Block block, boolean[] splatMap) { + return instanceSuper(context, self, methodName, definingModule, callInfo, splatArguments(args, splatMap), block); + } + @JIT // for JVM6 public static IRubyObject instanceSuperIterSplatArgs(ThreadContext context, IRubyObject self, String methodName, RubyModule definingModule, IRubyObject[] args, Block block, boolean[] splatMap) { return instanceSuperIter(context, self, methodName, definingModule, splatArguments(args, splatMap), block); } + @JIT // for JVM6 + public static IRubyObject instanceSuperIterSplatArgs(ThreadContext context, IRubyObject self, String methodName, RubyModule definingModule, int callInfo, IRubyObject[] args, Block block, boolean[] splatMap) { + return instanceSuperIter(context, self, methodName, definingModule, callInfo, splatArguments(args, splatMap), block); + } + @Interp public static IRubyObject instanceSuper(ThreadContext context, IRubyObject self, String id, RubyModule definingModule, IRubyObject[] args, Block block) { CacheEntry entry = getSuperMethodEntry(id, definingModule); @@ -1319,6 +1329,28 @@ public static IRubyObject instanceSuper(ThreadContext context, IRubyObject self, return method.call(context, self, entry.sourceModule, id, args, block); } + @Interp + public static IRubyObject instanceSuper(ThreadContext context, IRubyObject self, String id, RubyModule definingModule, int callInfo, IRubyObject[] args, Block block) { + CacheEntry entry = getSuperMethodEntry(id, definingModule); + DynamicMethod method = entry.method; + + if (method instanceof InstanceMethodInvoker && self instanceof JavaProxy) { + return javaProxySuper( + context, + (JavaProxy) self, + id, + (RubyClass) definingModule, + args, + (InstanceMethodInvoker) method); + } + + if (method.isUndefined()) { + return Helpers.callMethodMissing(context, self, method.getVisibility(), id, CallType.SUPER, callInfo, args, block); + } + + return method.call(context, self, entry.sourceModule, id, callInfo, block, args); + } + /** * Perform a super invocation against a Java proxy, using proxy logic to locate and invoke the appropriate shim * method. @@ -1364,21 +1396,40 @@ public static IRubyObject instanceSuperIter(ThreadContext context, IRubyObject s } } + @Interp + public static IRubyObject instanceSuperIter(ThreadContext context, IRubyObject self, String id, RubyModule definingModule, int callInfo, IRubyObject[] args, Block block) { + try { + return instanceSuper(context, self, id, definingModule, callInfo, args, block); + } finally { + block.escape(); + } + } + private static CacheEntry getSuperMethodEntry(String id, RubyModule definingModule) { RubyClass superClass = definingModule.getMethodLocation().getSuperClass(); return superClass != null ? superClass.searchWithCache(id) : CacheEntry.NULL_CACHE; } - @JIT // for JVM6 + @JIT public static IRubyObject classSuperSplatArgs(ThreadContext context, IRubyObject self, String methodName, RubyModule definingModule, IRubyObject[] args, Block block, boolean[] splatMap) { return classSuper(context, self, methodName, definingModule, splatArguments(args, splatMap), block); } + @JIT + public static IRubyObject classSuperSplatArgs(ThreadContext context, IRubyObject self, String methodName, RubyModule definingModule, int callInfo, IRubyObject[] args, Block block, boolean[] splatMap) { + return classSuper(context, self, methodName, definingModule, callInfo, splatArguments(args, splatMap), block); + } + @JIT // for JVM6 public static IRubyObject classSuperIterSplatArgs(ThreadContext context, IRubyObject self, String methodName, RubyModule definingModule, IRubyObject[] args, Block block, boolean[] splatMap) { return classSuperIter(context, self, methodName, definingModule, splatArguments(args, splatMap), block); } + @JIT // for JVM6 + public static IRubyObject classSuperIterSplatArgs(ThreadContext context, IRubyObject self, String methodName, RubyModule definingModule, int callInfo, IRubyObject[] args, Block block, boolean[] splatMap) { + return classSuperIter(context, self, methodName, definingModule, callInfo, splatArguments(args, splatMap), block); + } + @Interp public static IRubyObject classSuper(ThreadContext context, IRubyObject self, String id, RubyModule definingModule, IRubyObject[] args, Block block) { CacheEntry entry = getSuperMethodEntry(id, definingModule.getMetaClass()); @@ -1391,6 +1442,18 @@ public static IRubyObject classSuper(ThreadContext context, IRubyObject self, St return method.call(context, self, entry.sourceModule, id, args, block); } + @Interp + public static IRubyObject classSuper(ThreadContext context, IRubyObject self, String id, RubyModule definingModule, int callInfo, IRubyObject[] args, Block block) { + CacheEntry entry = getSuperMethodEntry(id, definingModule.getMetaClass()); + DynamicMethod method = entry.method; + + if (method.isUndefined()) { + return Helpers.callMethodMissing(context, self, method.getVisibility(), id, CallType.SUPER, callInfo, args, block); + } + + return method.call(context, self, entry.sourceModule, id, callInfo, block, args); + } + @Interp public static IRubyObject classSuperIter(ThreadContext context, IRubyObject self, String id, RubyModule definingModule, IRubyObject[] args, Block block) { try { @@ -1400,16 +1463,35 @@ public static IRubyObject classSuperIter(ThreadContext context, IRubyObject self } } + @Interp + public static IRubyObject classSuperIter(ThreadContext context, IRubyObject self, String id, RubyModule definingModule, int callInfo, IRubyObject[] args, Block block) { + try { + return classSuper(context, self, id, definingModule, callInfo, args, block); + } finally { + block.escape(); + } + } + @JIT public static IRubyObject unresolvedSuperSplatArgs(ThreadContext context, IRubyObject self, IRubyObject[] args, Block block, boolean[] splatMap) { return unresolvedSuper(context, self, splatArguments(args, splatMap), block); } + @JIT + public static IRubyObject unresolvedSuperSplatArgs(ThreadContext context, IRubyObject self, int callInfo, IRubyObject[] args, Block block, boolean[] splatMap) { + return unresolvedSuper(context, self, callInfo, splatArguments(args, splatMap), block); + } + @JIT public static IRubyObject unresolvedSuperIterSplatArgs(ThreadContext context, IRubyObject self, IRubyObject[] args, Block block, boolean[] splatMap) { return unresolvedSuperIter(context, self, splatArguments(args, splatMap), block); } + @JIT + public static IRubyObject unresolvedSuperIterSplatArgs(ThreadContext context, IRubyObject self, int callInfo, IRubyObject[] args, Block block, boolean[] splatMap) { + return unresolvedSuperIter(context, self, callInfo, splatArguments(args, splatMap), block); + } + @Interp public static IRubyObject unresolvedSuper(ThreadContext context, IRubyObject self, IRubyObject[] args, Block block) { // We have to rely on the frame stack to find the implementation class @@ -1431,6 +1513,27 @@ public static IRubyObject unresolvedSuper(ThreadContext context, IRubyObject sel return rVal; } + @Interp + public static IRubyObject unresolvedSuper(ThreadContext context, IRubyObject self, int callInfo, IRubyObject[] args, Block block) { + // We have to rely on the frame stack to find the implementation class + RubyModule klazz = context.getFrameKlazz(); + String methodName = context.getFrameName(); + + Helpers.checkSuperDisabledOrOutOfMethod(context, klazz, methodName); + + RubyClass superClass = searchNormalSuperclass(klazz); + CacheEntry entry = superClass != null ? superClass.searchWithCache(methodName) : CacheEntry.NULL_CACHE; + + IRubyObject rVal; + if (entry.method.isUndefined()) { + rVal = Helpers.callMethodMissing(context, self, entry.method.getVisibility(), methodName, CallType.SUPER, callInfo, args, block); + } else { + rVal = entry.method.call(context, self, entry.sourceModule, methodName, callInfo, block, args); + } + + return rVal; + } + @Interp public static IRubyObject unresolvedSuperIter(ThreadContext context, IRubyObject self, IRubyObject[] args, Block block) { try { @@ -1440,6 +1543,15 @@ public static IRubyObject unresolvedSuperIter(ThreadContext context, IRubyObject } } + @Interp + public static IRubyObject unresolvedSuperIter(ThreadContext context, IRubyObject self, int callInfo, IRubyObject[] args, Block block) { + try { + return unresolvedSuper(context, self, callInfo, args, block); + } finally { + block.escape(); + } + } + // MRI: vm_search_normal_superclass private static RubyClass searchNormalSuperclass(RubyModule klazz) { // Unwrap refinements, since super should always dispatch back to the refined class @@ -1456,11 +1568,21 @@ public static IRubyObject zSuperSplatArgs(ThreadContext context, IRubyObject sel return unresolvedSuper(context, self, splatArguments(args, splatMap), block); } + public static IRubyObject zSuperSplatArgs(ThreadContext context, IRubyObject self, int callInfo, IRubyObject[] args, Block block, boolean[] splatMap) { + if (block == null || !block.isGiven()) block = context.getFrameBlock(); + return unresolvedSuper(context, self, callInfo, splatArguments(args, splatMap), block); + } + public static IRubyObject zSuper(ThreadContext context, IRubyObject self, IRubyObject[] args, Block block) { if (block == null || !block.isGiven()) block = context.getFrameBlock(); return unresolvedSuper(context, self, args, block); } + public static IRubyObject zSuper(ThreadContext context, IRubyObject self, int callInfo, IRubyObject[] args, Block block) { + if (block == null || !block.isGiven()) block = context.getFrameBlock(); + return unresolvedSuper(context, self, callInfo, args, block); + } + public static IRubyObject[] splatArguments(IRubyObject[] args, boolean[] splatMap) { if (splatMap != null && splatMap.length > 0) { int count = 0; diff --git a/core/src/main/java/org/jruby/ir/targets/indy/ClassSuperInvokeSite.java b/core/src/main/java/org/jruby/ir/targets/indy/ClassSuperInvokeSite.java index 29f16c53af54..7f81ddfce407 100644 --- a/core/src/main/java/org/jruby/ir/targets/indy/ClassSuperInvokeSite.java +++ b/core/src/main/java/org/jruby/ir/targets/indy/ClassSuperInvokeSite.java @@ -26,7 +26,6 @@ protected RubyClass getSuperClass(RubyClass definingModule) { public IRubyObject invoke(ThreadContext context, IRubyObject caller, IRubyObject self, RubyClass definingModule, IRubyObject[] args, Block block) throws Throwable { // TODO: get rid of caller // TODO: caching - IRRuntimeHelpers.setCallInfo(context, flags); - return IRRuntimeHelpers.classSuperSplatArgs(context, self, superName, definingModule, args, block, splatMap); + return IRRuntimeHelpers.classSuperSplatArgs(context, self, superName, definingModule, flags, args, block, splatMap); } } diff --git a/core/src/main/java/org/jruby/ir/targets/indy/ClassSuperIterInvokeSite.java b/core/src/main/java/org/jruby/ir/targets/indy/ClassSuperIterInvokeSite.java index 7f5db24ea04d..e2c5ad0d3e8d 100644 --- a/core/src/main/java/org/jruby/ir/targets/indy/ClassSuperIterInvokeSite.java +++ b/core/src/main/java/org/jruby/ir/targets/indy/ClassSuperIterInvokeSite.java @@ -26,7 +26,6 @@ protected RubyClass getSuperClass(RubyClass definingModule) { public IRubyObject invoke(ThreadContext context, IRubyObject caller, IRubyObject self, RubyClass definingModule, IRubyObject[] args, Block block) throws Throwable { // TODO: get rid of caller // TODO: caching - IRRuntimeHelpers.setCallInfo(context, flags); - return IRRuntimeHelpers.classSuperIterSplatArgs(context, self, superName, definingModule, args, block, splatMap); + return IRRuntimeHelpers.classSuperIterSplatArgs(context, self, superName, definingModule, flags, args, block, splatMap); } } diff --git a/core/src/main/java/org/jruby/ir/targets/indy/InstanceSuperInvokeSite.java b/core/src/main/java/org/jruby/ir/targets/indy/InstanceSuperInvokeSite.java index 22330a9f621a..f1e8591cca47 100644 --- a/core/src/main/java/org/jruby/ir/targets/indy/InstanceSuperInvokeSite.java +++ b/core/src/main/java/org/jruby/ir/targets/indy/InstanceSuperInvokeSite.java @@ -26,7 +26,6 @@ protected RubyClass getSuperClass(RubyClass definingModule) { public IRubyObject invoke(ThreadContext context, IRubyObject caller, IRubyObject self, RubyClass definingModule, IRubyObject[] args, Block block) throws Throwable { // TODO: get rid of caller // TODO: caching - IRRuntimeHelpers.setCallInfo(context, flags); - return IRRuntimeHelpers.instanceSuperSplatArgs(context, self, superName, definingModule, args, block, splatMap); + return IRRuntimeHelpers.instanceSuperSplatArgs(context, self, superName, definingModule, flags, args, block, splatMap); } } diff --git a/core/src/main/java/org/jruby/ir/targets/indy/InstanceSuperIterInvokeSite.java b/core/src/main/java/org/jruby/ir/targets/indy/InstanceSuperIterInvokeSite.java index 308f27d8554f..5a7e42e1fa12 100644 --- a/core/src/main/java/org/jruby/ir/targets/indy/InstanceSuperIterInvokeSite.java +++ b/core/src/main/java/org/jruby/ir/targets/indy/InstanceSuperIterInvokeSite.java @@ -26,7 +26,6 @@ protected RubyClass getSuperClass(RubyClass definingModule) { public IRubyObject invoke(ThreadContext context, IRubyObject caller, IRubyObject self, RubyClass definingModule, IRubyObject[] args, Block block) throws Throwable { // TODO: get rid of caller // TODO: caching - IRRuntimeHelpers.setCallInfo(context, flags); - return IRRuntimeHelpers.instanceSuperIterSplatArgs(context, self, superName, definingModule, args, block, splatMap); + return IRRuntimeHelpers.instanceSuperIterSplatArgs(context, self, superName, definingModule, flags, args, block, splatMap); } } diff --git a/core/src/main/java/org/jruby/ir/targets/indy/InvokeSite.java b/core/src/main/java/org/jruby/ir/targets/indy/InvokeSite.java index d4956c9cc8ca..3de2f17f4e71 100644 --- a/core/src/main/java/org/jruby/ir/targets/indy/InvokeSite.java +++ b/core/src/main/java/org/jruby/ir/targets/indy/InvokeSite.java @@ -172,7 +172,8 @@ public IRubyObject invoke(ThreadContext context, IRubyObject caller, IRubyObject mh = getHandle(self, entry); } - finishBinding(entry, mh, self, selfClass, switchPoint); + boolean needsCallInfo = arity != -1; + finishBinding(entry, mh, self, selfClass, switchPoint, needsCallInfo); return performIndirectCall(context, self, args, block, methodName, passSymbol, entry); } @@ -195,7 +196,7 @@ public IRubyObject invoke(ThreadContext context, IRubyObject self, IRubyObject[] mh = getHandle(self, entry); } - finishBinding(entry, mh, self, selfClass, switchPoint); + finishBinding(entry, mh, self, selfClass, switchPoint, arity != -1); return performIndirectCall(context, self, args, block, methodName, passSymbol, entry); } @@ -212,21 +213,23 @@ private CacheEntry methodMissingEntry(ThreadContext context, RubyClass selfClass return Helpers.createMethodMissingEntry(context, selfClass, callType, visibility, entry.token, methodName); } - private void finishBinding(CacheEntry entry, MethodHandle mh, IRubyObject self, RubyClass selfClass, SwitchPoint switchPoint) { + private void finishBinding(CacheEntry entry, MethodHandle mh, IRubyObject self, RubyClass selfClass, SwitchPoint switchPoint, boolean needsCallInfo) { if (literalClosure) { mh = Binder.from(mh.type()) .tryFinally(getBlockEscape(signature)) .invoke(mh); } - SmartHandle callInfoWrapper; - SmartBinder baseBinder = SmartBinder.from(signature.changeReturn(void.class)).permute("context"); - if (flags == 0) { - callInfoWrapper = baseBinder.invokeVirtualQuiet(LOOKUP, "clearCallInfo"); - } else { - callInfoWrapper = baseBinder.append("flags", flags).invokeStaticQuiet(LOOKUP, IRRuntimeHelpers.class, "setCallInfo"); + if (needsCallInfo) { + SmartHandle callInfoWrapper; + SmartBinder baseBinder = SmartBinder.from(signature.changeReturn(void.class)).permute("context"); + if (flags == 0) { + callInfoWrapper = baseBinder.invokeVirtualQuiet(LOOKUP, "clearCallInfo"); + } else { + callInfoWrapper = baseBinder.append("flags", flags).invokeStaticQuiet(LOOKUP, IRRuntimeHelpers.class, "setCallInfo"); + } + mh = foldArguments(mh, callInfoWrapper.handle()); } - mh = foldArguments(mh, callInfoWrapper.handle()); updateInvocationTarget(mh, self, selfClass, entry.method, switchPoint); } @@ -235,14 +238,12 @@ private IRubyObject performIndirectCall(ThreadContext context, IRubyObject self, RubyModule sourceModule = entry.sourceModule; DynamicMethod method = entry.method; - IRRuntimeHelpers.setCallInfo(context, flags); - if (literalClosure) { try { if (passSymbol) { - return method.call(context, self, sourceModule, "method_missing", Helpers.arrayOf(context.runtime.newSymbol(methodName), args), block); + return method.call(context, self, sourceModule, "method_missing", flags, block, Helpers.arrayOf(context.runtime.newSymbol(methodName), args)); } else { - return method.call(context, self, sourceModule, methodName, args, block); + return method.call(context, self, sourceModule, methodName, flags, block, args); } } finally { block.escape(); @@ -250,9 +251,9 @@ private IRubyObject performIndirectCall(ThreadContext context, IRubyObject self, } if (passSymbol) { - return method.call(context, self, sourceModule, methodName, Helpers.arrayOf(context.runtime.newSymbol(methodName), args), block); + return method.call(context, self, sourceModule, methodName, flags, block, Helpers.arrayOf(context.runtime.newSymbol(methodName), args)); } else { - return method.call(context, self, sourceModule, methodName, args, block); + return method.call(context, self, sourceModule, methodName, flags, block, args); } } @@ -280,16 +281,15 @@ public IRubyObject fail(ThreadContext context, IRubyObject caller, IRubyObject s String name = methodName; CacheEntry entry = cache; - IRRuntimeHelpers.setCallInfo(context, flags); if (entry.typeOk(selfClass)) { - return entry.method.call(context, self, entry.sourceModule, name, args, block); + return entry.method.call(context, self, entry.sourceModule, name, flags, block, args); } entry = selfClass.searchWithCache(name); if (methodMissing(entry, caller)) { - return callMethodMissing(entry, callType, context, self, selfClass, name, args, block); + return callMethodMissing(entry, callType, context, self, selfClass, name, flags, args, block); } cache = entry; @@ -305,16 +305,14 @@ public IRubyObject failf(ThreadContext context, IRubyObject self, IRubyObject[] String name = methodName; CacheEntry entry = cache; - IRRuntimeHelpers.setCallInfo(context, flags); - if (entry.typeOk(selfClass)) { - return entry.method.call(context, self, entry.sourceModule, name, args, block); + return entry.method.call(context, self, entry.sourceModule, name, flags, block, args); } entry = selfClass.searchWithCache(name); if (methodMissing(entry)) { - return callMethodMissing(entry, callType, context, self, selfClass, name, args, block); + return callMethodMissing(entry, callType, context, self, selfClass, name, flags, args, block); } cache = entry; @@ -935,6 +933,14 @@ public static IRubyObject callMethodMissing(CacheEntry entry, CallType callType, return Helpers.callMethodMissing(context, self, selfClass, entry.method.getVisibility(), name, callType, args, block); } + /** + * Variable arity method_missing invocation. Arity zero also passes through here. + */ + public static IRubyObject callMethodMissing(CacheEntry entry, CallType callType, ThreadContext context, IRubyObject self, + RubyClass selfClass, String name, int callInfo, IRubyObject[] args, Block block) { + return Helpers.callMethodMissing(context, self, selfClass, entry.method.getVisibility(), name, callType, callInfo, args, block); + } + /** * Arity one method_missing invocation */ @@ -943,7 +949,6 @@ public static IRubyObject callMethodMissing(CacheEntry entry, CallType callType, return Helpers.callMethodMissing(context, self, selfClass, entry.method.getVisibility(), name, callType, arg0, block); } - /** * Arity two method_missing invocation */ @@ -952,7 +957,6 @@ public static IRubyObject callMethodMissing(CacheEntry entry, CallType callType, return Helpers.callMethodMissing(context, self, selfClass, entry.method.getVisibility(), name, callType, arg0, arg1, block); } - /** * Arity three method_missing invocation */ diff --git a/core/src/main/java/org/jruby/ir/targets/indy/UnresolvedSuperInvokeSite.java b/core/src/main/java/org/jruby/ir/targets/indy/UnresolvedSuperInvokeSite.java index 8c0d86001be1..3e0e3e29042d 100644 --- a/core/src/main/java/org/jruby/ir/targets/indy/UnresolvedSuperInvokeSite.java +++ b/core/src/main/java/org/jruby/ir/targets/indy/UnresolvedSuperInvokeSite.java @@ -19,8 +19,7 @@ public UnresolvedSuperInvokeSite(MethodType type, String name, String splatmapSt public IRubyObject invoke(ThreadContext context, IRubyObject caller, IRubyObject self, RubyClass definingModule, IRubyObject[] args, Block block) throws Throwable { // TODO: get rid of caller // TODO: caching - IRRuntimeHelpers.setCallInfo(context, flags); - return IRRuntimeHelpers.unresolvedSuperSplatArgs(context, self, args, block, splatMap); + return IRRuntimeHelpers.unresolvedSuperSplatArgs(context, self, flags, args, block, splatMap); } public IRubyObject fail(ThreadContext context, IRubyObject caller, IRubyObject self, RubyClass definingModule, IRubyObject[] args, Block block) throws Throwable { diff --git a/core/src/main/java/org/jruby/ir/targets/indy/UnresolvedSuperIterInvokeSite.java b/core/src/main/java/org/jruby/ir/targets/indy/UnresolvedSuperIterInvokeSite.java index c2a755d56724..b4150cb0a9c1 100644 --- a/core/src/main/java/org/jruby/ir/targets/indy/UnresolvedSuperIterInvokeSite.java +++ b/core/src/main/java/org/jruby/ir/targets/indy/UnresolvedSuperIterInvokeSite.java @@ -19,8 +19,7 @@ public UnresolvedSuperIterInvokeSite(MethodType type, String name, String splatm public IRubyObject invoke(ThreadContext context, IRubyObject caller, IRubyObject self, RubyClass definingModule, IRubyObject[] args, Block block) throws Throwable { // TODO: get rid of caller // TODO: caching - IRRuntimeHelpers.setCallInfo(context, flags); - return IRRuntimeHelpers.unresolvedSuperIterSplatArgs(context, self, args, block, splatMap); + return IRRuntimeHelpers.unresolvedSuperIterSplatArgs(context, self, flags, args, block, splatMap); } public IRubyObject fail(ThreadContext context, IRubyObject caller, IRubyObject self, RubyClass definingModule, IRubyObject[] args, Block block) throws Throwable { diff --git a/core/src/main/java/org/jruby/ir/targets/indy/ZSuperInvokeSite.java b/core/src/main/java/org/jruby/ir/targets/indy/ZSuperInvokeSite.java index a5e73d02c58f..1f3956acaf3c 100644 --- a/core/src/main/java/org/jruby/ir/targets/indy/ZSuperInvokeSite.java +++ b/core/src/main/java/org/jruby/ir/targets/indy/ZSuperInvokeSite.java @@ -20,8 +20,7 @@ public IRubyObject invoke(ThreadContext context, IRubyObject caller, IRubyObject // TODO: get rid of caller // TODO: caching if (block == null || !block.isGiven()) block = context.getFrameBlock(); - IRRuntimeHelpers.setCallInfo(context, flags); - return IRRuntimeHelpers.zSuperSplatArgs(context, self, args, block, splatMap); + return IRRuntimeHelpers.zSuperSplatArgs(context, self, flags, args, block, splatMap); } public IRubyObject fail(ThreadContext context, IRubyObject caller, IRubyObject self, RubyClass definingModule, IRubyObject[] args, Block block) throws Throwable { diff --git a/core/src/main/java/org/jruby/ir/targets/simple/NormalInvocationCompiler.java b/core/src/main/java/org/jruby/ir/targets/simple/NormalInvocationCompiler.java index 09cf32bb4ca7..a87452c52a97 100644 --- a/core/src/main/java/org/jruby/ir/targets/simple/NormalInvocationCompiler.java +++ b/core/src/main/java/org/jruby/ir/targets/simple/NormalInvocationCompiler.java @@ -74,6 +74,8 @@ public void invoke(String file, int lineNumber, String scopeFieldName, CallBase MethodType incoming, outgoing; String incomingSig, outgoingSig; + boolean needsCallInfo = true; + IRBytecodeAdapter.BlockPassType blockPassType = IRBytecodeAdapter.BlockPassType.fromIR(call); boolean blockGiven = blockPassType.given(); boolean functional = call.getCallType() == CallType.FUNCTIONAL || call.getCallType() == CallType.VARIABLE; @@ -81,8 +83,9 @@ public void invoke(String file, int lineNumber, String scopeFieldName, CallBase if (blockGiven) { switch (arity) { case -1: + needsCallInfo = false; incoming = MethodType.methodType(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT_ARRAY, Block.class)); - outgoing = MethodType.methodType(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT_ARRAY, Block.class)); + outgoing = MethodType.methodType(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, int.class, Block.class, JVM.OBJECT_ARRAY)); break; case 0: case 1: @@ -92,15 +95,16 @@ public void invoke(String file, int lineNumber, String scopeFieldName, CallBase outgoing = MethodType.methodType(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, arity, Block.class)); break; default: + needsCallInfo = false; incoming = MethodType.methodType(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, arity, Block.class)); - outgoing = MethodType.methodType(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT_ARRAY, Block.class)); + outgoing = MethodType.methodType(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, int.class, Block.class, JVM.OBJECT_ARRAY)); break; } } else { switch (arity) { case -1: incoming = MethodType.methodType(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT_ARRAY)); - outgoing = MethodType.methodType(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT_ARRAY)); + outgoing = MethodType.methodType(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, int.class, JVM.OBJECT_ARRAY)); break; case 0: case 1: @@ -111,7 +115,7 @@ public void invoke(String file, int lineNumber, String scopeFieldName, CallBase break; default: incoming = MethodType.methodType(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, arity)); - outgoing = MethodType.methodType(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT_ARRAY)); + outgoing = MethodType.methodType(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, int.class, JVM.OBJECT_ARRAY)); break; } } @@ -119,8 +123,9 @@ public void invoke(String file, int lineNumber, String scopeFieldName, CallBase if (blockGiven) { switch (arity) { case -1: + needsCallInfo = false; incoming = MethodType.methodType(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, JVM.OBJECT_ARRAY, Block.class)); - outgoing = MethodType.methodType(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, JVM.OBJECT_ARRAY, Block.class)); + outgoing = MethodType.methodType(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, int.class, Block.class, JVM.OBJECT_ARRAY)); break; case 0: case 1: @@ -130,15 +135,17 @@ public void invoke(String file, int lineNumber, String scopeFieldName, CallBase outgoing = MethodType.methodType(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, JVM.OBJECT, arity, Block.class)); break; default: + needsCallInfo = false; incoming = MethodType.methodType(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, JVM.OBJECT, arity, Block.class)); - outgoing = MethodType.methodType(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, JVM.OBJECT_ARRAY, Block.class)); + outgoing = MethodType.methodType(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, int.class, Block.class, JVM.OBJECT_ARRAY)); break; } } else { switch (arity) { case -1: + needsCallInfo = false; incoming = MethodType.methodType(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, JVM.OBJECT_ARRAY)); - outgoing = MethodType.methodType(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, JVM.OBJECT_ARRAY)); + outgoing = MethodType.methodType(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, int.class, JVM.OBJECT_ARRAY)); break; case 0: case 1: @@ -148,8 +155,9 @@ public void invoke(String file, int lineNumber, String scopeFieldName, CallBase outgoing = MethodType.methodType(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, JVM.OBJECT, arity)); break; default: + needsCallInfo = false; incoming = MethodType.methodType(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, JVM.OBJECT, arity)); - outgoing = MethodType.methodType(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, JVM.OBJECT_ARRAY)); + outgoing = MethodType.methodType(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, int.class, JVM.OBJECT_ARRAY)); break; } } @@ -179,6 +187,10 @@ public void invoke(String file, int lineNumber, String scopeFieldName, CallBase switch (arity) { case -1: + compiler.adapter.pushInt(call.getFlags()); + if (blockGiven) compiler.adapter.aload(selfBase + 2); + compiler.adapter.aload(selfBase + 1); + break; case 1: compiler.adapter.aload(selfBase + 1); if (blockGiven) compiler.adapter.aload(selfBase + 2); @@ -198,8 +210,9 @@ public void invoke(String file, int lineNumber, String scopeFieldName, CallBase if (blockGiven) compiler.adapter.aload(selfBase + 4); break; default: - IRBytecodeAdapter.buildArrayFromLocals(compiler.adapter, selfBase + 1, arity); + compiler.adapter.pushInt(call.getFlags()); if (blockGiven) compiler.adapter.aload(selfBase + 1 + arity); + IRBytecodeAdapter.buildArrayFromLocals(compiler.adapter, selfBase + 1, arity); break; } @@ -211,7 +224,7 @@ public void invoke(String file, int lineNumber, String scopeFieldName, CallBase }); // now set up callInfo and call the method - setCallInfo(call.getFlags()); + if (needsCallInfo) setCallInfo(call.getFlags()); compiler.adapter.invokestatic(clsName, methodName, incomingSig); } diff --git a/core/src/main/java/org/jruby/runtime/CallSite.java b/core/src/main/java/org/jruby/runtime/CallSite.java index 2f379099ba89..6202604e6dd9 100644 --- a/core/src/main/java/org/jruby/runtime/CallSite.java +++ b/core/src/main/java/org/jruby/runtime/CallSite.java @@ -162,6 +162,31 @@ public IRubyObject fcall(ThreadContext context, IRubyObject self, double flote) */ public abstract IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject self, IRubyObject... args); + /** + * Call the site's method against the target object passing arguments. + * + * @param context the ThreadContext for the current thread + * @param caller the caller, for visibility checks + * @param self the target object to call against + * @param callInfo the keyword call info + * @param args the arguments to pass + * @return the result of the call + */ + public abstract IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject self, int callInfo, IRubyObject... args); + + /** + * Call the site's method against the target object passing arguments. + * + * @param context the ThreadContext for the current thread + * @param caller the caller, for visibility checks + * @param self the target object to call against + * @param callInfo the keyword call info + * @param block the block for the call + * @param args the arguments to pass + * @return the result of the call + */ + public abstract IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject self, int callInfo, Block block, IRubyObject... args); + /** * Call the site's method against the target object passing arguments. * @@ -335,6 +360,21 @@ public IRubyObject fcall(ThreadContext context, IRubyObject self, double flote) */ public abstract IRubyObject callIter(ThreadContext context, IRubyObject caller, IRubyObject self, IRubyObject[] args, Block block); + /** + * Call the site's method against the target object passing arguments and + * a literal block. This version handles break jumps by returning their + * value if this is the appropriate place in the call stack to do so. + * + * @param context the ThreadContext for the current thread + * @param caller the caller, for visibility checks + * @param self the target object to call against + * @param callInfo the keyword call info + * @param block the literal block to pass + * @param args the arguments to pass + * @return the result of the call + */ + public abstract IRubyObject callIter(ThreadContext context, IRubyObject caller, IRubyObject self, int callInfo, Block block, IRubyObject... args); + /** * Call the site's method against the target object passing arguments and * a literal block. This version handles break jumps by returning their diff --git a/core/src/main/java/org/jruby/runtime/Helpers.java b/core/src/main/java/org/jruby/runtime/Helpers.java index 7786cbd7865d..e437a03fc922 100644 --- a/core/src/main/java/org/jruby/runtime/Helpers.java +++ b/core/src/main/java/org/jruby/runtime/Helpers.java @@ -117,11 +117,20 @@ public static IRubyObject callMethodMissing(ThreadContext context, IRubyObject s return selectMethodMissing(context, klass, visibility, name, callType).call(context, self, klass, name, args, block); } + public static IRubyObject callMethodMissing(ThreadContext context, IRubyObject self, RubyClass klass, Visibility visibility, String name, CallType callType, int callInfo, IRubyObject[] args, Block block) { + return selectMethodMissing(context, klass, visibility, name, callType).call(context, self, klass, name, callInfo, block, args); + } + public static IRubyObject callMethodMissing(ThreadContext context, IRubyObject receiver, Visibility visibility, String name, CallType callType, IRubyObject[] args, Block block) { final RubyClass klass = getMetaClass(receiver); return selectMethodMissing(context, klass, visibility, name, callType).call(context, receiver, klass, name, args, block); } + public static IRubyObject callMethodMissing(ThreadContext context, IRubyObject receiver, Visibility visibility, String name, CallType callType, int callInfo, IRubyObject[] args, Block block) { + final RubyClass klass = getMetaClass(receiver); + return selectMethodMissing(context, klass, visibility, name, callType).call(context, receiver, klass, name, callInfo, block, args); + } + public static IRubyObject callMethodMissing(ThreadContext context, IRubyObject self, RubyClass klass, Visibility visibility, String name, CallType callType, IRubyObject arg0, Block block) { return selectMethodMissing(context, klass, visibility, name, callType).call(context, self, klass, name, arg0, block); } diff --git a/core/src/main/java/org/jruby/runtime/callsite/CachingCallSite.java b/core/src/main/java/org/jruby/runtime/callsite/CachingCallSite.java index 42e60c742217..c6c034a8446b 100644 --- a/core/src/main/java/org/jruby/runtime/callsite/CachingCallSite.java +++ b/core/src/main/java/org/jruby/runtime/callsite/CachingCallSite.java @@ -77,10 +77,25 @@ public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject s return cacheAndCall(context, caller, self, selfType, args); } + @Override + public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject self, int callInfo, IRubyObject... args) { + RubyClass selfType = getMetaClass(self); + // This must be retrieved *once* to avoid racing with other threads. + CacheEntry cache = this.cache; + if (cache.typeOk(selfType)) { + return cache.method.call(context, self, cache.sourceModule, methodName, callInfo, args); + } + return cacheAndCall(context, caller, self, selfType, callInfo, args); + } + public IRubyObject fcall(ThreadContext context, IRubyObject self, IRubyObject... args) { return call(context, self, self, args); } + public IRubyObject fcall(ThreadContext context, IRubyObject self, int callInfo, IRubyObject... args) { + return call(context, self, self, callInfo, args); + } + @Override public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject self, IRubyObject[] args, Block block) { RubyClass selfType = getMetaClass(self); @@ -96,6 +111,21 @@ public IRubyObject fcall(ThreadContext context, IRubyObject self, IRubyObject[] return call(context, self, self, args, block); } + public IRubyObject fcall(ThreadContext context, IRubyObject self, int fcall, Block block, IRubyObject... args) { + return call(context, self, self, fcall, block, args); + } + + @Override + public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject self, int callInfo, Block block, IRubyObject... args) { + RubyClass selfType = getMetaClass(self); + // This must be retrieved *once* to avoid racing with other threads. + CacheEntry cache = this.cache; + if (cache.typeOk(selfType)) { + return cache.method.call(context, self, cache.sourceModule, methodName, callInfo, block, args); + } + return cacheAndCall(context, caller, self, selfType, callInfo, block, args); + } + @Override public IRubyObject callIter(ThreadContext context, IRubyObject caller, IRubyObject self, IRubyObject[] args, Block block) { @@ -106,10 +136,20 @@ public IRubyObject callIter(ThreadContext context, IRubyObject caller, IRubyObje } } + @Override + public IRubyObject callIter(ThreadContext context, IRubyObject caller, IRubyObject self, + int callInfo, Block block, IRubyObject... args) { + try { + return call(context, caller, self, callInfo, block, args); + } finally { + block.escape(); + } + } + public IRubyObject fcallIter(ThreadContext context, IRubyObject self, - IRubyObject[] args, Block block) { + int callInfo, Block block, IRubyObject[] args) { try { - return call(context, self, self, args, block); + return call(context, self, self, callInfo, block, args); } finally { block.escape(); } @@ -451,11 +491,21 @@ protected IRubyObject cacheAndCall(ThreadContext context, IRubyObject caller, IR return entry.method.call(context, self, entry.sourceModule, methodName, args); } + protected IRubyObject cacheAndCall(ThreadContext context, IRubyObject caller, IRubyObject self, RubyClass selfType, int callInfo, Block block, IRubyObject... args) { + CacheEntry entry = populateCacheEntry(caller, selfType, context, self); + return entry.method.call(context, self, entry.sourceModule, methodName, callInfo, block, args); + } + protected IRubyObject cacheAndCall(ThreadContext context, IRubyObject caller, IRubyObject self, RubyClass selfType) { CacheEntry entry = populateCacheEntry(caller, selfType, context, self); return entry.method.call(context, self, entry.sourceModule, methodName); } + protected IRubyObject cacheAndCall(ThreadContext context, IRubyObject caller, IRubyObject self, RubyClass selfType, int callInfo, IRubyObject[] args) { + CacheEntry entry = populateCacheEntry(caller, selfType, context, self); + return entry.method.call(context, self, entry.sourceModule, methodName, callInfo, args); + } + protected IRubyObject cacheAndCall(ThreadContext context, IRubyObject caller, IRubyObject self, RubyClass selfType, Block block) { CacheEntry entry = populateCacheEntry(caller, selfType, context, self); return entry.method.call(context, self, entry.sourceModule, methodName, block); diff --git a/core/src/main/java/org/jruby/runtime/callsite/ProfilingCachingCallSite.java b/core/src/main/java/org/jruby/runtime/callsite/ProfilingCachingCallSite.java index 62108c3012a3..5611e7c1b89d 100644 --- a/core/src/main/java/org/jruby/runtime/callsite/ProfilingCachingCallSite.java +++ b/core/src/main/java/org/jruby/runtime/callsite/ProfilingCachingCallSite.java @@ -80,6 +80,7 @@ private void inlineCheck(ThreadContext context, IRubyObject self, CacheEntry cac } } + @Override protected boolean methodMissing(DynamicMethod method, IRubyObject caller) { return method.isUndefined() || (!methodName.equals("method_missing") && !method.isCallableFrom(caller, callType)); } @@ -108,6 +109,21 @@ public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject s } } + @Override + public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject self, int callInfo, IRubyObject... args) { + RubyClass selfType = getClass(self); + CacheEntry cache = this.cache; // This must be retrieved *once* to avoid racing with other threads. + + if (cache.typeOk(selfType)) { + if ((totalMonomorphicCalls.incrementAndGet() % IRManager.IR_INLINER_THRESHOLD) == 0) inlineCheck(context, self, cache); + return cache.method.call(context, self, cache.sourceModule, methodName, callInfo, args); + } else { + totalMonomorphicCalls.set(1); + return cacheAndCall(context, caller, self, selfType, callInfo, args); + } + } + + @Override public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject self, IRubyObject[] args, Block block) { RubyClass selfType = getClass(self); CacheEntry cache = this.cache; // This must be retrieved *once* to avoid racing with other threads. @@ -121,6 +137,20 @@ public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject s } } + @Override + public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject self, int callInfo, Block block, IRubyObject... args) { + RubyClass selfType = getClass(self); + CacheEntry cache = this.cache; // This must be retrieved *once* to avoid racing with other threads. + + if (cache.typeOk(selfType)) { + if ((totalMonomorphicCalls.incrementAndGet() % IRManager.IR_INLINER_THRESHOLD) == 0) inlineCheck(context, self, cache); + return cache.method.call(context, self, cache.sourceModule, methodName, callInfo, block, args); + } else { + totalMonomorphicCalls.set(1); + return cacheAndCall(context, caller, self, selfType, callInfo, block, args); + } + } + @Override public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject self) { RubyClass selfType = getClass(self); @@ -135,6 +165,7 @@ public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject s } } + @Override public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject self, Block block) { RubyClass selfType = getClass(self); // This must be retrieved *once* to avoid racing with other threads. @@ -162,6 +193,7 @@ public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject s } } + @Override public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject self, IRubyObject arg1, Block block) { RubyClass selfType = getClass(self); // This must be retrieved *once* to avoid racing with other threads. @@ -189,6 +221,7 @@ public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject s } } + @Override public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject self, IRubyObject arg1, IRubyObject arg2, Block block) { RubyClass selfType = getClass(self); // This must be retrieved *once* to avoid racing with other threads. @@ -216,6 +249,7 @@ public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject s } } + @Override public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject self, IRubyObject arg1, IRubyObject arg2, IRubyObject arg3, Block block) { RubyClass selfType = getClass(self); // This must be retrieved *once* to avoid racing with other threads. diff --git a/core/src/main/java/org/jruby/runtime/callsite/RefinedCachingCallSite.java b/core/src/main/java/org/jruby/runtime/callsite/RefinedCachingCallSite.java index 7aecfb97dc79..ddbd0f7856f3 100644 --- a/core/src/main/java/org/jruby/runtime/callsite/RefinedCachingCallSite.java +++ b/core/src/main/java/org/jruby/runtime/callsite/RefinedCachingCallSite.java @@ -36,6 +36,20 @@ public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject s return method.call(context, self, entry.sourceModule, methodName, args); } + @Override + public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject self, int callInfo, IRubyObject... args) { + RubyClass selfType = getClass(self); + CacheEntry entry = selfType.searchWithRefinements(methodName, scope); + DynamicMethod method = entry.method; + + if (methodMissing(method, caller)) { + method = Helpers.selectMethodMissing(context, selfType, method.getVisibility(), methodName, callType); + } + + return method.call(context, self, entry.sourceModule, methodName, callInfo, args); + } + + @Override public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject self, IRubyObject[] args, Block block) { RubyClass selfType = getClass(self); CacheEntry entry = selfType.searchWithRefinements(methodName, scope); @@ -48,6 +62,20 @@ public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject s return method.call(context, self, entry.sourceModule, methodName, args, block); } + @Override + public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject self, int callInfo, Block block, IRubyObject[] args) { + RubyClass selfType = getClass(self); + CacheEntry entry = selfType.searchWithRefinements(methodName, scope); + DynamicMethod method = entry.method; + + if (methodMissing(method, caller)) { + method = Helpers.selectMethodMissing(context, selfType, method.getVisibility(), methodName, callType); + } + + return method.call(context, self, entry.sourceModule, methodName, callInfo, block, args); + } + + @Override public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject self) { RubyClass selfType = getClass(self); CacheEntry entry = selfType.searchWithRefinements(methodName, scope); @@ -60,6 +88,7 @@ public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject s return method.call(context, self, entry.sourceModule, methodName); } + @Override public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject self, Block block) { RubyClass selfType = getClass(self); CacheEntry entry = selfType.searchWithRefinements(methodName, scope); @@ -72,6 +101,7 @@ public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject s return method.call(context, self, entry.sourceModule, methodName, block); } + @Override public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject self, IRubyObject arg0) { RubyClass selfType = getClass(self); CacheEntry entry = selfType.searchWithRefinements(methodName, scope); @@ -84,6 +114,7 @@ public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject s return method.call(context, self, entry.sourceModule, methodName, arg0); } + @Override public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject self, IRubyObject arg0, Block block) { RubyClass selfType = getClass(self); CacheEntry entry = selfType.searchWithRefinements(methodName, scope); @@ -96,6 +127,7 @@ public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject s return method.call(context, self, entry.sourceModule, methodName, arg0, block); } + @Override public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject self, IRubyObject arg0, IRubyObject arg1) { RubyClass selfType = getClass(self); CacheEntry entry = selfType.searchWithRefinements(methodName, scope); @@ -108,6 +140,7 @@ public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject s return method.call(context, self, entry.sourceModule, methodName, arg0, arg1); } + @Override public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject self, IRubyObject arg0, IRubyObject arg1, Block block) { RubyClass selfType = getClass(self); CacheEntry entry = selfType.searchWithRefinements(methodName, scope); @@ -120,6 +153,7 @@ public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject s return method.call(context, self, entry.sourceModule, methodName, arg0, arg1, block); } + @Override public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject self, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2) { RubyClass selfType = getClass(self); CacheEntry entry = selfType.searchWithRefinements(methodName, scope); @@ -132,6 +166,7 @@ public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject s return method.call(context, self, entry.sourceModule, methodName, arg0, arg1, arg2); } + @Override public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject self, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, Block block) { RubyClass selfType = getClass(self); CacheEntry entry = selfType.searchWithRefinements(methodName, scope); @@ -144,6 +179,7 @@ public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject s return method.call(context, self, entry.sourceModule, methodName, arg0, arg1, arg2, block); } + @Override protected boolean methodMissing(DynamicMethod method, IRubyObject caller) { // doing full "normal" MM check rather than multiple refined sites by call types return method.isUndefined() || (!methodName.equals("method_missing") && !method.isCallableFrom(caller, callType)); diff --git a/core/src/main/java/org/jruby/runtime/callsite/SuperCallSite.java b/core/src/main/java/org/jruby/runtime/callsite/SuperCallSite.java index a552a20c88f0..13e4ec0fa668 100644 --- a/core/src/main/java/org/jruby/runtime/callsite/SuperCallSite.java +++ b/core/src/main/java/org/jruby/runtime/callsite/SuperCallSite.java @@ -50,6 +50,13 @@ public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject s return call(context, caller, self, klazz, name, args); } + public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject self, int callInfo, IRubyObject... args) { + RubyModule klazz = context.getFrameKlazz(); + String name = context.getFrameName(); + + return call(context, caller, self, klazz, name, callInfo, args); + } + public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject self, RubyModule klazz, String name, IRubyObject... args) { RubyClass selfType = pollAndGetClass(context, self, klazz, name); @@ -57,7 +64,17 @@ public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject s if (selfType != null && myCache.cacheOk(name, selfType)) { return myCache.cache.method.call(context, self, cache.cache.sourceModule, name, args); } - return cacheAndCall(caller, selfType, args, context, self, name); + return cacheAndCall(context, caller, self, selfType, name, args); + } + + public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject self, RubyModule klazz, String name, int callInfo, IRubyObject... args) { + RubyClass selfType = pollAndGetClass(context, self, klazz, name); + + SuperTuple myCache = cache; + if (selfType != null && myCache.cacheOk(name, selfType)) { + return myCache.cache.method.call(context, self, cache.cache.sourceModule, name, callInfo, args); + } + return cacheAndCall(context, caller, self, selfType, name, callInfo, args); } public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject self, IRubyObject[] args, Block block) { @@ -67,6 +84,13 @@ public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject s return call(context, caller, self, klazz, name, args, block); } + public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject self, int callInfo, Block block, IRubyObject... args) { + RubyModule klazz = context.getFrameKlazz(); + String name = context.getFrameName(); + + return call(context, caller, self, klazz, name, callInfo, block, args); + } + public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject self, RubyModule klazz, String name, IRubyObject[] args, Block block) { RubyClass selfType = pollAndGetClass(context, self, klazz, name); @@ -74,7 +98,17 @@ public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject s if (selfType != null && myCache.cacheOk(name, selfType)) { return myCache.cache.method.call(context, self, cache.cache.sourceModule, name, args, block); } - return cacheAndCall(caller, selfType, block, args, context, self, name); + return cacheAndCall(context, caller, self, selfType, name, args, block); + } + + public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject self, RubyModule klazz, String name, int callInfo, Block block, IRubyObject... args) { + RubyClass selfType = pollAndGetClass(context, self, klazz, name); + + SuperTuple myCache = cache; + if (selfType != null && myCache.cacheOk(name, selfType)) { + return myCache.cache.method.call(context, self, cache.cache.sourceModule, name, callInfo, block, args); + } + return cacheAndCall(context, caller, self, selfType, name, callInfo, args, block); } public IRubyObject callIter(ThreadContext context, IRubyObject caller, IRubyObject self, IRubyObject[] args, Block block) { @@ -85,6 +119,14 @@ public IRubyObject callIter(ThreadContext context, IRubyObject caller, IRubyObje } } + public IRubyObject callIter(ThreadContext context, IRubyObject caller, IRubyObject self, int callInfo, Block block, IRubyObject... args) { + try { + return call(context, caller, self, callInfo, block, args); + } finally { + block.escape(); + } + } + public IRubyObject callIter(ThreadContext context, IRubyObject caller, IRubyObject self, RubyModule klazz, String name, IRubyObject[] args, Block block) { try { return call(context, caller, self, klazz, name, args, block); @@ -184,7 +226,7 @@ public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject s if (selfType != null && myCache.cacheOk(name, selfType)) { return myCache.cache.method.call(context, self, cache.cache.sourceModule, name, block); } - return cacheAndCall(caller, selfType, block, context, self, name); + return cacheAndCall(context, caller, self, selfType, name, block); } public IRubyObject callIter(ThreadContext context, IRubyObject caller, IRubyObject self, Block block) { @@ -217,7 +259,7 @@ public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject s if (selfType != null && myCache.cacheOk(name, selfType)) { return myCache.cache.method.call(context, self, cache.cache.sourceModule, name, arg1); } - return cacheAndCall(caller, selfType, context, self, name, arg1); + return cacheAndCall(context, caller, self, selfType, name, arg1); } public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject self, IRubyObject arg1, Block block) { @@ -234,7 +276,7 @@ public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject s if (selfType != null && myCache.cacheOk(name, selfType)) { return myCache.cache.method.call(context, self, cache.cache.sourceModule, name, arg1, block); } - return cacheAndCall(caller, selfType, block, context, self, name, arg1); + return cacheAndCall(context, caller, self, selfType, name, arg1, block); } public IRubyObject callIter(ThreadContext context, IRubyObject caller, IRubyObject self, IRubyObject arg1, Block block) { @@ -267,7 +309,7 @@ public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject s if (selfType != null && myCache.cacheOk(name, selfType)) { return myCache.cache.method.call(context, self, cache.cache.sourceModule, name, arg1, arg2); } - return cacheAndCall(caller, selfType, context, self, name, arg1, arg2); + return cacheAndCall(context, caller, self, selfType, name, arg1, arg2); } public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject self, IRubyObject arg1, IRubyObject arg2, Block block) { @@ -284,7 +326,7 @@ public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject s if (selfType != null && myCache.cacheOk(name, selfType)) { return myCache.cache.method.call(context, self, cache.cache.sourceModule, name, arg1, arg2, block); } - return cacheAndCall(caller, selfType, block, context, self, name, arg1, arg2); + return cacheAndCall(context, caller, self, selfType, name, arg1, block, arg2); } public IRubyObject callIter(ThreadContext context, IRubyObject caller, IRubyObject self, IRubyObject arg1, IRubyObject arg2, Block block) { @@ -317,7 +359,7 @@ public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject s if (selfType != null && myCache.cacheOk(name, selfType)) { return myCache.cache.method.call(context, self, cache.cache.sourceModule, name, arg1, arg2, arg3); } - return cacheAndCall(caller, selfType, context, self, name, arg1, arg2, arg3); + return cacheAndCall(context, caller, self, selfType, name, arg1, arg2, arg3); } public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject self, IRubyObject arg1, IRubyObject arg2, IRubyObject arg3, Block block) { @@ -334,7 +376,7 @@ public IRubyObject call(ThreadContext context, IRubyObject caller, IRubyObject s if (selfType != null && myCache.cacheOk(name, selfType)) { return myCache.cache.method.call(context, self, cache.cache.sourceModule, name, arg1, arg2, arg3, block); } - return cacheAndCall(caller, selfType, block, context, self, name, arg1, arg2, arg3); + return cacheAndCall(context, caller, self, selfType, name, arg1, arg2, arg3, block); } public IRubyObject callIter(ThreadContext context, IRubyObject caller, IRubyObject self, IRubyObject arg1, IRubyObject arg2, IRubyObject arg3, Block block) { @@ -353,7 +395,7 @@ public IRubyObject callIter(ThreadContext context, IRubyObject caller, IRubyObje } } - protected IRubyObject cacheAndCall(IRubyObject caller, RubyClass selfType, Block block, IRubyObject[] args, ThreadContext context, IRubyObject self, String name) { + protected IRubyObject cacheAndCall(ThreadContext context, IRubyObject caller, IRubyObject self, RubyClass selfType, String name, IRubyObject[] args, Block block) { CacheEntry entry = selfType != null ? selfType.searchWithCache(name) : CacheEntry.NULL_CACHE; DynamicMethod method = entry.method; if (methodMissing(method, caller)) { @@ -363,7 +405,17 @@ protected IRubyObject cacheAndCall(IRubyObject caller, RubyClass selfType, Block return method.call(context, self, entry.sourceModule, name, args, block); } - protected IRubyObject cacheAndCall(IRubyObject caller, RubyClass selfType, IRubyObject[] args, ThreadContext context, IRubyObject self, String name) { + protected IRubyObject cacheAndCall(ThreadContext context, IRubyObject caller, IRubyObject self, RubyClass selfType, String name, int callInfo, IRubyObject[] args, Block block) { + CacheEntry entry = selfType != null ? selfType.searchWithCache(name) : CacheEntry.NULL_CACHE; + DynamicMethod method = entry.method; + if (methodMissing(method, caller)) { + return callMethodMissing(context, self, selfType, name, method, callInfo, args, block); + } + cache = new SuperTuple(name, entry); + return method.call(context, self, entry.sourceModule, name, callInfo, block, args); + } + + protected IRubyObject cacheAndCall(ThreadContext context, IRubyObject caller, IRubyObject self, RubyClass selfType, String name, IRubyObject[] args) { CacheEntry entry = selfType != null ? selfType.searchWithCache(name) : CacheEntry.NULL_CACHE; DynamicMethod method = entry.method; if (methodMissing(method, caller)) { @@ -373,6 +425,16 @@ protected IRubyObject cacheAndCall(IRubyObject caller, RubyClass selfType, IRuby return method.call(context, self, entry.sourceModule, name, args); } + protected IRubyObject cacheAndCall(ThreadContext context, IRubyObject caller, IRubyObject self, RubyClass selfType, String name, int callInfo, IRubyObject[] args) { + CacheEntry entry = selfType != null ? selfType.searchWithCache(name) : CacheEntry.NULL_CACHE; + DynamicMethod method = entry.method; + if (methodMissing(method, caller)) { + return callMethodMissing(context, self, selfType, name, method, callInfo, args); + } + cache = new SuperTuple(name, entry); + return method.call(context, self, entry.sourceModule, name, callInfo, args); + } + protected IRubyObject cacheAndCall(IRubyObject caller, RubyClass selfType, ThreadContext context, IRubyObject self, String name) { CacheEntry entry = selfType != null ? selfType.searchWithCache(name) : CacheEntry.NULL_CACHE; DynamicMethod method = entry.method; @@ -383,7 +445,7 @@ protected IRubyObject cacheAndCall(IRubyObject caller, RubyClass selfType, Threa return method.call(context, self, entry.sourceModule, name); } - protected IRubyObject cacheAndCall(IRubyObject caller, RubyClass selfType, Block block, ThreadContext context, IRubyObject self, String name) { + protected IRubyObject cacheAndCall(ThreadContext context, IRubyObject caller, IRubyObject self, RubyClass selfType, String name, Block block) { CacheEntry entry = selfType != null ? selfType.searchWithCache(name) : CacheEntry.NULL_CACHE; DynamicMethod method = entry.method; if (methodMissing(method, caller)) { @@ -393,7 +455,7 @@ protected IRubyObject cacheAndCall(IRubyObject caller, RubyClass selfType, Block return method.call(context, self, entry.sourceModule, name, block); } - protected IRubyObject cacheAndCall(IRubyObject caller, RubyClass selfType, ThreadContext context, IRubyObject self, String name, IRubyObject arg) { + protected IRubyObject cacheAndCall(ThreadContext context, IRubyObject caller, IRubyObject self, RubyClass selfType, String name, IRubyObject arg) { CacheEntry entry = selfType != null ? selfType.searchWithCache(name) : CacheEntry.NULL_CACHE; DynamicMethod method = entry.method; if (methodMissing(method, caller)) { @@ -403,7 +465,7 @@ protected IRubyObject cacheAndCall(IRubyObject caller, RubyClass selfType, Threa return method.call(context, self, entry.sourceModule, name, arg); } - protected IRubyObject cacheAndCall(IRubyObject caller, RubyClass selfType, Block block, ThreadContext context, IRubyObject self, String name, IRubyObject arg) { + protected IRubyObject cacheAndCall(ThreadContext context, IRubyObject caller, IRubyObject self, RubyClass selfType, String name, IRubyObject arg, Block block) { CacheEntry entry = selfType != null ? selfType.searchWithCache(name) : CacheEntry.NULL_CACHE; DynamicMethod method = entry.method; if (methodMissing(method, caller)) { @@ -413,7 +475,7 @@ protected IRubyObject cacheAndCall(IRubyObject caller, RubyClass selfType, Block return method.call(context, self, entry.sourceModule, name, arg, block); } - protected IRubyObject cacheAndCall(IRubyObject caller, RubyClass selfType, ThreadContext context, IRubyObject self, String name, IRubyObject arg1, IRubyObject arg2) { + protected IRubyObject cacheAndCall(ThreadContext context, IRubyObject caller, IRubyObject self, RubyClass selfType, String name, IRubyObject arg1, IRubyObject arg2) { CacheEntry entry = selfType != null ? selfType.searchWithCache(name) : CacheEntry.NULL_CACHE; DynamicMethod method = entry.method; if (methodMissing(method, caller)) { @@ -423,7 +485,7 @@ protected IRubyObject cacheAndCall(IRubyObject caller, RubyClass selfType, Threa return method.call(context, self, entry.sourceModule, name, arg1, arg2); } - protected IRubyObject cacheAndCall(IRubyObject caller, RubyClass selfType, Block block, ThreadContext context, IRubyObject self, String name, IRubyObject arg1, IRubyObject arg2) { + protected IRubyObject cacheAndCall(ThreadContext context, IRubyObject caller, IRubyObject self, RubyClass selfType, String name, IRubyObject arg1, Block block, IRubyObject arg2) { CacheEntry entry = selfType != null ? selfType.searchWithCache(name) : CacheEntry.NULL_CACHE; DynamicMethod method = entry.method; if (methodMissing(method, caller)) { @@ -433,7 +495,7 @@ protected IRubyObject cacheAndCall(IRubyObject caller, RubyClass selfType, Block return method.call(context, self, entry.sourceModule, name, arg1, arg2, block); } - protected IRubyObject cacheAndCall(IRubyObject caller, RubyClass selfType, ThreadContext context, IRubyObject self, String name, IRubyObject arg1, IRubyObject arg2, IRubyObject arg3) { + protected IRubyObject cacheAndCall(ThreadContext context, IRubyObject caller, IRubyObject self, RubyClass selfType, String name, IRubyObject arg1, IRubyObject arg2, IRubyObject arg3) { CacheEntry entry = selfType != null ? selfType.searchWithCache(name) : CacheEntry.NULL_CACHE; DynamicMethod method = entry.method; if (methodMissing(method, caller)) { @@ -443,7 +505,7 @@ protected IRubyObject cacheAndCall(IRubyObject caller, RubyClass selfType, Threa return method.call(context, self, entry.sourceModule, name, arg1, arg2, arg3); } - protected IRubyObject cacheAndCall(IRubyObject caller, RubyClass selfType, Block block, ThreadContext context, IRubyObject self, String name, IRubyObject arg1, IRubyObject arg2, IRubyObject arg3) { + protected IRubyObject cacheAndCall(ThreadContext context, IRubyObject caller, IRubyObject self, RubyClass selfType, String name, IRubyObject arg1, IRubyObject arg2, IRubyObject arg3, Block block) { CacheEntry entry = selfType != null ? selfType.searchWithCache(name) : CacheEntry.NULL_CACHE; DynamicMethod method = entry.method; if (methodMissing(method, caller)) { @@ -457,6 +519,10 @@ protected IRubyObject callMethodMissing(ThreadContext context, IRubyObject self, return Helpers.callMethodMissing(context, self, selfType, method.getVisibility(), name, callType, args, Block.NULL_BLOCK); } + protected IRubyObject callMethodMissing(ThreadContext context, IRubyObject self, RubyClass selfType, String name, DynamicMethod method, int callInfo, IRubyObject[] args) { + return Helpers.callMethodMissing(context, self, selfType, method.getVisibility(), name, callType, callInfo, args, Block.NULL_BLOCK); + } + protected IRubyObject callMethodMissing(ThreadContext context, IRubyObject self, RubyClass selfType, String name, DynamicMethod method) { return Helpers.callMethodMissing(context, self, selfType, method.getVisibility(), name, callType, Block.NULL_BLOCK); } @@ -473,6 +539,10 @@ protected IRubyObject callMethodMissing(ThreadContext context, IRubyObject self, return Helpers.callMethodMissing(context, self, selfType, method.getVisibility(), name, callType, args, block); } + protected IRubyObject callMethodMissing(ThreadContext context, IRubyObject self, RubyClass selfType, String name, DynamicMethod method, int callInfo, IRubyObject[] args, Block block) { + return Helpers.callMethodMissing(context, self, selfType, method.getVisibility(), name, callType, callInfo, args, block); + } + protected IRubyObject callMethodMissing(ThreadContext context, IRubyObject self, RubyClass selfType, String name, DynamicMethod method, IRubyObject arg0, Block block) { return Helpers.callMethodMissing(context, self, selfType, method.getVisibility(), name, callType, arg0, block); }