Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: bde8eec605ec
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: ab5fd74a8395
Choose a head ref
  • 3 commits
  • 10 files changed
  • 1 contributor

Commits on Jan 12, 2015

  1. Unverified

    This commit is not signed, but one or more authors requires that any commit attributed to them is signed.
    Copy the full SHA
    a7412cc View commit details
  2. Copy the full SHA
    51b1767 View commit details
  3. Copy the full SHA
    ab5fd74 View commit details
5 changes: 5 additions & 0 deletions core/src/main/java/org/jruby/truffle/nodes/RubyNode.java
Original file line number Diff line number Diff line change
@@ -266,6 +266,11 @@ public void probeLite(TruffleEventReceiver eventReceiver) {
this.replace(wrapper);
}

public boolean isRational(RubyBasicObject o) {
// TODO(CS, 10-Jan-15) should this be a full is_a? test? We'd need a node for that.
return o.getLogicalClass() == getContext().getCoreLibrary().getRationalClass();
}

// Copied from RubyTypesGen

@SuppressWarnings("static-method")
18 changes: 18 additions & 0 deletions core/src/main/java/org/jruby/truffle/nodes/core/BignumNodes.java
Original file line number Diff line number Diff line change
@@ -662,6 +662,24 @@ public int hash(RubyBignum self) {

}

@CoreMethod(names = "to_f")
public abstract static class ToFNode extends CoreMethodNode {

public ToFNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

public ToFNode(ToFNode prev) {
super(prev);
}

@Specialization
public double toF(RubyBignum value) {
return value.doubleValue();
}

}

@CoreMethod(names = {"to_s", "inspect"})
public abstract static class ToSNode extends CoreMethodNode {

138 changes: 125 additions & 13 deletions core/src/main/java/org/jruby/truffle/nodes/core/FixnumNodes.java
Original file line number Diff line number Diff line change
@@ -11,11 +11,13 @@

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.ExactMath;
import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.UnexpectedResultException;
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.api.utilities.BranchProfile;
import com.oracle.truffle.api.utilities.ConditionProfile;
import org.jruby.truffle.nodes.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNode;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNodeFactory;
@@ -162,9 +164,6 @@ public Object add(VirtualFrame frame, long a, RubyBasicObject b) {
return rationalAdd.call(frame, b, "+", null, a);
}

public boolean isRational(RubyBasicObject o) {
return o.getLogicalClass() == getContext().getCoreLibrary().getRationalClass();
}
}

@CoreMethod(names = "-", required = 1)
@@ -313,50 +312,153 @@ public Object mul(long a, RubyBignum b) {

}

