Skip to content

Instantly share code, notes, and snippets.

@headius
Last active January 2, 2016 21:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save headius/8361960 to your computer and use it in GitHub Desktop.
Save headius/8361960 to your computer and use it in GitHub Desktop.
BEFORE interpreted:
user system total real
control, 1 and :to_ary 0.070000 0.000000 0.070000 ( 0.068000)
1m 1.respond_to?(:to_ary) 0.130000 0.000000 0.130000 ( 0.126000)
1m 1.respond_to?(:to_ary,true) 0.120000 0.000000 0.120000 ( 0.122000)
1m 1.respond_to?(:next) 0.100000 0.000000 0.100000 ( 0.093000)
1m redefined obj.respond_to? 0.130000 0.000000 0.130000 ( 0.135000)
1m varying name respond_to? 0.280000 0.010000 0.290000 ( 0.272000)
BEFORE compiled:
user system total real
control, 1 and :to_ary 0.040000 0.000000 0.040000 ( 0.037000)
1m 1.respond_to?(:to_ary) 0.110000 0.000000 0.110000 ( 0.108000)
1m 1.respond_to?(:to_ary,true) 0.110000 0.000000 0.110000 ( 0.109000)
1m 1.respond_to?(:next) 0.070000 0.000000 0.070000 ( 0.072000)
1m redefined obj.respond_to? 0.060000 0.000000 0.060000 ( 0.059000)
1m varying name respond_to? 0.060000 0.000000 0.060000 ( 0.059000)
AFTER interpreted:
user system total real
control, 1 and :to_ary 0.070000 0.000000 0.070000 ( 0.069000)
1m 1.respond_to?(:to_ary) 0.060000 0.000000 0.060000 ( 0.063000)
1m 1.respond_to?(:to_ary,true) 0.070000 0.000000 0.070000 ( 0.061000)
1m 1.respond_to?(:next) 0.060000 0.000000 0.060000 ( 0.065000)
1m redefined obj.respond_to? 0.130000 0.000000 0.130000 ( 0.131000)
1m varying name respond_to? 0.250000 0.000000 0.250000 ( 0.250000)
AFTER compiled:
user system total real
control, 1 and :to_ary 0.040000 0.000000 0.040000 ( 0.035000)
1m 1.respond_to?(:to_ary) 0.050000 0.000000 0.050000 ( 0.050000)
1m 1.respond_to?(:to_ary,true) 0.050000 0.000000 0.050000 ( 0.050000)
1m 1.respond_to?(:next) 0.050000 0.000000 0.050000 ( 0.045000)
1m redefined obj.respond_to? 0.060000 0.000000 0.060000 ( 0.063000)
1m varying name respond_to? 0.070000 0.000000 0.070000 ( 0.071000)
1m varying name respond_to? 0.060000 0.000000 0.060000 ( 0.058000)
diff --git a/core/src/main/java/org/jruby/Ruby.java b/core/src/main/java/org/jruby/Ruby.java
index f780f2c..3f5a16b 100644
--- a/core/src/main/java/org/jruby/Ruby.java
+++ b/core/src/main/java/org/jruby/Ruby.java
@@ -1849,6 +1849,14 @@ public final class Ruby {
public void setRespondToMethod(DynamicMethod rtm) {
this.respondTo = rtm;
}
+
+ public DynamicMethod getRespondToMissingMethod() {
+ return respondToMissing;
+ }
+
+ public void setRespondToMissingMethod(DynamicMethod rtmm) {
+ this.respondToMissing = rtmm;
+ }
public RubyClass getDummy() {
return dummyClass;
@@ -4695,7 +4703,7 @@ public final class Ruby {
procSysModule, precisionModule, errnoModule;
private DynamicMethod privateMethodMissing, protectedMethodMissing, variableMethodMissing,
- superMethodMissing, normalMethodMissing, defaultMethodMissing, respondTo;
+ superMethodMissing, normalMethodMissing, defaultMethodMissing, respondTo, respondToMissing;
// record separator var, to speed up io ops that use it
private GlobalVariable recordSeparatorVar;
diff --git a/core/src/main/java/org/jruby/RubyKernel.java b/core/src/main/java/org/jruby/RubyKernel.java
index 31bf0b8..0c4f15b 100644
--- a/core/src/main/java/org/jruby/RubyKernel.java
+++ b/core/src/main/java/org/jruby/RubyKernel.java
@@ -164,6 +164,7 @@ public class RubyKernel {
RubyModule module = runtime.getKernel();
runtime.setRespondToMethod(module.searchMethod("respond_to?"));
+ runtime.setRespondToMissingMethod(module.searchMethod("respond_to_missing?"));
}
@JRubyMethod(module = true, visibility = PRIVATE)
diff --git a/core/src/main/java/org/jruby/compiler/impl/InvokeDynamicInvocationCompiler.java b/core/src/main/java/org/jruby/compiler/impl/InvokeDynamicInvocationCompiler.java
index 15f0bd9..51762ba 100644
--- a/core/src/main/java/org/jruby/compiler/impl/InvokeDynamicInvocationCompiler.java
+++ b/core/src/main/java/org/jruby/compiler/impl/InvokeDynamicInvocationCompiler.java
@@ -98,10 +98,17 @@ public class InvokeDynamicInvocationCompiler extends StandardInvocationCompiler
@Override
public void invokeDynamic(String name, CompilerCallback receiverCallback, ArgumentsCallback argsCallback, CallType callType, CompilerCallback closureArg, boolean iterator) {
+ // super calls do not optimize in indy right now
if (callType == CallType.SUPER) {
super.invokeDynamic(name, receiverCallback, argsCallback, callType, closureArg, iterator);
return;
}
+
+ // respond_to? calls do not optimize in indy right now
+ if (name.equals("respond_to?")) {
+ super.invokeDynamic(name, receiverCallback, argsCallback, callType, closureArg, iterator);
+ return;
+ }
methodCompiler.loadThreadContext(); // [adapter, tc]
diff --git a/core/src/main/java/org/jruby/runtime/callsite/RespondToCallSite.java b/core/src/main/java/org/jruby/runtime/callsite/RespondToCallSite.java
index 202a6ac..ba61e75 100644
--- a/core/src/main/java/org/jruby/runtime/callsite/RespondToCallSite.java
+++ b/core/src/main/java/org/jruby/runtime/callsite/RespondToCallSite.java
@@ -68,13 +68,16 @@ public class RespondToCallSite extends NormalCachingCallSite {
}
// alternate logic to cache the result of respond_to if it's the standard one
- // FIXME: 1.9's respond_to_missing breaks this, so we have to bail out
- if (false &&
- entry.method.equals(context.runtime.getRespondToMethod())) {
+ if (entry.method.equals(context.runtime.getRespondToMethod())) {
String name = arg.asJavaString();
RespondToTuple tuple = recacheRespondsTo(entry, name, selfType, true, context);
- respondToTuple = tuple;
- return tuple.respondsTo;
+
+ // only cache if it does respond_to? or there's no custom respond_to_missing? logic
+ if (tuple.respondsTo.isTrue() ||
+ selfType.searchWithCache("respond_to_missing?").method == context.runtime.getRespondToMissingMethod()) {
+ respondToTuple = tuple;
+ return tuple.respondsTo;
+ }
}
// normal logic if it's not the builtin respond_to? method
@@ -91,14 +94,16 @@ public class RespondToCallSite extends NormalCachingCallSite {
}
// alternate logic to cache the result of respond_to if it's the standard one
- // FIXME: 1.9's respond_to_missing breaks this, so we have to bail out
- // FIXME: 1.9's respond_to_missing breaks this, so we have to bail out
- if (false &&
- entry.method.equals(context.runtime.getRespondToMethod())) {
+ if (entry.method.equals(context.runtime.getRespondToMethod())) {
String name = arg0.asJavaString();
RespondToTuple tuple = recacheRespondsTo(entry, name, selfType, !arg1.isTrue(), context);
- respondToTuple = tuple;
- return tuple.respondsTo;
+
+ // only cache if it does respond_to? or there's no custom respond_to_missing? logic
+ if (tuple.respondsTo.isTrue() ||
+ selfType.searchWithCache("respond_to_missing?").method == context.runtime.getRespondToMissingMethod()) {
+ respondToTuple = tuple;
+ return tuple.respondsTo;
+ }
}
// normal logic if it's not the builtin respond_to? method
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment