Skip to content

Commit

Permalink
Use a SwitchPoint for Fixnum/Float reopening, FOR MORE SPEED.
Browse files Browse the repository at this point in the history
  • Loading branch information
headius committed Dec 6, 2012
1 parent 82f1222 commit 5049a0f
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 27 deletions.
39 changes: 29 additions & 10 deletions src/org/jruby/Ruby.java
Original file line number Diff line number Diff line change
Expand Up @@ -4234,31 +4234,47 @@ public int getCallerCount() {
}

/**
* Whether the Fixnum class has been reopened and modified
* Mark Fixnum as reopened
*/
public void reopenFixnum() {
fixnumInvalidator.invalidate();
fixnumReopened = true;
}

/**
* Retrieve the invalidator for Fixnum reopening
*/
public Invalidator getFixnumInvalidator() {
return fixnumInvalidator;
}

/**
* Whether the Float class has been reopened and modified
*/
public boolean isFixnumReopened() {
return fixnumReopened;
}

/**
* Set whether the Fixnum class has been reopened and modified
* Mark Float as reopened
*/
public void setFixnumReopened(boolean fixnumReopened) {
this.fixnumReopened = fixnumReopened;
public void reopenFloat() {
floatInvalidator.invalidate();
floatReopened = true;
}

/**
* Whether the Float class has been reopened and modified
* Retrieve the invalidator for Float reopening
*/
public boolean isFloatReopened() {
return floatReopened;
public Invalidator getFloatInvalidator() {
return floatInvalidator;
}

/**
* Set whether the Float class has been reopened and modified
* Whether the Float class has been reopened and modified
*/
public void setFloatReopened(boolean floatReopened) {
this.floatReopened = floatReopened;
public boolean isFloatReopened() {
return floatReopened;
}

public boolean isBooting() {
Expand Down Expand Up @@ -4522,6 +4538,9 @@ public void secure(int level) {
// Count of built-in warning backtraces generated by code running in this runtime
private final AtomicInteger warningCount = new AtomicInteger();

private Invalidator
fixnumInvalidator = OptoFactory.newConstantInvalidator(),
floatInvalidator = OptoFactory.newConstantInvalidator();
private boolean fixnumReopened, floatReopened;

private volatile boolean booting = true;
Expand Down
4 changes: 2 additions & 2 deletions src/org/jruby/RubyModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -1117,9 +1117,9 @@ public void invalidateCacheDescendants() {
protected void invalidateCoreClasses() {
if (!getRuntime().isBooting()) {
if (this == getRuntime().getFixnum()) {
getRuntime().setFixnumReopened(true);
getRuntime().reopenFixnum();
} else if (this == getRuntime().getFloat()) {
getRuntime().setFloatReopened(true);
getRuntime().reopenFloat();
}
}
}
Expand Down
56 changes: 41 additions & 15 deletions src/org/jruby/runtime/invokedynamic/MathLinker.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import org.jruby.runtime.MethodIndex;
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
import java.lang.invoke.SwitchPoint;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.callsite.CacheEntry;
Expand Down Expand Up @@ -115,13 +116,21 @@ public static IRubyObject fixnumOperator(ThreadContext context, IRubyObject call
methodType(IRubyObject.class, ThreadContext.class, IRubyObject.class, IRubyObject.class, JRubyCallSite.class, RubyFixnum.class));
fallback = insertArguments(fallback, 3, site, context.runtime.newFixnum(value));

MethodHandle test = lookup().findStatic(MathLinker.class, "fixnumTest", methodType(boolean.class, Ruby.class, IRubyObject.class));
test = test.bindTo(context.runtime);
MethodHandle test = lookup().findStatic(MathLinker.class, "fixnumTest", methodType(boolean.class, IRubyObject.class));
test = permuteArguments(test, methodType(boolean.class, ThreadContext.class, IRubyObject.class, IRubyObject.class), new int[] {2});

if (RubyInstanceConfig.LOG_INDY_BINDINGS) LOG.info(name + "\tFixnum operation at site #" + site.siteID() + " (" + site.file() + ":" + site.line() + ") bound directly");
site.setTarget(guardWithTest(test, target, fallback));
return (IRubyObject)site.getTarget().invokeWithArguments(context, caller, self);

// confirm it's a Fixnum
target = guardWithTest(test, target, fallback);

// check Fixnum reopening
target = ((SwitchPoint)context.runtime.getFixnumInvalidator().getData())
.guardWithTest(target, fallback);

site.setTarget(target);

return (IRubyObject)target.invokeWithArguments(context, caller, self);
}

public static boolean fixnumBoolean(ThreadContext context, IRubyObject caller, IRubyObject self, JRubyCallSite site, long value) throws Throwable {
Expand All @@ -141,17 +150,25 @@ public static boolean fixnumBoolean(ThreadContext context, IRubyObject caller, I
methodType(boolean.class, ThreadContext.class, IRubyObject.class, IRubyObject.class, JRubyCallSite.class, RubyFixnum.class));
fallback = insertArguments(fallback, 3, site, context.runtime.newFixnum(value));

MethodHandle test = lookup().findStatic(MathLinker.class, "fixnumTest", methodType(boolean.class, Ruby.class, IRubyObject.class));
test = test.bindTo(context.runtime);
MethodHandle test = lookup().findStatic(MathLinker.class, "fixnumTest", methodType(boolean.class, IRubyObject.class));
test = permuteArguments(test, methodType(boolean.class, ThreadContext.class, IRubyObject.class, IRubyObject.class), new int[] {2});

if (RubyInstanceConfig.LOG_INDY_BINDINGS) LOG.info(name + "\tFixnum boolean operation at site #" + site.siteID() + " (" + site.file() + ":" + site.line() + ") bound directly");
site.setTarget(guardWithTest(test, target, fallback));
return (Boolean)site.getTarget().invokeWithArguments(context, caller, self);

// confirm it's a Fixnum
target = guardWithTest(test, target, fallback);

// check Fixnum reopening
target = ((SwitchPoint)context.runtime.getFixnumInvalidator().getData())
.guardWithTest(target, fallback);

site.setTarget(target);

return (Boolean)target.invokeWithArguments(context, caller, self);
}

public static boolean fixnumTest(Ruby runtime, IRubyObject self) {
return self instanceof RubyFixnum && !runtime.isFixnumReopened();
public static boolean fixnumTest(IRubyObject self) {
return self instanceof RubyFixnum;
}

public static IRubyObject fixnumOperatorFail(ThreadContext context, IRubyObject caller, IRubyObject self, JRubyCallSite site, RubyFixnum value) throws Throwable {
Expand Down Expand Up @@ -284,17 +301,26 @@ public static IRubyObject floatOperator(ThreadContext context, IRubyObject calle
methodType(IRubyObject.class, ThreadContext.class, IRubyObject.class, IRubyObject.class, JRubyCallSite.class, RubyFloat.class));
fallback = insertArguments(fallback, 3, site, context.runtime.newFloat(value));

MethodHandle test = lookup().findStatic(MathLinker.class, "floatTest", methodType(boolean.class, Ruby.class, IRubyObject.class));
test = test.bindTo(context.runtime);
MethodHandle test = lookup().findStatic(MathLinker.class, "floatTest", methodType(boolean.class, IRubyObject.class));
test = permuteArguments(test, methodType(boolean.class, ThreadContext.class, IRubyObject.class, IRubyObject.class), new int[] {2});

if (RubyInstanceConfig.LOG_INDY_BINDINGS) LOG.info(name + "\tFloat operation at site #" + site.siteID() + " (" + site.file() + ":" + site.line() + ") bound directly");
site.setTarget(guardWithTest(test, target, fallback));
return (IRubyObject)site.getTarget().invokeWithArguments(context, caller, self);

// confirm it's a Float
target = guardWithTest(test, target, fallback);

// check Float reopening
target = ((SwitchPoint)context.runtime.getFloatInvalidator().getData())
.guardWithTest(target, fallback);

site.setTarget(target);

return (IRubyObject)target.invokeWithArguments(context, caller, self);
}

public static boolean floatTest(Ruby runtime, IRubyObject self) {
return self instanceof RubyFloat && !runtime.isFloatReopened();
public static boolean floatTest(IRubyObject self) {
return self instanceof RubyFloat;
}

public static IRubyObject floatOperatorFail(ThreadContext context, IRubyObject caller, IRubyObject self, JRubyCallSite site, RubyFloat value) throws Throwable {
Expand Down

0 comments on commit 5049a0f

Please sign in to comment.