@CoreMethod(names = "**", required = 1, lowerFixnumSelf = true, lowerFixnumParameters = 0)
@CoreMethod(names = "**", required = 1)
public abstract static class PowNode extends BignumNodes.BignumCoreMethodNode {

@Child private CallDispatchHeadNode complexConvertNode;
@Child private CallDispatchHeadNode complexPowNode;

@Child private CallDispatchHeadNode rationalConvertNode;
@Child private CallDispatchHeadNode rationalPowNode;

private final ConditionProfile negativeProfile = ConditionProfile.createBinaryProfile();
private final ConditionProfile complexProfile = ConditionProfile.createBinaryProfile();

public PowNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

public PowNode(PowNode prev) {
super(prev);
complexConvertNode = prev.complexConvertNode;
complexPowNode = prev.complexPowNode;
rationalConvertNode = prev.rationalConvertNode;
rationalPowNode = prev.rationalPowNode;
}

@Specialization(guards = "canShiftIntoInt")
public int powTwo(int a, int b) {
return 1 << b;
}

@Specialization(guards = "canShiftIntoInt")
public int powTwo(int a, long b) {
return 1 << b;
}

@Specialization
public Object pow(int a, int b) {
return fixnumOrBignum(bignum(a).pow(b));
return pow(a, (long) b);
}

@Specialization
public double pow(int a, double b) {
return Math.pow(a, b);
public Object pow(int a, long b) {
return pow((long) a, b);
}

@Specialization
public Object pow(VirtualFrame frame, int a, double b) {
return pow(frame, (long) a, b);
}

@Specialization
public Object pow(int a, RubyBignum b) {
return pow((long) a, b);
}

@Specialization(guards = "canShiftIntoLong")
public long powTwo(long a, int b) {
return 1 << b;
}

@Specialization(guards = "canShiftIntoLong")
public long powTwo(long a, long b) {
return 1 << b;
}

@Specialization
public Object pow(long a, int b) {
return pow(a, (long) b);
}

@Specialization
public Object pow(long a, long b) {
if (negativeProfile.profile(b < 0)) {
return Math.pow(a, b);
} else {
return fixnumOrBignum(bignum(a).pow(b));
}
}

@Specialization
public Object pow(VirtualFrame frame, long a, double b) {
if (complexProfile.profile(a < 0 && b != Math.round(b))) {
if (complexConvertNode == null) {
CompilerDirectives.transferToInterpreter();
complexConvertNode = insert(DispatchHeadNodeFactory.createMethodCall(getContext(), true));
complexPowNode = insert(DispatchHeadNodeFactory.createMethodCall(getContext()));
}

final Object aComplex = complexConvertNode.call(frame, getContext().getCoreLibrary().getComplexClass(), "convert", null, a, 0);

return complexPowNode.call(frame, aComplex, "**", null, b);
} else {
return Math.pow(a, b);
}
}

@Specialization
public Object pow(long a, RubyBignum b) {
notDesignedForCompilation();

final RubyBignum bigA = bignum(a);
if (a == 0) {
return 0;
}

if (a == 1) {
return 1;
}

if (a == -1) {
if (b.bigIntegerValue().testBit(0)) {
return -1;
} else {
return 1;
}
}

RubyBignum result = bignum(1);
return Math.pow(a, b.doubleValue());
}

for (RubyBignum n = bignum(0); b.compareTo(n) < 0; n = n.add(bignum(1))) {
result = result.multiply(bigA);
@Specialization(guards = "isRational(arguments[1])")
public Object pow(VirtualFrame frame, Object a, RubyBasicObject b) {
if (rationalConvertNode == null) {
CompilerDirectives.transferToInterpreter();
rationalConvertNode = insert(DispatchHeadNodeFactory.createMethodCall(getContext(), true));
rationalPowNode = insert(DispatchHeadNodeFactory.createMethodCall(getContext()));
}

return result;
final Object aRational = rationalConvertNode.call(frame, getContext().getCoreLibrary().getRationalClass(), "convert", null, a, 1);

return rationalPowNode.call(frame, aRational, "**", null, b);
}

protected static boolean canShiftIntoInt(int a, int b) {
return canShiftIntoInt(a, (long) b);
}

protected static boolean canShiftIntoInt(int a, long b) {
// Highest bit we can set is the 30th due to sign
return a == 2 && b <= 32 - 2;
}

protected static boolean canShiftIntoLong(long a, int b) {
return canShiftIntoLong(a, (long) b);
}

protected static boolean canShiftIntoLong(long a, long b) {
// Highest bit we can set is the 30th due to sign
return a == 2 && b <= 30;
return a == 2 && b <= 64 - 2;
}

}
@@ -661,6 +763,11 @@ public RubyArray divMod(int a, RubyBignum b) {
return divModNode.execute(a, b);
}

@Specialization
public RubyArray divMod(int a, double b) {
return divModNode.execute(a, b);
}

@Specialization
public RubyArray divMod(long a, int b) {
return divModNode.execute(a, b);
@@ -676,6 +783,11 @@ public RubyArray divMod(long a, RubyBignum b) {
return divModNode.execute(a, b);
}

@Specialization
public RubyArray divMod(long a, double b) {
return divModNode.execute(a, b);
}

}

@CoreMethod(names = "<", required = 1, unsupportedOperationBehavior = UnsupportedOperationBehavior.ARGUMENT_ERROR)
56 changes: 54 additions & 2 deletions core/src/main/java/org/jruby/truffle/nodes/core/FloatNodes.java
Original file line number Diff line number Diff line change
@@ -11,8 +11,12 @@

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.api.utilities.BranchProfile;
import com.oracle.truffle.api.utilities.ConditionProfile;
import org.jruby.truffle.nodes.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNodeFactory;
import org.jruby.truffle.runtime.RubyCallStack;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.RaiseException;
@@ -108,12 +112,17 @@ public double sub(double a, RubyBignum b) {
@CoreMethod(names = "*", required = 1)
public abstract static class MulNode extends CoreMethodNode {

@Child private CallDispatchHeadNode rationalConvertNode;
@Child private CallDispatchHeadNode rationalPowNode;

public MulNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

public MulNode(MulNode prev) {
super(prev);
rationalConvertNode = prev.rationalConvertNode;
rationalPowNode = prev.rationalPowNode;
}

@Specialization
@@ -136,17 +145,38 @@ public double mul(double a, RubyBignum b) {
return a * b.doubleValue();
}

@Specialization(guards = "isRational(arguments[1])")
public Object mul(VirtualFrame frame, double a, RubyBasicObject b) {
if (rationalConvertNode == null) {
CompilerDirectives.transferToInterpreter();
rationalConvertNode = insert(DispatchHeadNodeFactory.createMethodCall(getContext(), true));
rationalPowNode = insert(DispatchHeadNodeFactory.createMethodCall(getContext()));
}

final Object aRational = rationalConvertNode.call(frame, getContext().getCoreLibrary().getRationalClass(), "convert", null, a, 1);

return rationalPowNode.call(frame, aRational, "*", null, b);
}

}

@CoreMethod(names = "**", required = 1)
public abstract static class PowNode extends CoreMethodNode {

@Child private CallDispatchHeadNode complexConvertNode;
@Child private CallDispatchHeadNode complexPowNode;

@Child private CallDispatchHeadNode rationalPowNode;

private final ConditionProfile complexProfile = ConditionProfile.createBinaryProfile();

public PowNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

public PowNode(PowNode prev) {
super(prev);
rationalPowNode = prev.rationalPowNode;
}

@Specialization
@@ -160,15 +190,37 @@ public double pow(double a, long b) {
}

@Specialization
public double pow(double a, double b) {
return Math.pow(a, b);
public Object pow(VirtualFrame frame, double a, double b) {
if (complexProfile.profile(a < 0 && b != Math.round(b))) {
if (complexConvertNode == null) {
CompilerDirectives.transferToInterpreter();
complexConvertNode = insert(DispatchHeadNodeFactory.createMethodCall(getContext(), true));
complexPowNode = insert(DispatchHeadNodeFactory.createMethodCall(getContext()));
}

final Object aComplex = complexConvertNode.call(frame, getContext().getCoreLibrary().getComplexClass(), "convert", null, a, 0);

return complexPowNode.call(frame, aComplex, "**", null, b);
} else {
return Math.pow(a, b);
}
}

@Specialization
public double pow(double a, RubyBignum b) {
return Math.pow(a, b.doubleValue());
}

@Specialization(guards = "isRational(arguments[1])")
public Object pow(VirtualFrame frame, double a, RubyBasicObject b) {
if (rationalPowNode == null) {
CompilerDirectives.transferToInterpreter();
rationalPowNode = insert(DispatchHeadNodeFactory.createMethodCall(getContext(), true));
}

return rationalPowNode.call(frame, a, "pow_rational", null, b);
}

}

@CoreMethod(names = {"/", "__slash__"}, required = 1)
Loading