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 c88f60bce8d..180d3b332f4 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 9675f8779b0..e8682dbe294 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 564226f35dc..588a9f047b4 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 27b685bab14..9ff5f006da6 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 b50ff615993..1c371585a11 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 8a8f7ff64fc..dbdce75992d 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 95e95bea49c..016ba870117 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 29f16c53af5..7f81ddfce40 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 7f5db24ea04..e2c5ad0d3e8 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 22330a9f621..f1e8591cca4 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 308f27d8554..5a7e42e1fa1 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 a081e72ce25..7f52d6aead1 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 @@ -178,6 +178,14 @@ MethodHandle buildGenericHandle(CacheEntry entry) { binder = binder.collect("args", "arg.*", constructObjectArrayHandle(arity)); } + if (arity < 0 || arity > 3) { + // add call info to varargs path because thread-local wrapper logic only added for specific-arity paths + binder = binder.insert(5, "callInfo", flags); + if (signature.argOffset("block") != -1) { + binder = binder.permute("method", "context", "self", "rubyClass", "name", "callInfo", "block", "args"); + } + } + if (Options.INVOKEDYNAMIC_LOG_BINDING.load()) { LOG.info(name() + "\tbound indirectly " + method + ", " + Bootstrap.logMethod(method)); } @@ -652,7 +660,8 @@ public IRubyObject invoke(ThreadContext context, IRubyObject caller, IRubyObject mh = getHandle(self, entry); } - finishBinding(entry, mh, self, selfClass, switchPoint); + boolean needsCallInfo = arity > -1 && arity < 4; + finishBinding(entry, mh, self, selfClass, switchPoint, needsCallInfo); return performIndirectCall(context, self, args, block, methodName, passSymbol, entry); } @@ -675,7 +684,8 @@ public IRubyObject invoke(ThreadContext context, IRubyObject self, IRubyObject[] mh = getHandle(self, entry); } - finishBinding(entry, mh, self, selfClass, switchPoint); + boolean needsCallInfo = arity > -1 && arity < 4; + finishBinding(entry, mh, self, selfClass, switchPoint, needsCallInfo); return performIndirectCall(context, self, args, block, methodName, passSymbol, entry); } @@ -692,21 +702,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); } @@ -715,14 +727,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(); @@ -730,9 +740,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); } } @@ -760,16 +770,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; @@ -785,16 +794,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; @@ -1415,6 +1422,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 */ @@ -1423,7 +1438,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 */ @@ -1432,7 +1446,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 8c0d86001be..3e0e3e29042 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 c2a755d5672..b4150cb0a9c 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 a5e73d02c58..1f3956acaf3 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 09cf32bb4ca..c6423a1cd1c 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,17 @@ 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: + needsCallInfo = false; 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: @@ -110,8 +115,9 @@ public void invoke(String file, int lineNumber, String scopeFieldName, CallBase outgoing = MethodType.methodType(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, arity)); break; default: + needsCallInfo = false; 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 +125,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 +137,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 +157,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 +189,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 +212,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 +226,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 2f379099ba8..6202604e6dd 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 1e99920cceb..e6933e41f19 100644 --- a/core/src/main/java/org/jruby/runtime/Helpers.java +++ b/core/src/main/java/org/jruby/runtime/Helpers.java @@ -118,11 +118,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 42e60c74221..c6c034a8446 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 62108c3012a..5611e7c1b89 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 7aecfb97dc7..ddbd0f7856f 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 a552a20c88f..13e4ec0fa66 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); }