Permalink
Browse files

[indy] Variable accessor chaining

Do MH chaining in ivar invocation for VariableSite as same as method
invocation for JRubyCallSite.  Make it rebind when chain length is
greater than invokedynamic.maxpoly option.
  • Loading branch information...
1 parent 0a70821 commit 9e96e11ae577ba80822ec3434d5a71bd2c3cf7ae @nahi nahi committed Mar 31, 2012
Showing with 36 additions and 6 deletions.
  1. +36 −6 src/org/jruby/runtime/invokedynamic/InvokeDynamicSupport.java
@@ -36,7 +36,6 @@
import java.math.BigInteger;
import org.jcodings.Encoding;
import org.jcodings.EncodingDB;
-import org.jruby.Ruby;
import org.jruby.RubyClass;
import org.jruby.RubyEncoding;
import org.jruby.RubyFixnum;
@@ -59,7 +58,6 @@
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.callsite.CacheEntry;
import org.jruby.util.ByteList;
-import org.jruby.util.JavaNameMangler;
import org.jruby.util.RegexpOptions;
import static org.jruby.util.CodegenUtils.*;
@@ -385,9 +383,23 @@ public static CallSite getBlockBody19Bootstrap(Lookup lookup, String name, Metho
public static class VariableSite extends MutableCallSite {
public final String name;
+ private int chainCount;
public VariableSite(MethodType type, String name) {
super(type);
this.name = name;
+ this.chainCount = 0;
+ }
+
+ public synchronized int chainCount() {
+ return chainCount;
+ }
+
+ public synchronized void incrementChainCount() {
+ chainCount += 1;
+ }
+
+ public synchronized void clearChainCount() {
+ chainCount = 0;
}
}
@@ -426,8 +438,17 @@ public static IRubyObject getVariableFallback(VariableSite site, IRubyObject sel
getValue = filterReturnValue(getValue, nullToNil);
// prepare fallback
- MethodHandle fallback = findStatic(InvokeDynamicSupport.class, "getVariableFallback", methodType(IRubyObject.class, VariableSite.class, IRubyObject.class));
- fallback = fallback.bindTo(site);
+ MethodHandle fallback = null;
+ if (site.getTarget() == null || site.chainCount() > RubyInstanceConfig.MAX_POLY_COUNT) {
+ if (RubyInstanceConfig.LOG_INDY_BINDINGS) LOG.info(site.name + "\tget triggered site rebind " + self.getMetaClass().id);
+ fallback = findStatic(InvokeDynamicSupport.class, "getVariableFallback", methodType(IRubyObject.class, VariableSite.class, IRubyObject.class));
+ fallback = fallback.bindTo(site);
+ site.clearChainCount();
+ } else {
+ if (RubyInstanceConfig.LOG_INDY_BINDINGS) LOG.info(site.name + "\tget added to PIC " + self.getMetaClass().id);
+ fallback = site.getTarget();
+ site.incrementChainCount();
+ }
// prepare test
MethodHandle test = findStatic(InvocationLinker.class, "testRealClass", methodType(boolean.class, RubyClass.class, IRubyObject.class));
@@ -455,8 +476,17 @@ public static IRubyObject setVariableFallback(VariableSite site, IRubyObject sel
setValue = foldArguments(returnValue, setValue);
// prepare fallback
- MethodHandle fallback = findStatic(InvokeDynamicSupport.class, "setVariableFallback", methodType(IRubyObject.class, VariableSite.class, IRubyObject.class, IRubyObject.class));
- fallback = fallback.bindTo(site);
+ MethodHandle fallback = null;
+ if (site.getTarget() == null || site.chainCount() > RubyInstanceConfig.MAX_POLY_COUNT) {
+ if (RubyInstanceConfig.LOG_INDY_BINDINGS) LOG.info(site.name + "\tset triggered site rebind " + self.getMetaClass().id);
+ fallback = findStatic(InvokeDynamicSupport.class, "setVariableFallback", methodType(IRubyObject.class, VariableSite.class, IRubyObject.class, IRubyObject.class));
+ fallback = fallback.bindTo(site);
+ site.clearChainCount();
+ } else {
+ if (RubyInstanceConfig.LOG_INDY_BINDINGS) LOG.info(site.name + "\tset added to PIC " + self.getMetaClass().id);
+ fallback = site.getTarget();
+ site.incrementChainCount();
+ }
// prepare test
MethodHandle test = findStatic(InvocationLinker.class, "testRealClass", methodType(boolean.class, RubyClass.class, IRubyObject.class));

0 comments on commit 9e96e11

Please sign in to comment.